百度前端技术学院是一个为大学生创办的免费的前端技术实践、分享、交流平台。由百度校园招聘组、百度校园品牌部、百度前端技术部以及多个百度的前端团队联合创办。学院组织了一批百度在职工程师,精心编写了数十个实践编码任务,将技术知识点系统有机地串联在各个充满趣味与挑战的任务中,同学们通过实际地编码练习来掌握知识,再辅以互相评价、学习笔记等方式,加深对于学习内容的理解。在过去的三年中,百度前端技术学院累积吸引了上万名同学参加,并且有数十名同学在学习后,顺利加入了百度,成为了百度的前端工程师。

分别用Transition和Animation实现往返的动画效果

作者马腾课程任务五:听指令的小方块(二)3776次浏览102017-03-31 16:07

问题描述

任务五:听指令的小方块(二)中有实现转动过渡效果的要求。如直接转动小方块,小方块的四个角在转动过程中必定会突出棋盘格,影响美观。若能在转动前将给小方块加个圆角 border-radius: 50%,旋转动画后再改回 border-radius: 0,岂不妙哉~


一. 用Animation实现

既然圆角需要先从0到50%,再从50%到0,首先想到的就是可以实现往返效果的animation了。代码如下
CSS

//朝上的情况下左转的动画
@keyframes tl {
  0% {
    border-radius: 0;
    transform: rotate(0deg);
  }
  33% {
    border-radius: 50%;
    transform: rotate(0deg);
  }
  67% {
    border-radius: 50%;
    transform: rotate(-90deg);
  }
  100% {
    border-radius: 0;
    transform: rotate(-90deg);
  }
}
//设置通用的动画CSS
animation-duration: 3s;
animation-fill-mode: forwards;
  • 其他朝向不同转动方向的动画就不列举了,可以通过修改rotate的角度实现
  • 当然,也可以只设置一个rotate动画,然后在JS中修改动画效果

JS

//取得小方块
var box = …
//当小方块朝上,向左转时
style.animationName = “tl”;
  • 其他朝向不同转动方向的animation赋值就不列举了
  • forwards是必须的,表示转动后显示动画100%的状态。如果不加forwards,则需要在给box加一个transform: rotate(N deg)的CSS,否则box会在转动后变为朝上。

二. 用Transition实现

Trasnsition,可以显示某个元素从状态1到状态2的过渡动画,而且与Animation相比,需要的代码量更少。但如果需要再从状态2返回状态1,单纯用CSS好像无法实现,需要借助JS。
先来实现从状态1到状态2吧,从方角到圆角,然后再转个向。代码如下
CSS

transition-property: transform, border-radius;
transition-time: 1s, 1s;
transition-delay: 1s, 0s;

JS

//取得小方块
var box = …
//设置CSS
box.style.transform = "rotate(" + N*90 + "deg)";
box.style.borderRadius = “50%”;

至此,状态1到状态2已经实现了。接下来就是状态2到状态1了。
从状态1到状态2设置了1s+1s的过渡时间,那么在2s末,需要将border-radius的值修改为0。延迟2s运行某些代码,很自然的就能想到 setTimeout。代码就不列了。

其实,我不是来推销setTimeout的,我是来安利transitionend事件的——
从字面意思来理解,就可以知道transitionend事件是在过渡动画完成时触发的。transitionend事件不仅拥有targettype等一般事件属性,还拥有3个特有的属性:propertyNameelapsedTimepseudoElement,分别表示过渡动画的属性名称(CSS中设置的transition-property)、过渡动画经历的时长以及伪元素名称(如果该过渡动画显示在伪元素上),具体可以参考这里
transitionend事件实现目标的原理也很简单:监听transitionend事件,如果该事件是由transform引起的,则改变borderRadius的值。代码如下

box.addEventListener("transitionend", function(e) {
  if (e.propertyName === "transform"){
    box.style.borderRadius = "0";
  }
});

延伸一下:既然有transitionend事件,是否会有transitionstar事件呢?答案是,有的,而且不仅仅只有transitionstar,还会有transitionrun呢!!!更令人惊讶的是,这两个事件会出现在Firefox 53中,嗯,或许你看到这篇文章的时候,53版本还没有发布...

个人理解,从时效上讲,用transitionend事件还是比用setTimeout靠谱一些的。


三. Animation和Transition的异同

我也不是很清楚,查阅了MDNstackOverflow,也没找出个所以然来。我就参考别人总结的和自己理解的,谈一谈两者在表象上的异同吧。

两者的相似之处

之所以要谈两者的异同,是因为两者比较相近,那么就先来看看两者的相近之处吧。
1. 两者能产生动画效果的property相同,而且都要事先定义需要产生效果的property
2. 两者能接收的timing-function相同,默认值也相同
3. 两者都能在动画前产生延迟
4. 两者都有相应的开始和结束事件
5. 最大的相似之处,两者都能产生动画,且动画效果在视觉上相同

两者的不同之处

  1. 两者的动画的触发形式不同,并由此导致Animation动画播放后,会默认回到动画前的状态
  2. Animation可以轻松实现循环播放、倒序播放、暂停播放等功能,Transition不能
  3. Animation可以轻松实现多步走,既从状态1到状态2再到状态3等等,Transition则需借助于JS

小结:两者有较多的相似之处,且仅用比较简单的JS语句就可以消除两者的不同之处(Animation的暂停播放貌似是个例外),怪不得网上有人说Animation∈Transition,又有人说Transition∈Animation。我都开始怀疑在底层这两者是不是同一个东西。
关于异同,这篇文章写得不错,告诉大家哪种情况下用哪个代码少比较好,大家可以看看。

0条评论