0

0

实例CSS3开场动画的制作与优化_html/css_WEB-ITnose

php中文网

php中文网

发布时间:2016-06-21 09:00:52

|

2094人浏览过

|

来源于php中文网

原创

素材:

椒图AI
椒图AI

中文AI修图神器,一句话搞定复杂修图

下载

期望效果: http://v.youku.com/v_show/id_XMjY2NTc1MzYw.html

一开始需要制作这个动画的时候,其实我是拒绝的,因为单凭这几个素材,即便我对动画了如指掌,也是无从下手的。后来有一天,我见到了wow军团再临的CG动画,脑海中突然灵光一闪,便出现了这样的构思:

“穿越重重的云层,伴随着白天到黑夜的转化,logo从遥远的地方出现,随后往屏幕方向快速移动,在logo快要充满整个屏幕的时候星光一闪,又消逝在远方…” 

立即学习前端免费学习笔记(深入)”;

于是我开始了开场动画的坎坷历程。

云层制作:

云层的制作耗时比较久,期间参阅了网上一些使用CSS模拟云层的博文及示例,下面列出两个比较好的示例:

移动的云: https://codepen.io/montanaflynn/pen/orxwK

3D云: https://www.clicktorelease.com/blog/how-to-make-clouds-with-css-3d

实际上使用单图片来模拟云层会有一些体验问题,比如,当我们试图穿过一片图片生成的云时,会感觉一下就没了,对用户而言会产生一定的视觉落差,而真实的云层是一片区域,所以一片云我使用了5张图片转换方向来生成,这样在三维的场景下我们的云就有了充实感。

下面引用一段Jaume Sanchez Elias写的3D云的生成代码:

function createCloud() {    vardiv = document.createElement('div');    div.className = 'cloudBase';    // 随机定位当前云团位置    var t = 'translateX( ' + random_x + 'px )  ' +           'translateY( ' + random_y + 'px )  ' +           'translateZ( ' + random_z + 'px )';    div.style.transform = t;    world.appendChild(div);    for (varj = 0; j < 5 + Math.round(Math.random() * 10); j++) {        varcloud = document.createElement('div');        cloud.className = 'cloudLayer';        // 随机产生云层的'translateX/translateY/translateZ/rotateZ/scale       // CSS值,这里是云团充实感的关键实现        cloud.data = {            x: random_x,            y: random_y,            z: random_z,            a: random_a,            s: random_s        };        var t = 'translateX( ' + random_x + 'px )  ' +                'translateY( ' + random_y + 'px )  ' +               'translateZ( ' + random_z + 'px )  ' +               'rotateZ( ' + random_a + 'deg )  ' +               'scale( ' + random_s + ' )';         cloud.style.transform = t;        div.appendChild(cloud);        layers.push(cloud);    }    return div;}

通过上面的方法去输出云层,我们便拥有了质感较强的云。而为了让动画的加载更快一些,我将生成的云层以固定DOM的形式写在页面中,让前期的JS消耗尽量减小,并且图片的加载会在页面加载之初进行。在有了云层DOM后,便可以开始着手穿越云层效果的制作了,穿越过程里还夹带了从白天到黑夜的背景色变化效果,这个穿越的动作我使用translateZ属性来实现,让屏幕随着时间往前推进,完成穿越云层的效果,代码实现如下(这里仅展示webkit版本代码):

@-webkit-keyframes angular {    0% {        -webkit-transform: translateZ(300px);        opacity: 1;    }    100% {        -webkit-transform: translateZ(570px);        opacity: 1;    }} @-webkit-keyframes dayToNight {    0% {        background-color: #007fd5;        opacity: 1;    }    100% {        background-color: #000;        opacity: 1;    }}

星光及logo:

logo及星光的呈现过程是一个放大及放更大/缩小的过程,通过改变它的scale可以实现,实现如下:

/* 星光场景 */@-webkit-keyframes starsense {    0% {        -webkit-transform: scale(1);        opacity: 0;    }    30% {        -webkit-transform: scale(25);        opacity: 1;    }    90% {        -webkit-transform: scale(0);        opacity: 1;    }    100% {        -webkit-transform: scale(0);        opacity: 0;    }}/* logo场景 */@-webkit-keyframes logosense {    0% {        -webkit-transform: scale(0);        transform: scale(0);        opacity: 1;    }    20% {        -webkit-transform: scale(1);        transform: scale(1);    }    85% {        -webkit-transform: scale(1);        transform: scale(1);        opacity: 1;        -webkit-filter: blur(0);    }    100% {        -webkit-transform: scale(100);        transform: scale(100);        opacity: 0;        -webkit-filter: blur(50px);    }}

性能优化:

由于在测试中发现动画的性能是一个比较大的问题,在一些配置比较低的机器会有很多掉帧,卡顿的现象,因此需要进行性能方面的优化。

我使用chrome里面的工具Timeline进行了动画执行性能检查,从中发现,在动画执行周期内,渲染及重绘耗费的资源比较多,并且期间JS也占用了一些资源,于是我首先回头查看了我的动画加载函数

    function loadOpenSenseAnimation() {        isStart = true;        openSense.className += ' begin';        world.className += ' begin';        logoSense.className += ' begin';         setTimeout(function() {            viewPort.className = ' begin';        }, 4000);        loadingAudio === 0 && Audio.play();        openSense.addEventListener("webkitAnimationEnd", function(){             // 动画结束时事件             console.log('动画执行结束啦!');             if (openSense) {                // 执行完就抹除                openSense.parentNode.removeChild(openSense);            }        }, false);     }

于是它变成了这样纸:

    function loadOpenSenseAnimation() {         Settings.isStart = true;        $container.className += ' animated';         $mask.addEventListener("webkitAnimationStart", function() {            // 动画开始时候播放            if (Settings.isVoice && Settings.loadingAudio === 0) {                Settings.AudioPlayer.play();            }        }, false);         $container.addEventListener("webkitAnimationEnd",           function(animation) {            // 动画结束时事件            if (animation.animationName === Settings.EndingAnimatedName) {                OpenSense.pass();            }        }, false);    }

这里我把setTimeout函数移除掉,使用animation-delay来接替setTimeout的位置,多个DOM操作被合并成了一个,把JS的消耗影响尽量降到最低。动画的声音播放使用webkitAnimationStart事件来监听,使音乐与动画的进行同步(这里需要注意webkitAnimationEnd/webkitAnimationStart的使用,每一个子节点的动画开始结束都会触发这个事件,需要判断一下animationName 确定是否是自己需要的动画事件),接下来我再次使用Timeline进行检查:

可以看到,在动画执行期间,从云层开始帧数就一直不高,结合此前的渲染重绘时间占用率过高,初步定为CSS属性使用不当。于是我查阅了CSS动画中所使用的属性:

根据Timeline掉帧的时间片段,结合这个时间段内产生作用的CSS属性,将一些可能影响性能的属性标记了出来,并进行了排除试验,我们发现,blur是损耗性能的主要因素,于是我对CSS做了一次排除优化,将blur,重复或不必要的属性进行剔除。

优化结果:

多次优化后,通过Timeline得到了下面的结果,我们可以看到,除了页面加载之初的一些掉帧,后面基本平稳在60帧,期间的无帧数是因为动画固定在logo处停了3s左右。

在线示例: http://huangxingbang.github.io/openSense/cloud.html

总结:

1.动画尽量使用opacity/translate/rotate /scale 这些可以让GPU分担工作的属性。

2.摈弃setTimeout在动画中的控制,动画播放时机的控制使用animation-delay来实现,如果需要精准控制,使用RequestAnimationFrame对动画进行更新。

3.使用webkitAnimationStart/webkitAnimationEnd对动画并行的任务进行开始/结束控制。

参考资料:

前端性能优化(CSS动画篇): https://segmentfault.com/a/1190000000490328

高性能 CSS3 动画: https://www.qianduan.net/high-performance-css3-animations/

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
go语言 注释编码
go语言 注释编码

本专题整合了go语言注释、注释规范等等内容,阅读专题下面的文章了解更多详细内容。

32

2026.01.31

go语言 math包
go语言 math包

本专题整合了go语言math包相关内容,阅读专题下面的文章了解更多详细内容。

23

2026.01.31

go语言输入函数
go语言输入函数

本专题整合了go语言输入相关教程内容,阅读专题下面的文章了解更多详细内容。

16

2026.01.31

golang 循环遍历
golang 循环遍历

本专题整合了golang循环遍历相关教程,阅读专题下面的文章了解更多详细内容。

5

2026.01.31

Golang人工智能合集
Golang人工智能合集

本专题整合了Golang人工智能相关内容,阅读专题下面的文章了解更多详细内容。

6

2026.01.31

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

268

2026.01.31

高干文在线阅读网站大全
高干文在线阅读网站大全

汇集热门1v1高干文免费阅读资源,涵盖都市言情、京味大院、军旅高干等经典题材,情节紧凑、人物鲜明。阅读专题下面的文章了解更多详细内容。

195

2026.01.31

无需付费的漫画app大全
无需付费的漫画app大全

想找真正免费又无套路的漫画App?本合集精选多款永久免费、资源丰富、无广告干扰的优质漫画应用,涵盖国漫、日漫、韩漫及经典老番,满足各类阅读需求。阅读专题下面的文章了解更多详细内容。

170

2026.01.31

漫画免费在线观看地址大全
漫画免费在线观看地址大全

想找免费又资源丰富的漫画网站?本合集精选2025-2026年热门平台,涵盖国漫、日漫、韩漫等多类型作品,支持高清流畅阅读与离线缓存。阅读专题下面的文章了解更多详细内容。

85

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
【web前端】Node.js快速入门
【web前端】Node.js快速入门

共16课时 | 2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号