zoukankan      html  css  js  c++  java
  • CSS3属性animation-play-state控制动画运行或暂停的技巧

    animation-play-state介绍

    animation-play-state 属性规定动画正在运行还是暂停。

    div{
      animation-play-state:paused;
      -webkit-animation-play-state:paused; /* Safari 和 Chrome */
    }

    浏览器支持:
    Internet Explorer 10Firefox 以及 Opera 支持 animation-play-state 属性。
    Safari Chrome 支持替代的 -webkit-animation-play-state 属性。

    注释:Internet Explorer 9 以及更早的版本不支持 animation-play-state 属性。

    语法:animation-play-state: paused|running;
    paused 规定动画已暂停。
    running 规定动画正在播放。

    下面讲解一下animation-play-state的使用技巧。

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

    使用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属性对每屏动画进行控制,实现如下:

    动画相关CSS代码直接写在元素上:

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

    创建一个类名,如.animate,凡是使用到了animation动画的元素都添加这个类名;如下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;
    }

    有人可能要奇怪了,怎么突然IE浏览器乱入了?首先,我们不能无视主流手机之Windows Phone. 其次,帅气的翻屏动画并不是移动端专有,桌面端也适用。稍稍用力,桌面移动全适配,何乐而不为!

    不同状态下的连续动画

    有时候,动画可能不是一波流,分状态。
    例如,我们的小火箭,先是淡出动画,然后无限上下悬浮。怎么实现呢?

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

    据我所知,没办法只使用一个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的动画关键帧描述还是?

    对啊,你直接外面套一层标签不就万事大吉了

    .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,于是乎,当遭遇这些浏览器的时候,页面动画元素的布局实际上是毁掉的。所以,这些动画元素定位的时候,需要使用“无侵入定位”,也就是,就算页面没有animation, 我也是个“标致人儿”。

    ②. 不使用keyframes中出现的属性定位
    举个例子,有个球,正好定位在模块的中心,同时有个无限旋转效果。使用transform: translate(-50%,-50%)居中定位再合适不过了,不用我心里难受,于是,使用了transform定位。此时,冲突发生,旋转动画也是需要transform变换的。

    @keyframes spin {
        0% { transform: rotate(0); }
        100% { transform: rotate(360deg); }
    }

    要么使用业界约定俗成spin覆盖,要么另起炉灶没法重用:

    @keyframes spin-trans {
        0% { transform: rotate(0) translate(-50%,-50%); }
        100% { transform: rotate(360deg) translate(-50%,-50%); }
    }

    显然,都是不合适的。建议使用传统left/top/margin进行定位,与transform变换动画“无侵入”。

    2. 这里的“居中定位准则”包含两部分:一是元素定位在容器中间位置;二是元素的定位方式为居中定位。

    ①. 元素定位在容器中间
    容器以及容器内的动画元素可以看成是一个动画模块,为了这个模块可以轻松驾驭水平布局和垂直局部,里面的动画元素形成的整体一定要在容器的中间,不要被设计稿或周围环境影响。

    ②. 定位方式为居中定位
    所谓“居中定位”是相对“传统定位”而言的。Web页面中的模块、文字什么的默认都是相对于左上角堆砌的,所以,很自然地,我们在重构页面,做布局,写交互效果的时候,也都是相对左上角定位。活用元素本身的定位特性,这是很赞的也推荐这么做!但是,如果你和多元素CSS动画打交道,可能就需要改变下惯性思维了,很重要的一点就是从以左上角为参考点变成以中心点为参考点
    我们在实现多元素动画效果时候,会出现两类角色:一是容器;二是容器里面诸多动画元素。

    其中,对于容器元素,尤其在做移动端产品时候,我们很自然会让其居中定位:

    .container {
        position: absolute; left: 50%; top: 50%;
        transform: translate3d(-50%, -50%, 0);
    }

    左上角定位(或右上角定位):

    .example {
        position: absolute; left: 100px; top: 100px;
    }

    中心点定位+ margin偏移:

    .example {
        position: absolute; left: 50%; top: 50%; 
        margin-left: -100px; margin-top: -100px;
    }

    在《CSS3实现全景图特效》中用到了animation-play-state属性,有兴趣的可以查看下。

    参考地址:https://isux.tencent.com/css-...

  • 相关阅读:
    PHP循环控制语句中的“for”循环
    PHP循环控制语句之“do...while”
    PHP循环控制语句之“while”
    PHP跳出循环之“continue”
    PHP跳出循环之“break”
    PHP控制语句之“switch”语句
    PHP条件控制语句之“elseif语句”
    PHP控制语句之“if...else”语句
    PHP条件控制语句之“if语句”
    三元运算符
  • 原文地址:https://www.cnblogs.com/moqiutao/p/6363952.html
Copyright © 2011-2022 走看看