css3变形动画www.4242.com:

 新闻中心     |      2020-04-04 16:52

1.分析

css3中变形与动画(三),css3变形动画

transform可以实现矩阵变换,transition实现属性的平滑过渡,animation意思是动画,动漫,这个属性才和真正意义的一帧一帧的动画相关。本文就介绍animation属性。

animation属性通过一些关键帧中元素属性的改变来实现动画效果。当然也可以控制动画持续时间,动画迭代次数等。

当消息被触发的时候,会有一个自上而下的淡入过程。在持续了一段时间后会自动的消失,或者是需要用户来手动的点击关闭按钮。在消息消失的时候,会有一个自下而上的淡出过程。消息是可以叠加弹出的,最新的消息会排在消息列表的最后面。当前面的消息消失后,后面的消息会有一个向上滑动效果。然后消息本身是有三部分组成

一、例子

在介绍transition时开篇有一个例子就是实现鼠标放上去,div宽度从100px缓慢增大到200px。

用transition实现方法如下

div:hover{
    width: 200px;
    transition:width 5s ease-in;
}

用animation也能实现类似效果,如下:

<style type="text/css">
div {
    width: 100px;
    height: 100px;
    background-color: red;
}
@keyframes enlarge {
    0% {
        width: 100px;
    }
    50% {
        width: 150px;
    }
    100% {
        width: 200px;
    }
}
div:hover {
    /*width: 200px;    */   
    /*transition:width 5s ease-in;*/
    animation: 5s enlarge;
}
}
</style>
<div></div>

鼠标悬停,动画持续5s,在时间到一半时div的宽度要从100px达到150px,5s时div宽度达到200px,动画结束。

但是transition和animation效果还是有差别的,鼠标hover上去,transition动画执行完后width保持200px;animation动画执行完后width回到100px。

www.4242.com 1

当然这只是默认效果,这个动画完成时的效果也是可以修改的。

修改上面代码中animation为

animation: 5s enlarge forwards;

就可以让动画执行完后停在最后一帧。这个forwards是animation-fill-mode的值,后面会详细讲。

通过这个例子只是想说,可以理解为transition是animation的简化版,animation可以做更多的控制,也更强大。下面正式开始介绍。

消息图标,用来区分不同类型的消息。消息文本。关闭按钮,并不是所有消息都需要关闭按钮。

二、keyframes

keyframes意思是“关键帧”,在关键帧会改变元素属性的计算值。

keyframes语法:

keyframes-rule: '@keyframes' IDENT '{' keyframes-blocks '}';
keyframes-blocks: [ keyframe-selectors block ]* ;
keyframe-selectors: [ 'from' | 'to' | PERCENTAGE ] [ ',' [ 'from' | 'to' | PERCENTAGE ] ]*;

综合写法:

 @keyframes IDENT {
     from {
       Properties:Properties value;
     }
     Percentage {
       Properties:Properties value;
     }
     to {
       Properties:Properties value;
     }
   }
   或者全部写成百分比的形式:
   @keyframes IDENT {
      0% {
         Properties:Properties value;
      }
      Percentage {
         Properties:Properties value;
      }
      100% {
         Properties:Properties value;
      }
    }

可见keyframes写法是这样的:由"@keyframes"开头,后面紧跟这个“动画的名称”加上一对花括号“{}”,括号中是一些不同时间段的样式规则,规则写法同css样式。

一个“@keyframes”中的样式规则是由多个百分比构成的,如"0%"到"100%"之间,可以在一个规则中创建多个百分比,分别在每一个百分比中给需要有动画效果的元素加上不同的属性,从而让元素达到一种不断变化的效果,比如说移动、改变元素颜色、位置、大小、形状等。

两个关键字,"from"和"to"表示一个动画从哪开始,到哪结束,也就是"from"相当于"0%",而"to"相当于"100%"。

Note:0%中的%不能省略,省略则整个keyframes语法错误,整条规则无效,因为keyframes的单位只接受百分比值。

举例:W3C官网的实例,下面介绍animation时会用到这段代码。

 @-webkit-keyframes 'wobble' {
     0% {
        margin-left: 100px;
        background: green;
     }
     40% {
        margin-left: 150px;
        background: orange;
     }
     60% {
        margin-left: 75px;
        background: blue;
     }
     100% {
        margin-left: 100px;
        background: red;
     }
  }

keyframes定义每一帧的动画,但只写keyframes是没用的,需要调用才能生效。那怎样调用就用到animation了。

2. 实现样式

三、animation

animation没有事件触发时,在页面加载后显式的随着时间变化来改变元素css样式,从而产生动画效果。

元素是怎样调用animation和keyframes的呢?

举例:调用上面写好的wobble动画。

 .demo1 {
     width: 50px;
     height: 50px;
     margin-left: 100px;
     background: blue;
     -webkit-animation-name:'wobble';/*动画属性名,也就是我们前面keyframes定义的动画名*/
     -webkit-animation-duration: 10s;/*动画持续时间*/
     -webkit-animation-timing-function: ease-in-out; /*动画频率,和transition-timing-function是一样的*/
     -webkit-animation-delay: 2s;/*动画延迟时间*/
     -webkit-animation-iteration-count: 10;/*定义循环次数,infinite为无限次*/
     -webkit-animation-direction: alternate;/*定义动画方式*/
  }

到此,如果前面看过transition应该已经明白animation也是个复合属性。

www.4242.com,animation包含下面属性: animation-name,animation-duration,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,animation-play-state和animation-fill-mode。下面一一介绍,重点理解加粗的属性。

那么,不管我们是用原生js还是vue,首先呢,我们都需要把这个消息的基本样式给写出来,然后再通过js来控制消息的弹出和关闭。所以,我们先来写html和css。

1、animation-name

animation-name是最关键的了,表示应用哪个帧动画。

语法:

animation-name: none | IDENT[,none | IDENT]*;

默认值:none,即默认情况没有动画效果。

animation-name属性调用@keyframes定义好的动画,必须和"@keyframes"定义的动画名称完全一致(区分大小写)。

举例:animation配合矩阵变换中的平移做一个有意思的小动画。

www.4242.com 2<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>变形与动画</title> <style type="text/css"> @keyframes around{ 0% { transform: translateX(0); } 25%{ transform: translateX(180px); } 50%{ transform: translate(180px, 180px); } 75%{ transform:translate(0,180px); } 100%{ transform: translateY(0); } } div { width: 200px; height: 200px; border: 1px solid red; margin: 20px auto; } div span { display: inline-block; width: 20px; height: 20px; background: orange; border-radius: 100%; animation-name:around; animation-duration: 10s; animation-timing-function: ease; animation-delay: 1s; animation-iteration-count:infinite; } </style> </head> <body> <div> <span></span> </div> </body> </html> View Code

www.4242.com 3

       这是一条正经的消息~      这是一条正经的消息~ /* message.css */ #message-container { position: fixed; left: 0; top: 0; right: 0; /* 采用flex弹性布局,让容器内部的所有消息可以水平居中,还能任意的调整宽度 */ display: flex; flex-direction: column; align-items: center;}#message-container .message { background: #fff; margin: 10px 0; padding: 0 10px; height: 40px; box-shadow: 0 0 10px 0 #eee; font-size: 14px; border-radius: 3px; /* 让消息内部的三个元素可以垂直水平居中 */ display: flex; align-items: center;}#message-container .message .text { color: #333; padding: 0 20px 0 5px;}#message-container .message .close { cursor: pointer; color: #999;} /* 给每个图标都加上不同的颜色,用来区分不同类型的消息 */#message-container .message .icon-info { color: #0482f8;}#message-container .message .icon-error { color: #f83504;}#message-container .message .icon-success { color: #06a35a;}#message-container .message .icon-warning { color: #ceca07;}#message-container .message .icon-loading { color: #0482f8;}

2、animation-duration

语法:

animation-duration: <time>[,<time>]*

默认值为0,意味着动画时长0,即没有动画效果(如果值为负值被视为0)。

animation-duration定义播放动画持续的时间,也就是完成从0%到100%一次动画所需要的时间。单位s。

3. 实现动画

3、animation-timing-function

语法:

animation-timing-function:ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier(<number>, <number>, <number>, <number>) [, ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier(<number>, <number>, <number>, <number>)]*

animation-timing-function属性用来设置动画播放方式。详情可参考css3中变形与动画(二)中的介绍。

接下来要做的就是这个消息的弹出和消失动画,我们还是用css来实现。

4、animation-delay

语法:

animation-delay:<time>[,<time>]*

animation-delay定义事件触发到动画开始执行的时间,即延时。

想要在css里边实现自定义的动画,首先需要用@keyframes来定义一个动画规则,然后再通过animation属性把动画应用到某个元素上就可以了。所谓的动画规则其实就是一个动画序列,或者可以理解为一个个的关键帧,而关键帧的内部就是你想改变的css属性,你可以在关键帧里边写上几乎任何的css属性,当动画被应用的时候,这些css属性就会根据各个关键帧做出相应的变换。

5、animation-iteration-count

语法:

animation-iteration-count: infinite | <number> [, infinite | <number>]*

animation-iteration-count属性用来定义动画的播放次数。

默认值为1,即动画从开始到结束只播放一次。

值为infinite,动画将会无限次播放。

那我们先用@keyframes来写一个动画规则吧

6、animation-direction

语法:

animation-direction:normal | alternate [, normal | alternate]*

animation-direction设置动画播放方向。

属性:

normal:默认值,如果值为normal时,动画每次循环都是向前播放。

alternate:奇数次播放动画是按顺序播放各帧动画,偶数次播放动画是按逆序播放各帧动画。

这个alternate还是很有用的,我写了一个例子,可以感受一下alternate效果。

例子:div尺寸由小到大,然后由大到小。

www.4242.com 4<style type="text/css"> @-webkit-keyframes 'testAnimationDirection' { 0% { width: 50px; } 20% { width: 100px; } 40% { width: 150px; } 60% { width: 200px; } 80% { width: 250px; } 100% { width: 300px; } } div{ width: 50px; height: 50px; border:1px solid red; -webkit-animation-name:'testAnimationDirection'; -webkit-animation-duration: 10s; -webkit-animation-timing-function: ease-in-out; -webkit-animation-delay: 0s; -webkit-animation-iteration-count: infinite; -webkit-animation-direction: alternate; -webkit-animation-fill-mode:backwards; } </style> <div></div> View Code

 

/* message.css */ /* 这个动画规则我们就叫做message-move-in吧,随后我们会用animation属性在某个元素上应用这个动画规则。 */@keyframes message-move-in { 0% { /* 前边分析过了,弹出动画是一个自上而下的淡入过程 */ /* 所以在动画初始状态要把元素的不透明度设置为0,在动画结束的时候再把不透明度设置1,这样就会实现一个淡入动画 */ opacity: 0; /* 那么“自上而下”这个动画可以用“transform”变换属性结合他的“translateY”上下平移函数来完成 */ /* translateY表示动画初始状态,元素在实际位置上面“自身一个高度”的位置。 */ transform: translateY; } 100% { opacity: 1; /* 平移到自身位置 */ transform: translateY; }}

7、animation-play-state

animation-play-state用来控制元素动画的播放状态。

参数:

running:running是其默认值,作用是类似于音乐播放器一样,可以通过paused将正在播放的动画停下来,也可以通过running将暂停的动画重新播放。

Note:

这里的重新播放不一定是从元素动画的开始播放,而是从暂停的那个位置开始播放。

如果暂停了动画的播放,元素的样式将回到最原始设置状态。

paused:暂停播放。

这个很有用,让动画在鼠标悬停时暂停,离开时继续播放。

例子:还是上面的例子,加下面代码即可。

  div:hover{
      animation-play-state:paused;
  }

然后我们再定义一个和message元素同级的类move-in,把message-move-in这个动画规则给应用到move-in类上,这样我们需要让哪个消息弹出,就只需要在消息的类上加一个move-in就行。

8、animation-fill-mode

animation-fill-mode规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用的样式。

有四个属性值:

none:默认值,动画执行前后不改变元素的任何样式。就是说动画在第一个关键帧播放之前不影响元素,最后一个关键帧播放完后停止影响元素。

forwards:动画完成后呆在最后一帧,就是保持结束时的状态。这里的最后一帧取决于animation-direction和animation-iteration-count:

www.4242.com 5

backwards:在animation-delay期间应用第一帧。保持animation-delay,第一帧取法如下:

www.4242.com 6

both:根据animation-direction轮流应用forwards和backwards规则。

Note:forwards和backwards关键字都是有s的。

/* message.css */ #message-container .message.move-in { /* animation属性是用来加载某个动画规则 请参考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation */ animation: message-move-in 0.3s ease-in-out;}

backwards和none的区别

还是上面的例子,只是增加了animation-fill-mode属性。

<style type="text/css">
 @-webkit-keyframes 'wobble' {
     0% {
        margin-left: 100px;
        background: green;
     }
     40% {
        margin-left: 150px;
        background: orange;
     }
     60% {
        margin-left: 75px;
        background: blue;
     }
     100% {
        margin-left: 100px;
        background: red;
     }
  }
    div{
   width: 50px;
     height: 50px;
     margin-left: 100px;
     background: blue;
     -webkit-animation-name:'wobble';
     -webkit-animation-duration: 10s;
     -webkit-animation-timing-function: ease-in-out; 
     -webkit-animation-delay: 10s;
     -webkit-animation-iteration-count: 10;
     -webkit-animation-direction: alternate;
    /* -webkit-animation-fill-mode:none; /*动画开始为蓝色*/
     -webkit-animation-fill-mode:backwards; /*动画开始为绿色*/
  }
</style>
<div></div>

animation-fill-mode为none,则动画开始延时期间div为蓝色,backwards则动画开始延时期间div为绿色。

可以看到,只需要在某个message上追加一个move-in就能实现弹出动画。那么,消失动画也是一个套路,只不过跟弹出动画反过来而已。

四、相关资源

看网上资料说做动画,尽量使用绝对定位,从而避免重绘重排问题:

动画十四原则: 

动画十二原则:

css3 animation动画库,有很多基础动画

hover animation动画

css3 animation在线调节工具:

     基于chrome的插件,可以快速调节页面上的动画

      腾讯isux一款非常强大的动画工具

    财付通的帧动画调节工具

参考资源链接:

css3 animation动画技巧

跳动心脏

w3c css3-animations

MDN animation-fill-mode

 

本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:

 

transform可以实现矩阵变换,transition实现属性的平滑过渡,animation意思是动画,动漫,这个属性才和真...

/* message.css */ @keyframes message-move-out { 0% { opacity: 1; transform: translateY; } 100% { opacity: 0; transform: translateY; }} #message-container .message.move-out { animation: message-move-out 0.3s ease-in-out; /* 让动画结束后保持结束状态 */ animation-fill-mode: forwards;}

animation-fill-mode: forwards;这个是干嘛的呢?因为动画结束后默认会回到元素的最初状态,在这里表现的是消失后又出现了。

所以animation-fill-mode: forwards;是为了让动画结束后保持这个结束状态,也就是不在显示了。

4. 编写js插件

那么,在写js之前呢,我们先来思考一下,如果你是插件的使用者,你想怎么来调用这个插件?我们的插件很简单,就是在需要的时候弹出一个消息,假设插件他提供给我们的是一个类,就叫做Message吧,并且他内部有一个show方法,那么只要使用者实例化这个类后,调用他的show方法,然后传入不同的参数就可以弹出一个消息了。而且我们所实例化的对象可以是全局唯一的。

 // message&#21487;&#20197;&#23450;&#20041;&#20026;&#20840;&#23616;&#23545;&#35937;&#65292;&#39033;&#30446;&#20013;&#21487;&#20197;&#30452;&#25509;&#35843;&#29992;&#12290;const message = new Message();message.show({ type: 'success', text: '&#28857;&#20010;&#20851;&#27880;&#19981;&#36855;&#36335;~'});

所以呢,我们要先写一个Message类,并且必须要实现一个show方法。

/* message.js */ class Message { constructor() { } show({ type = 'info', text = '' }) { }}

这里我直接用了es6的class关键词,其实他的内部还是原型链的形式。用class呢,可以让我们更直观的了解这个类。

根据我们在第一部分的分析,所有的消息元素都是需要在js中创建的,所以我们不需要使用者来写任何html代码,那么我们只需要在对象被实例化new Message()的时候,就去创建消息容器message-container,后续在调用show方法时候,直接把消息插入到message-container内部即可。

/* message.js */ class Message { /** * 构造函数会在实例化的时候自动执行 */ constructor() { const containerId = 'message-container'; // 检测下html中是否已经有这个message-container元素 this.containerEl = document.getElementById; if  { // 创建一个Element对象,也就是创建一个id为message-container的dom节点 this.containerEl = document.createElement; this.containerEl.id = containerId; // 把message-container元素放在html的body末尾 document.body.appendChild; } } show({ type = 'info', text = '' }) { }}

这样,我们调用const message = new Message()的时候会在dom中自动的插入一个message-container节点。那么,最重要的还是我们的show方法:

创建一个消息节点,并把它追加到message-container容器的末尾。设定一个时间,在这个时间结束后自动的将消息移除。监听“关闭按钮”的click事件,来让用户可以手动的移除消息。我们一步一步来。

4.1 创建一个消息节点,并把它追加到message-container容器的末尾。

class Message { // 省略... show({ type = 'info', text = '' }) { // 创建一个Element对象 let messageEl = document.createElement; // 设置消息class,这里加上move-in可以直接看到弹出效果 messageEl.className = 'message move-in'; // 消息内部html字符串 messageEl.innerHTML = `  ${text}  `; // 追加到message-container末尾 // this.containerEl属性是我们在构造函数中创建的message-container容器 this.containerEl.appendChild; }

 弹窗消息提醒  // message&#21487;&#20197;&#23450;&#20041;&#20026;&#20840;&#23616;&#23545;&#35937;&#65292;&#39033;&#30446;&#20013;&#21487;&#20197;&#30452;&#25509;&#35843;&#29992;&#12290; const message = new Message(); document.querySelector.addEventListener =&gt; { message.show({ type: 'success', text: '&#28857;&#20010;&#20851;&#27880;&#19981;&#36855;&#36335;~' }); }); 

4.2 设定一个时间,在这个时间结束后自动的将消息移除。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000 }) { // 省略... // 用setTimeout来做一个定时器 setTimeout => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove; }}

可以看到,消息在过了2秒后,自动的从dom树中移除了,不过呢并没有动画,还记得前边我们写了move-out类吗?这个类和message是同级的。现在我们只需要在定时结束后把这个类应用到message元素上就行。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000 }) { // 省略... // 用setTimeout来做一个定时器 setTimeout => { // 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下 messageEl.className = messageEl.className.replace; // 增加一个move-out类 messageEl.className += 'move-out'; // 这个地方是监听动画结束事件,在动画结束后把消息从dom树中移除。 // 如果你是在增加move-out后直接调用messageEl.remove,那么你不会看到任何动画效果 messageEl.addEventListener => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove; }}

4.3 监听“关闭按钮”的click事件,来让用户可以手动的移除消息。

有时候呢,我们希望消息能够一直展示,直到用户来手动的关闭掉,那么首先我们要加一个参数,用来控制是否展示这个关闭按钮。

// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000, closeable = false }) { // 创建一个Element对象 let messageEl = document.createElement; // 设置消息class,这里加上move-in可以直接看到弹出效果 messageEl.className = 'message move-in'; // 消息内部html字符串 messageEl.innerHTML = `  ${text} `; // 是否展示关闭按钮 if  { // 创建一个关闭按钮 let closeEl = document.createElement; closeEl.className = 'close icon icon-close'; // 把关闭按钮追加到message元素末尾 messageEl.appendChild; // 监听关闭按钮的click事件,触发后将调用我们的close方法 // 我们把刚才写的移除消息封装为一个close方法 closeEl.addEventListener => { this.close; } // 追加到message-container末尾 // this.containerEl属性是我们在构造函数中创建的message-container容器 this.containerEl.appendChild; // 只有当duration大于0的时候才设置定时器,这样我们的消息就会一直显示 if  { // 用setTimeout来做一个定时器 setTimeout => { this.close; }, duration); } } /** * 关闭某个消息 * 由于定时器里边要移除消息,然后用户手动关闭事件也要移除消息,所以我们直接把移除消息提取出来封装成一个方法 * @param {Element} messageEl */ close { // 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下 messageEl.className = messageEl.className.replace; // 增加一个move-out类 messageEl.className += 'move-out'; // 这个地方是监听动画结束事件,在动画结束后把消息从dom树中移除。 // 如果你是在增加move-out后直接调用messageEl.remove,那么你不会看到任何动画效果 messageEl.addEventListener => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove; }}

我们来调用下试试~

 弹窗消息提醒  // message&#21487;&#20197;&#23450;&#20041;&#20026;&#20840;&#23616;&#23545;&#35937;&#65292;&#39033;&#30446;&#20013;&#21487;&#20197;&#30452;&#25509;&#35843;&#29992;&#12290; const message = new Message(); document.querySelector.addEventListener =&gt; { message.show({ type: 'warning', text: '&#28857;&#25105;&#26049;&#36793;&#30340;&#21449;&#21449;&#35797;&#35797;', duration: 0, // &#19981;&#20250;&#33258;&#21160;&#28040;&#22833; closeable: true, // &#21487;&#25163;&#21160;&#20851;&#38381; }); }); 

其实已经写的差不多了,不过还是有一些小问题,比如当我们弹出两个甚至更多消息的时候,如果前边的消息消失后,下面的消息会直接跳到上面的位置,很僵硬,没有任何的滑动。

我们可以通过css的transition属性来让meesage的高度逐渐变小,这样下面的元素就会根据变化来逐渐上移。

/* message.css *//* 省略... */ #message-container .message { background: #fff; margin: 10px 0; padding: 0 10px; height: 40px; box-shadow: 0 0 10px 0 #ccc; font-size: 14px; border-radius: 3px; /* 让消息内部的三个元素可以垂直水平居中 */ display: flex; align-items: center;/* 增加一个过渡属性,当message元素的高度和margin变化时候将会有一个过渡动画 */ transition: height 0.2s ease-in-out, margin 0.2s ease-in-out;} /* 省略... */

然后我们只需要在Message类的close方法中做一下改变:

 close { // 首先把move-in这个弹出动画类给移除掉,要不然会有问题,可以自己测试下 messageEl.className = messageEl.className.replace; // 增加一个move-out类 messageEl.className += 'move-out'; // move-out动画结束后把元素的高度和边距都设置为0 // 由于我们在css中设置了transition属性,所以会有一个过渡动画 messageEl.addEventListener => { messageEl.setAttribute('style', 'height: 0; margin: 0'); }); // 这个地方是监听transition的过渡动画结束事件,在动画结束后把消息从dom树中移除。 messageEl.addEventListener => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove; }

结尾好了,基本上已经写好了,不过为了各个浏览器的兼容性,建议大家用babel转码,如果想发布,可以用webpack把js和css一块打包。不过我们还是少考虑了一个场景,现在的关闭消息都是对象内部调用close方法来实现,如果我们希望外部能够控制消息的关闭呢,比如我请求服务器时候弹出一个loading的消息,现在服务器返回数据后,我怎么来关闭这个消息呢。很简单,各位自行实现吧!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

上一篇:没有了 下一篇:腾讯技术委员会正式成立www.4242.com