您现在的位置: 万盛学电脑网 >> 程序编程 >> 网页制作 >> DivCSS教程 >> 正文

多屏复杂动画CSS技巧三则

作者:佚名    责任编辑:admin    更新时间:2022-06-22

 

    当下CSS3应用已经相当广泛,其中重要成员之一就是CSS3动画。并且,随着CSS动画的逐渐深入与普及,更复杂与细腻的动画场景也如雨后春笋般破土而出。

     

    例如上个月做的「企业QQ-新年祝福」活动:

     

    虽然视频内容是手机上的显示效果,但是,这个“企业新年祝福活动”原本只针对桌面端,移动端是后来辅助增强(增加了相当于活动页面UV 5.7%的点击)。而目前大多数类似页面只针对移动端,例如其他同事实现的QQ空间5.0预约页第二版:

    多屏复杂动画CSS技巧三则 三联

    扫码(需登录)或者链接二选一:

    经验分享:多屏复杂动画CSS技巧三则

    因此,需要多一点适配的技巧。但是,对于动画效果实现,其实都是一脉相承的,最终的实现需要很多点滴积累,我这里讲三个部分同学可能不知道的相关CSS技巧。

    注:示例代码的私有前缀均省略,大家自行脑补

    技巧一、使用animation-play-state控制每屏动画播放

    1. 类名active与动画触发
    首先,使用active触发每一屏的动画,几乎已经约定俗成,应该也建议成为默认的行业规范。

    一般做法是,当对应一屏内容进入的时候,使用JS给容器添加类名active:

    container.classList.add("active");

    如果你做的动画逼格较高,希望每次浏览这一屏内容的时候,动画都走一遍,可以使用reflow重新触发一下animation:

    container.classList.remove("active");
    container.offsetWidth = container.offsetWidth;
    container.classList.add("active");

    2. 类名active与动画控制技巧
    如何具体控制动画的播放呢?我们通常第一反应是使用下面的方法实现,动画的完整CSS代码在active状态下呈现,如:

    .element1 { /* 尺寸与定位 */ }
    .element2 { /* 尺寸与定位 */ }
    .element3 { /* 尺寸与定位 */ }
    ....active .element1 { animate: name1 1s; }
    .active .element2 { animate: name2 1s; }
    .active .element3 { animate: name2 1s; }
    ...

    从实现和功能上将,上面方法是很不错的,通俗易懂,不易犯错。不过我个人更喜欢使用配合CSS3的animation-play-state属性对每屏动画进行控制,实现如下:

    1. 动画相关CSS代码直接写在元素上:
      .element1 { /* 尺寸与定位 */ animate: name1 1s; }
      .element2 { /* 尺寸与定位 */ animate: name2 1s; }
      .element3 { /* 尺寸与定位 */ animate: name3 1s; }
      ...
    2. 创建一个类名,如.animate,凡是使用到了animation动画的元素都添加这个类名;
    3. 如下CSS代码:
      .animate {
      animation-play-state: paused;
      }
      .active .animate {
      animation-play-state: running;
      }

    之所以个人更喜欢后面的方法,是因为有一种“无侵入”的感觉,代码层次清晰,控制关系明确。有利于后期的维护与扩展。

    然而,使用animation-play-state还是有些需要注意的,对于IE10/IE11浏览器,animation-play-state是不能简写的。如:

    .element { animate: shake 4s 2s both infinite paused; }

    只会让整个CSS声明挂掉的!如下写法支持:

    .element { 
    animate: shake 4s 2s both infinite;
    animation-play-state: paused;
    }

    经验分享:多屏复杂动画CSS技巧三则

    首先,我们不能无视主流手机之Windows Phone. 其次,帅气的翻屏动画并不是移动端专有,桌面端也适用。稍稍用力,桌面移动全适配,何乐而不为!

    技巧二、不同状态下的连续动画

    有时候,动画可能不是一波流,分状态。

    例如,我们的小火箭,先是淡出动画,然后无限上下悬浮。怎么实现呢?

    经验分享:多屏复杂动画CSS技巧三则

    关键点就是动画分解与延时。

    据我所知,没办法只使用一个keyframes关键帧声明就实现这个效果,因为,这里有动画状态的变化:一个只执行一次的动画和一个无限循环动画。

    怎么办?我们可以将动画分解,写2个animation keyframes动画关键帧描述。

    @keyframes fadeIn { /* ... */ }
    @keyframes float { /* ... */ }

    然后,再分别应用这些关键帧动画。如何应用呢?有2个小技巧:

    1. 逗号与多animation动画值
    如下:

    <div class="element">小火箭</div>.element { animation: fadeIn 1s, float .5s 1s infinite; }
      /* 我淡出, 需要1秒;我1秒后开始无限漂浮 */

    其中float .5s 1s infinite这里的1s就是无限漂浮动画执行延迟的时间,于是,两个动画完美配合,感觉就像是一个动画。实际上,就是一个动画,所有CSS3 animation动画走同一个UI线程,这也是为何推荐使用CSS实现动画效果的原因。

    此写法没有兼容性问题,大家可以开开心心地使用。

    2. 标签嵌套与独立动画
    我们还可以通过嵌套标签的形式实现连续动画,例如:

    <div class="element-wrap"><div class="element">小火箭</div></div>.element-wrap { animation: fadeIn 1s; }
              /* 我淡出, 需要1秒 */
    .element { animation: float .5s 1s infinite; } /* 我1秒后开始无限漂浮 */

    有人可能会奇怪了。animation本身就支持多动画并行,你还搞个标签嵌套,没有任何使用的理由啊!没错,单纯看我们这个例子,确实是这样。但是:

    ① 提取公用动画
    这类多屏动画是有N多元素同时执行不同的动画。比方说,火箭是淡出,然后上下漂浮;火箭的火焰是淡出,然后大小变化;黑洞是淡出,然后左右随波。你如何实现?

    如果纯粹借助animation语法,应该是:

    .element1 { animation: fadeIn 1s, float .5s 1s infinite; }  /* 我淡出, 需要1秒;我1秒后开始无限漂浮 */
    .element2 { animation: fadeIn 1s, size .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒后开始大小变化 */
    .element3 { animation: fadeIn 1s, move .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒后开始左右移动 */

    可以看到,淡出是公用的动画效果,我们可以借助嵌套标签,实现公用语法的合并,方面后期维护:

    .element-wrap { animation: fadeIn 1s; }          /* 大家都1秒淡出 */
    .element1 { animation: float .5s 1s infinite; } /* 我1秒后无限漂浮 */
    .element2 { animation: size .5s 1s infinite; } /* 我1秒后忽大忽小 */
    .element3 { animation: move .5s 1s infinite; } /* 我1秒后左右移动 */

    ②避免变换冲突
    有个元素动画是边360度旋转、边放大(从0放大到100%),像这种具有典型特征的动画我们显然要独立提取与公用的:

    @keyframes spin { /* transform: rotate... */ }
    @keyframes zoomIn { /* transform: scale... */ }

    好了,现在问题来了,变放大边旋转:

    .element { animation: spin 1s, zoomIn 1s; }  /* 旋转:啊,完蛋啦,我被放大覆盖啦! */

    由于都是使用transform, 发生了残忍的覆盖。当然,有好事的人会说,你使用zoom不就好了!确实,如果只是移动端,使用zoom确实棒棒哒!但是,我们这个企业活动,PC是主战场,因此,FireFox浏览器(FF不识zoom)是不能无视的。

    怎么办?重新建一个名为spinZoomIn的动画关键帧描述还是?

    经验分享:多屏复杂动画CSS技巧三则

    .element-wrap { animation: spin 1s; }   /* 我转转转 */
    .element { animation: zoomIn 1s; } /* 我大大大 */

    技巧三、无侵入定位和居中定位准则

    1. 这里的“无侵入定位”指不受animation影响的元素定位,包含两部分:一是不使用keyframes关键帧决定初始位置;二是不要使用keyframes中出现的属性定位。

    ①. 不使用keyframes决定初始位置
    应该都知道,CSS3 animation的fill-mode可以决定元素动画结束前后的位置,也就是也具有定位的作用。此时,可能就会有小伙伴,故作聪明,利用animation keyframes 0% {}或form {}去做定位,貌似,还省了写代码。看上去很赞,实际上狭隘了,这对于对animation支持不佳或不支持的浏览器实际上是不友好的,例如Android2.3不支持animation-fill-mode, IE6-IE9不支持CSS3 animation,于是乎,当遭遇这些浏览器的