简单的转盘抽奖——CSS动画优化
前言
前两天去一家公司面试,被问到一些小游戏的东西。面试官提到了刷红包还有抽奖这些怎么实现,当时简单说了下思路,回来之后想想还是说的太轻描淡写了,干说不做就是耍流氓,所以就做了一个(Demo & 源码)。启动方式:手指在转盘上滑动,转盘转动。这里没有像一般的抽奖程序一样在后台指定抽奖结果,结果完全由你的手速决定的(老板哭了。。。)
界面
界面很简单,网上搜个图片或者直接搜个 demo 就有了,当然自适应也是必须的。这里用了 Rem 来实现自适应,所有尺寸单位均用 rem,改变 html 节点的 font-size 即可实现全屏缩放,这里设置的是当屏幕宽度小于420px的时候转盘尺寸与屏宽城正比,当屏宽大于420px的时候转盘尺寸固定。更多关于rem实现自适应的内容,可以看看这里:Here。
动效与交互
网上看到的demo大多数是点击启动的,就想着换个交互方式,用触屏滑动的方式启动。这里很容易就能想到以滑屏速度转动转盘,转动时给一个负加速度就可以实现减速了。这里要注意用户体验,为了让人有一个顺畅的感觉,启动的速度必须要相当的快,结尾的时候要慢慢的减速,营造抽奖的紧张气氛。所以加速度是有一个先大后小的变化,跟CSS中的 ease-out 一样的效果。代码如下:
var rotate = document.getElementById('imgs');
var speed = vspeed = 0,
x0 = y0 = t0 = x1 = y1 = t1 = null; (function(){
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x){
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}; if(!window.requestAnimationFrame){
window.requestAnimationFrame = function(callback, element){
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
}; if (!window.cancelAnimationFrame){
window.cancelAnimationFrame = function(id){
clearTimeout(id);
};
};
})(); // Setup requestAnimationFrame when it is unavailable. document.addEventListener('touchmove', function (e) {
e.preventDefault();
}); rotate.addEventListener('touchstart', function (e) {
if (e.touches.length == 1) {
x0 = e.targetTouches[0].clientX;
y0 = e.targetTouches[0].clientY;
t0 = new Date().getTime();
}
}); rotate.addEventListener('touchend', function (e) {
var that = this,
l = 0,
angle = 0,
timerID = null;
x1 = e.changedTouches[0].clientX;
y1 = e.changedTouches[0].clientY;
t1 = new Date().getTime();
l = Math.sqrt(Math.pow(x1-x0,2) + Math.pow(y1-y0,2));
speed = l/(t1-t0)*20;
if (speed < 10) return;
vspeed = 0.5; var roll = function () {
angle += speed;
that.style.transform = 'rotateZ(' + angle + 'deg)';
switch (true){
case speed < -0.3:
window.cancelAnimationFrame(timerID);
return;
case speed < 10 && vspeed > 0.1:
speed -= vspeed;
vspeed -= 0.03;
break;
default:
speed -= vspeed;
break;
}
timerID = window.requestAnimationFrame(roll);
};
roll();
});
这里动画用的还是 h5 的 requestAnimationFrame 来实现,对于不支持 requestAnimationFrame 的浏览器也做了兼容。
编程还是相当简单的,难点在于参数的调整,要调整速度控制整个转动周期不能过长过短,而最麻烦的应该是最后减速阶段的加速度调整了。最后阶段太快了就没有紧张的气氛,太慢了又会有卡顿的感觉,尤其在国产移动浏览器上表现得更为明显。
性能优化
在没性能优化前,在国产的移动浏览器上卡顿得简直瞎了眼,优化是必须的。
常规做法:分层,动态元素与静态元素分离,也就是转盘绝对定位、单独占一个层,这样的话动态元素的变化不会影响到静态元素的布局,减少重绘。这个优化很基础,写页面的时候就已经实施了,可见问题并不在此。另外之前一直听说要用 CSS3d 变换的方法强制使用 GPU 渲染页面提高性能,但是代码上我已经写了 'rotateZ()',应该已经开启了硬件渲染了,不知道问题在哪,如何解决。空想也是无用,赶紧用 chrome developer 测试了一下:
可以看到数据其实还是相当不错的,脚本、渲染和绘图所占时间还比较合理的,但是问题会出在哪里呢?当然是国产浏览器身上了,那怎么去优化呢?再用 chrome 的渲染检测工具看看吧。打开方式:
见名知义,第一项可以检测页面的绘制刷新(重绘),第二项显示图层边界,第三项是显示 FPS(Frame per Second,FPS,帧率),这几项重点关注。因为这个是单页应用,所以后面的滚动问题检测和媒体仿真就略过了。启动之后是这样的:
最前面的绿色遮罩表示重绘区域,四周还有一圈褐色的表示渲染层,启动动画的时候可以发现在绘制动画时事实上转盘元素在不断重绘,这应该是问题的关键。但怎么解决呢?很多文章在介绍使用 GPU 渲染时候都会提到下面这两句样式:
backface-visibility: hidden;
perspective: 1000;
试着用了这两句之后,立马出现了效果,旋转的时候不再出现绿色的重绘框了:
再回到某国产移动浏览器上测试,终于没有那种死活转不起来的感觉了,感觉跟原生应用差不多了,其实原生应用无非也是用了 GPU 渲染而已,当 web 能调用这些底层的话,性能上差别不会很大。这里面其实后面一句 perspective: 1000; 是多余的,设这么大的透视距离目的是为了减弱 3D 效果,减少计算量,而转盘转动本来就没 3D 效果,所以这里是没效果的。
主要是 backface-visibility: hidden 起作用。backface 就是元素背面,元素和医院照的X光片一样,正反两面都可以看。隐藏背面的意思就是转过来是空白的,什么也没有。如果不设置这个的话,浏览器会连物体的背面也渲染出来。由于转盘元素上面还叠加有指针元素,如果不指定隐藏背面的话,那浏览器就将转盘覆盖的范围全部重绘,比如说我绕 X 或者 Y 轴旋转,既然画出转盘还要画出指针,那肯定是要重绘这一大块页面的。至于隐藏背面之后为何不再发生渲染层的重绘,这个可能跟浏览器的渲染策略有关,这里浏览器应该会按照最优解去重绘所需的层,不变的层仍然保留,最后做合成算法。这一块我也还不甚了解,这些只是我个人的理解,有不当之处请务必指正!
PS: 后续发现只要设置了 backface-visibility: hidden,根本不需要开启 GPU,直接用 2D 旋转也能得到非常好的效果!
邓爷爷说得对,实践是检验真理的唯一标准!
参考资料:
1)Accelerated Rendering in Chrome: http://www.html5rocks.com/en/tutorials/speed/layers/
2)App performance validation: https://developer.mozilla.org/en-US/Apps/Fundamentals/Performance/App_performance_validation
3)被解放的GPU CSS3动画加速: http://www.cnblogs.com/sunshq/p/4878019.html
4)【Web动画】CSS3 3D 行星运转 && 浏览器渲染原理: http://www.cnblogs.com/coco1s/p/5439619.html#3420358
5)Web animations on large screens: https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox_OS_for_TV/Web_animations_on_large_screen
以上,码字不易,随手点赞哈
(图片出处:小周)
原创文章,转载请注明出处!本文链接:http://www.cnblogs.com/qieguo/p/5481522.html
简单的转盘抽奖——CSS动画优化的更多相关文章
- 前端性能优化(css动画篇)
正巧看到在送书,于是乎找了找自己博客上记录过的一些东西来及其无耻的蹭书了~~~ 小广告:更多内容可以看我的博客 最近拜读了一下html5rocks上几位大神写的一篇关于CSS3动画性能优化的文章,学到 ...
- web前端学习(三)css学习笔记部分(5)-- CSS动画--页面特效、HTML与CSS3简单页面效果实例
CSS动画--页面特效部分内容目前仅仅观看了解内容,记录简单笔记,之后工作了进行内容的补充 7. CSS动画--页面特效 7.1 2D.3D转换 7.1.1 通过CSS3转换,我们能够对元素进行 ...
- 简单JS旋转实现转盘抽奖效果
闲来没事,做了一个模拟转盘抽奖的HTML&JS的效果: 可以在设置的时候,选择几个区域,并且可以填写指针将要停止的区域 比如,我选择了"区域2",结果就是这样 具体可以见下 ...
- HTML5 Canvas绘制转盘抽奖
新项目:完整的Canvas转盘抽奖代码 https://github.com/givebest/GB-canvas-turntable 演示 http://blog.givebest.cn/GB-ca ...
- 梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画
CSS动画并不是绝对比JavaScript动画性能更优越,开源动画库Velocity.js等就展现了强劲的性能. 一.两者的主要区别 先开门见山的说说两者之间的区别. 1)CSS动画: 基于CSS的动 ...
- web:转盘抽奖
移动web:转盘抽奖(幸运大转盘) 为了获取客户.回馈客户,平台一般会推出抽奖活动类的营销页.因此web页面中,有各式各样的抽奖效果. 格子式(九宫格),背景滚动式(数字/文字/图案),旋转式(转 ...
- 移动web:转盘抽奖(幸运大转盘)
为了获取客户.回馈客户,平台一般会推出抽奖活动类的营销页.因此web页面中,有各式各样的抽奖效果. 格子式(九宫格),背景滚动式(数字/文字/图案),旋转式(转盘),游戏式(砸蛋/拼图...).... ...
- CSS 动画一站式指南
CSS 动画一站式指南 目录 CSS 动画一站式指南 1. CSS 动画 1.1 变换 1.1.1 变换属性介绍 1.1.2 变换动画实践 1.2 过渡 1.2.1 过渡属性介绍 1.2.2 过渡动画 ...
- React-Native 动画优化
前言 动画对于客户端来说是非常重要的一部分,直接影响到应用的用户体验.前端对于动画优化通常使用CSS3样式来实现动画,以利用GPU加速特性.而React-Native由于渲染模式的不同,无法使用CSS ...
随机推荐
- C# ini文件操作【源码下载】
介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...
- 2015 西雅图微软总部MVP峰会记录
2015 西雅图微软总部MVP峰会记录 今年决定参加微软MVP全球峰会,在出发之前本人就已经写这篇博客,希望将本次会议原汁原味奉献给大家 因为这次是本人第一次写会议记录,写得不好的地方希望各位园友见谅 ...
- 【接口开发】浅谈 SOAP Webserver 与 Restful Webserver 区别
接口,强大,简单,交互,跨越平台 下面简单阐述这两大接口思想 一 REST: REST是一种架构风格,其核心是面向资源,REST专门针对网络应用设计和开发方式,以降低开发的复杂性,提高系统的可伸缩性. ...
- Vue.js 2.0 和 React、Augular等其他框架的全方位对比
引言 这个页面无疑是最难编写的,但也是非常重要的.或许你遇到了一些问题并且先前用其他的框架解决了.来这里的目的是看看Vue是否有更好的解决方案.那么你就来对了. 客观来说,作为核心团队成员,显然我们会 ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- SQL Server-聚焦IN VS EXISTS VS JOIN性能分析(十九)
前言 本节我们开始讲讲这一系列性能比较的终极篇IN VS EXISTS VS JOIN的性能分析,前面系列有人一直在说场景不够,这里我们结合查询索引列.非索引列.查询小表.查询大表来综合分析,简短的内 ...
- NET Core-学习笔记(三)
这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...
- 对Thoughtworks的有趣笔试题实践
记得2014年在网上看到Thoughtworks的一道笔试题,当时觉得挺有意思,但是没动手去写.这几天又在网上看到了,于是我抽了一点时间写了下,我把程序运行的结果跟网上的答案对了一下,应该是对的,但是 ...
- sql的那些事(一)
一.概述 书写sql是我们程序猿在开发中必不可少的技能,优秀的sql语句,执行起来吊炸天,性能杠杠的.差劲的sql,不仅使查询效率降低,维护起来也十分不便.一切都是为了性能,一切都是为了业务,你觉得你 ...
- 深入理解CSS六种颜色模式
前面的话 赏心悦目的颜色搭配让人感到舒服,修改元素颜色的功能让人趋之若鹜.但颜色规划不当,会让网站用户无所适从.颜色从<font color="">发展至今,保留了很多 ...