最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    正文概述 掘金(掘金安东尼)   2021-07-02   525

    前言小叙

    FPS 全称:Frames per second,即 【每秒帧数】 的意思。

    通常来讲,当动画的每秒帧数低于 12 (即 12 FPS 以下)时,我们的大脑就能快速从动画中区分出一些静止的图片,所以此时的动画并不是无缝动画。

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    一旦播放速率(每秒帧数)达到 16-24 FPS 时,大脑就会认为这些画面是连续移动的场景,看起来就是影片的效果了(大部分数字电影拍摄是每秒 24 帧)。

    所以,我们可以大致了解到:FPS 越高,画面越流畅!

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    明白这些后,我们可以便可开始本篇正题了:CSS3 实现 60 FPS 的动画效果!

    常规操作

    本瓜知道你会说:“CSS3 动画,有手就行!”

    知道我们的目标是实现下图动画效果时,

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    你信手拈来,一顿操作!

    很棒,恭喜你能轻松写出以下这段超级常规的 CSS3 动画~

    <div class="layout">
    	<div class="app-menu"></div>
    	<div class="header">
    		<div class="menu-icon"></div>
    	</div>
    </div>
    
    .app-menu {
    	left: -300px;
    	transition: left 300ms linear;
    }
    
    .app-menu-open .app-menu {
    	left: 0px;
    	transition: left 300ms linear;
    }
    

    它的实现效果:

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    你确实做到了,但,到此为止吗?这次,不止于此!

    于是,咱打开控制台 Performance Ctrl+E 进行录制这段动画来进一步分析分析

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    我们可以看到它的 TimelineFPS 指标(绿色部分)

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    我们发现它存在问题:

    1. 绿色部分的高度并不一致,说明 FPS 不稳定;

    2. 绿色部分有相当一部分处在低点,说明 FPS 不流畅;

    3. 存在很多红色条,说明动画很卡;

    所以,结论是:我们这种方法实现的 CSS3 动画,并不流畅!!

    我们期望的是:高度齐平,绿色都处于高点,红色条越少越好。 别方,带着期望,继续往下看!

    进阶操作

    你非常棒,并且异于常人!!你想到了使用 Transform 来实现!!

    CSS 代码:

    .app-menu {
    	-webkit-transform: translateX(-100%);
    			transform: translateX(-100%);
    	transition: transform 300ms linear;
    }
    .app-menu-open .app-menu {
    	-webkit-transform: none;
    			transform: none;
    	transition: transform 300ms linear;
    }
    

    实现效果:

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    控制台看下 Timeline:

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    的确不一样了,跟【常规操作】中的 Timeline 图作比,高度都更加齐平了!更多绿色部分处于高点了!红色条也减少了!

    这表示我们的动画效果,更流畅了!

    • 这里动画效果为什么更流畅了呢?暂时按下不表,后文解释。

    高级操作

    噢噢噢,原来你是位高级前端,你还会这样 will-change 这样高级的操作!

    CSS 代码:

    .app-menu {
    	-webkit-transform: translateX(-100%);
    			transform: translateX(-100%);
    	transition: transform 300ms linear;
    	will-change: transform;
    }
    

    实现效果:

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    控制台看下 Timeline:

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    天呐噜!

    相较于【进阶操作】,我们更加接近目标:高度基本齐平了!绿色位置绝大部分都处在高位!红条减的更少了!

    这么厉害的嘛?不妨再往下看!

    顶级操作

    至此,你的手中还有牌吗?

    或许我们还能从 DOM 结构找找突破口!

    将前文的 DOM 改造成:

    <div class="menu">
    	<div class="app-menu"></div>
    </div>
    <div class="layout">
    	<div class="header">
    		<div class="menu-icon"></div>
    	</div>
    </div>
    

    在 layout 区域之外创建 menu,然后使用 js 中的 transitionend 函数来监听,使 menu--animatable 类在过渡时间结束时被移除。

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    // js

    function toggleClassMenu() {
    	myMenu.classList.add("menu--animatable");	
    	if(!myMenu.classList.contains("menu--visible")) {		
    		myMenu.classList.add("menu--visible");
    	} else {
    		myMenu.classList.remove('menu--visible');		
    	}	
    }
    
    function OnTransitionEnd() {
    	myMenu.classList.remove("menu--animatable");
    }
    
    var myMenu = document.querySelector(".menu");
    var oppMenu = document.querySelector(".menu-icon");
    myMenu.addEventListener("transitionend", OnTransitionEnd, false);
    oppMenu.addEventListener("click", toggleClassMenu, false);
    myMenu.addEventListener("click", toggleClassMenu, false);
    

    // 完整 css

    menu {
        position: fixed;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        pointer-events: none;
        z-index: 150;
    }
    
    .menu--visible {
        pointer-events: auto;
    }
    
    .app-menu {
        background-color: #fff;
        color: #fff;
        position: relative;
        max-width: 400px;
        width: 90%;
        height: 100%;
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
        -webkit-transform: translateX(-103%);
                transform: translateX(-103%);
        display: flex;
        flex-direction: column;
        will-change: transform;
        z-index: 160;
        pointer-events: auto;            
    }
    
    .menu--visible .app-menu {
        -webkit-transform: none;
                transform: none;
    }
    
    .menu--animatable .app-menu {
        transition: all 130ms ease-in;
    }
    
    .menu--visible.menu--animatable  .app-menu {
        transition: all 330ms ease-out;
    }
    
    .menu:after {
        content: '';
        display: block;
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        background: rgba(0,0,0,0.4);
        opacity: 0;
        will-change: opacity;
        pointer-events: none;
        transition: opacity 0.3s cubic-bezier(0,0,0.3,1);
    }
    
    .menu--visible.menu:after {
        opacity: 1;
        pointer-events: auto;
    }
    

    它的 Timeline:

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    这就是 CSS3 实现 60 FPS动画的顶级操作!

    高度全部齐平!!全部处在高位!!没有红条!!

    这是完美的 FPS 动画!如丝般顺滑!

    你做到了!(๑•̀ㅂ•́)و✧

    原理探寻

    我们在此做简单回顾:

    级别实现核心方式FPS 绿块效果动画顺滑程度
    常规操作transition: left 300ms linear;高度不齐平、较多处于低点、很多红条30% 顺滑进阶操作transition: transform 300ms linear;高度比较齐平、较少处于低点、较少红条60% 顺滑高级操作will-change: transform;高度基本齐平、很少处于低点、很少红条80% 顺滑顶级操作transitionend 函数高度完全齐平、全部处于高点、没有红条100% 顺滑

    原理呢?原理还得回归底层,来看看浏览器的渲染机制!

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    上图是浏览器渲染的关键步骤,相信大家都很熟悉:

    1. Styles(样式): 浏览器计算要应用于元素的样式;
    2. Layout(布局):浏览器计算每个元素生成形状和位置,比如 width、height、margin、left/top/right/bottom 这些;
    3. Paint(渲染):浏览器将每个元素的像素填充到图层中;
    4. Composite(合成):浏览器开始在屏幕上绘制所有图层的时候;

    第 4 步“合成”给了我们很多操作空间:

    我们可以使用 transformopacity 两个属性实现四种最常用的动画:

    1. 位置动画:translateX(n) translateY(n) translateZ(n);
    2. 大小动画:transform: scale(n);
    3. 旋转动画:transform: rotate(ndeg);
    4. 不透明度动画:opacity: n;

    在第 4 步操作为什么具有魔法呢?

    笨蛋,当然是避免重绘、回流增加渲染负担啦~

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    所以,我们的【进阶操作】控制 transform 比【常规操作】控制 left 属性更优!

    而【高级操作】中的 will-change 能告知浏览器元素会有哪些变化,这样浏览器能在变化之前做好优化准备工作,将一部分复杂计算提前准备好,所以页面的反应更加快速灵敏。

    【顶级操作】中改造分离 DOM,然后用 JS控制,手动添加 menu--animatable 类,然后用到 transitionend 事件 会在 CSS transition 结束后触发,移除 menu--animatable 类。实现完全体的 60FPS 动画!

    写在结尾

    我们都知道编码习惯非常重要,但同时又一直苦于思考,如何将一些原理知识与实际编码结合?!

    而本篇是基于浏览器渲染原理,对 CSS3 动画的一个很好结合实践!

    CodeReview 时,同事都直呼:细节!

    “秒啊~ 我理解的原理知识用来面试,你理解的原理知识用来工作中日常编码,细节!高级!”

    疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    ok,以上便是本次分享~ 都看到这儿了,撰文不易、需要鼓励~ b( ̄▽ ̄)d

    参考:

    • 为什么电影24帧就算流畅,主机30帧就算流畅,而电脑游戏需要60帧流畅?
    • FPS幀數是什麼?24fps、30fps、60fps有什麼區別?
    • how-to-achieve-60-fps-animations-with-CSS3
    • transitionend_event

    起源地下载网 » 疯狂操作 CSS3 实现 60 FPS 动画效果,CodeReview 时同事直呼:细节!

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元