2014年10月29日,W3C泪流满面地宣布,经过几乎8年的艰辛努力,HTML5标准规范终于最终制定完成了,并已公开发布。
HTML5的正式发布,可谓大快人心,是否今后各浏览器就能统一标准呢?还得拭目以待。
说到HTML5,首先会想到canvas,但在我们项目中,考虑到兼容性和上线时间,并没有使用HTML5的canvas。关于HTML5,我们用了其中的viewport
技术。
手机浏览器是把页面放在一个虚拟的“窗口”(viewport
)中,通常这个虚拟的“窗口”(viewport
)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的网页的布局),用户可以通过平移和缩放来看网页的不同部分,如下图:
在我们项目中,为了使得页面自适应各种分辨率的手机尺寸,我们将viewport的大小等于手机屏幕大小,初始比例设为1,并且禁止用户手动缩放。
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, user-scalable=no">
zepto.js
,我们仅需要它进行DOM的操作,相较于jQuery Mobile,它体积更小,完全满足我们的需要,这就够了。而它的用法,和jQuery几乎一样,使用起来感觉不到差别。touch.js
,zepto的一个组件,用于支持触屏操作,仅6K。CSS3是我们这个页面的核心,所有的动画效果都是由它完成。而CSS3动画的精髓,无外乎这三个属性:变形(transform
)、转换(transition
)和动画(animation
)。
更多关于CSS3的基础知识,可以前往CSS3 Introduction。
在本项目中,有一些动画效果比较通用,主要是一些基本的平移、旋转、缩放等我们将这些通用的动画提取成了一个css库,叫做NEC,我们一起来看一下:
.nec-ani-fadeIn
.nec-ani-fadeOut
.nec-ani-moveFromLeft
.nec-ani-moveFromRight
.nec-ani-moveFromTop
.nec-ani-moveFromBottom
.nec-ani-moveToLeft
.nec-ani-moveToRight
.nec-ani-moveToTop
.nec-ani-moveToBottom
.nec-ani-moveFromLeftFade
.nec-ani-moveFromRightFade
.nec-ani-moveFromTopFade
.nec-ani-moveFromBottomFade
.nec-ani-moveToLeftFade
.nec-ani-moveToRightFade
.nec-ani-moveToTopFade
.nec-ani-moveToBottomFade
.nec-ani-moveUpDownSpring
.nec-ani-moveLeftRightSpring
.nec-ani-rotateLeft
.nec-ani-rotateRight
.nec-ani-scaleUpCenter
.nec-ani-scaleDownCenter
.nec-ani-scaleDown
.nec-ani-scaleUp
很酷,对不对?其实实现起来很简单,只需要在眼镜的玻璃上放一个圆形的div
,div
的背景图片选择一张包含很长的数字流的图片,然后通过css3
控制background-position-y
进行变化。
@keyframes matrixGlass {
0% { background-position-y: 0%;}
100% { background-position-y: -500%;}
}
这个动画也被加入NEC中了,只需要为你的需要飘落的元素上加上.nec-ani-flagWave
这个类就可以了。
具体实现原理如下:
@keyframes flagWave {
0% { opacity: 0; transform: translate(-250%, -500%) rotate(30deg);}
5% { opacity: 1; transform: translate(-225%, -450%) rotate(28deg);}
50% { opacity: 1; transform: translate(0%, 0%) rotate(0);}
95% { opacity: 1; transform: translate(225%, 450%) rotate(-115deg);}
100% { opacity: 0; transform: translate(250%, 500%) rotate(-120deg);}
}
.nec-ani-tagFloatingLeft
.nec-ani-tagFloatingRight
.nec-ani-bubble
有一个摩托车从天而降,然后嗖的一下开走的小动画,很炫,那么它是怎么实现的呢?其实很简单,我们先来看一下分解动作:
首先在旋转-30度透明度为零的情况下,从天而降,下降到地面,并且下降的同时将透明度渐变到1,然后后轮着地时,开始做旋转的动作,将角度转到0,紧接着再做向右平移的动作,代码如下:
@keyframes autobike {
0% { opacity: 0; transform: translateY(-400%) rotate(-30deg);}
30% { opacity: 1; transform: translateY(-30%) rotate(-30deg);}
60% { opacity: 1; transform: translateY(0%) rotate(0deg);}
100% { opacity: 1; transform: translateY(500%) rotate(0deg);}
}
在自适应屏幕尺寸方面,我们花了不少努力。我们主要通过下面4个方面来控制在各种屏幕上显示效果的一致性:
我们以图片的宽度百分比来控制图片的大小,这样可以保证图片在不同尺寸的屏幕下,其图片宽度总是不会超过屏幕,并且他们之前的相对大小一致。
绝对布局是为了后面以屏幕中心为基准,进行位置的调整。通常的绝对布局是通过left
和top
来进行定位,但是这样定位有一个问题:由于我们所有单位都是基于百分比的,而且left
的百分比是基于屏幕宽度,而top
的百分比是基于屏幕高度度,如果单纯使用left
和top
来定位,当屏幕尺寸不成等比变化时,各元素的left
和top
位移的比例不一样,导致各个元素之间的相对位置发生了改变,对于我们这个项目来说,这是不能允许的,例如第二幅动画里的地球自转,他和周围的建筑物之间的相对位置必须保持一致,否则显示效果就会很差。于是我们采用设置left
和top
都为50%
,然后通过margin-left
和margin-top
来进行位置调整,根据W3C的规范,当margin
的单位为百分比时,他们都是基于宽度来进行计算的,也就是说当屏幕尺寸变化时,我们margin-left
和margin-top
的量只取决于宽度的变化,这样各元素的相对位置就保持一致了。
这样还有一个问题,当屏幕宽度不变,高度变得很低,甚至低于宽度的时候,也就是说用户横屏了,这时候整个页面虽然宽度没问题,高度也是居中的,但是人物头和脚会看不见,因为根据之前的理论,我们并没有对其进行高度的限制,仅根据宽度进行缩放。这时候,我们需要借助js,将整个wrap进行scale缩放。
我们发现,我们显示效果最优的屏幕比例是0.63,而当屏幕比例大于0.65时,会开始出现顶部和底部留的空白太少的问题,影响美观,当这个比例再大的时候,就会出现顶部或底部显示不全的问题,因此当宽高比大于0.65时,我们进行处理,将整个wrap缩小,缩小的比例为0.63/屏幕宽高比
,为什么是这个值?大家可以自行画图理解。大家可以看下面三个图:
第一张,是正常的显示情况,第二张是没有进行缩放的显示情况,第三张是经过我们整体缩放之后的显示效果。可以看到,经过这样处理后,任何屏幕比例,我们都能较完美的显示出来。
说到浏览器的兼容性,其实经过测试,几乎目前所有智能手机的系统自带浏览器的显示效果都很不错,然而,在他们的微信上,显示效果却常常会有问题,主要是位置上的问题,元素之间的相对位置发生了变化,这不符合我们之前所做的努力。这一点,我们做了一些研究,结果发现和Webkit的内核版本号有关。先给出一些测试数据,见下表(均为Android机器,微信版本都是6.0版):
浏览器 | 显示效果 | Webkit版本 |
---|---|---|
A手机-微信 | Good | AppleWebkit/537.36 |
A手机-Chrome | Good | AppleWebkit/537.36 |
A手机-自带 | Good | AppleWebkit/537.36 |
A手机-百度6.0 | Good | AppleWebkit/537.36 |
A手机-搜狗 | Bad | AppleWebkit/534.30 |
B手机-微信 | Bad | AppleWebkit/534.30 |
B手机-UC | Bad | AppleWebkit/533.1 |
B手机-自带 | Good | AppleWebkit/537.36 |
从上面的表中,可以得出两个结论:
好,我们先来解决第一个问题。
首先经过分析,我们发现,在534.39等不正常的webkit版本上,问题出在margin-top
上,根据W3C的规范,margin-top
值为百分比时,应当按照容器宽度作为基础,而在这些webkit版本中,却是以高度作为基础的。经过仔细搜寻,终于找到了这个bug,Webkit在2012年12月13日变更集137695中已经修复了这个bug。
下面问题来了,到底是低于哪个版本的webkit有这个bug呢?我们并没有能够找到webkit发布的history,只找到了safari的发布历史。通过safari的发布历史,我们基本可以确定,当webkit版本号小于536.28时,均存在这个bug。
下面我们来看第二个问题。
既然微信里的内置浏览器并没有自带内核,那他就应该是使用了系统中安装的某个浏览器的内核。
基于这个猜想,我们在A机器上又安装了各种浏览器,当我们安装了QQ浏览器之后,问题来了!QQ浏览器和A手机上的微信都挂了!显示效果都出了问题!
下面是A手机中安装了QQ浏览器之后的数据:
浏览器 | 显示效果 | Webkit版本 |
---|---|---|
A手机-微信 | Bad | AppleWebkit/533.1 |
A手机-QQ浏览器 | Bad | AppleWebkit/537.36 |
大家注意看上面的表格,QQ浏览器里的webkit内核版本号显示的是537.36,而他却并没有修复旧版的bug,而且在安装了它之后,微信就不行了,而微信里面显示的webkit内核却是533.1。这是咋回事?
其实,QQ浏览器是使用的自家基于webkit修改过的内核,号称X5内核,而他们的UA版本号却是伪造的537.36,其真实的webkit内核版本其实是533.1,关于这一点,强烈谴责一下腾讯,你说你基于两年前的533.1也就罢了,干嘛还要伪装成最新的呢?坑!是在太坑!
一开始,我们一直以为我们可以通过微信企业号来进行发布,因为微信企业号发布的消息,是可以手动添加封面的。后来直到上线那天才发现,我们NESC的微信账号是服务号,不是企业号。我们只能直接通过链接自己分享到朋友圈、发给好友。那么问题又来了,如何控制微信链接前面的缩略图呢?
微信链接的缩略图的选择,官方并没有进行说明,通过研究,我们发现,微信会选择页面中第一张display
不为none
,并且分辨率大于400px*400px
的图片作为缩略图,那就简单了,将制作好的一张分辨率为450px*450px
的缩略图放在页面比较靠前的位置,并且加上style="width:0; height:0; position:absolute;"
即可。