Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

你不知道的 transition 与 animation #11

Open
rccoder opened this issue Jul 31, 2016 · 9 comments
Open

你不知道的 transition 与 animation #11

rccoder opened this issue Jul 31, 2016 · 9 comments
Labels

Comments

@rccoder
Copy link
Owner

rccoder commented Jul 31, 2016

2016-09-19 补充性能相关

题图

石器时代

CSS3 出现之前,网页上的动画都是靠 JavaScript 来实现的,在这个时代,你可能会经常看见这样的代码片段:

setTimeout(funcntion() {
  document.getElementById("test").style.opacity += 0.1;
}, 300)

上面这段代码片段就实现了这个 id 所描述内容的透明度渐变。

这样写起来看上去比较复杂,可维护性也比较差。除此之外,在移动端的性能也很是捉急。

CSS3 时代

石器时代终于过去,黎明已经到来,CSS3 的动画效果也随之而来。

CSS3 中有关动画的常用属性有 transitiontransform

transition

中文释义:"过渡"。最基本的场景在于 :hover 的过渡中:

.box {
  width: 100px;
  height: 200px;
  background: red;
  transition: all 1s ease;
}
.box:hover {
  width: 200px;
  height: 100px;
  background: yellow;
}

JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.38.13"></script>

上面这段代码实现了一个简单的过渡效果,涉及其 width, height, background; 过渡时间为 1s;过渡方式为 ease;在 hover 的时候触发。

transition 这个属性有四个参数: property duration timing-function delay;。分别代码过渡属性,延时时间,过渡方法函数,过渡延迟。

即:

transition: property duration timing-function delay;

需要注意的有下面几点:

  • property 这个位置不是能写所有的属性,比如 display 就是不行的。这是因为需要用 property 来计算过渡的各项指针,像 display 这种么没有明确数值标记的是万万不能达到效果的。
  • timing-function 是一个神奇的东西,如果你曾经接触过 贝赛尔曲线 肯定就知道其中的奥秘了。它的存在会让你的过渡效果不是那么的生硬,不管是淡进淡出还是其他复杂的过渡效果,他都能平滑的处理。一般情况下我们使用常用的ease, ease-in, ease-out, linear 就能满足大部分的需求了,如果你有更高的需求,可以通过http://web.chacuo.net/css3beziertool 来定制。
  • delay 表示延迟,即动画开始的延迟时间
  • 如果要实现多段动画,比如首先大小进行变化,然后背景颜色进行变化也是可以的。 比如: transition: width 1s ease, background 1s ease 1s;

就实际情况来说,利用 :hover 来触发动画往往不是特别实际的。一般情况下,我们在实际开发中都是往往通过添加或删除 class 来触发动画的。

<div id="box"></div>

#box {
  width: 100px;
  height: 200px;
  background: yellow;
}
.red {
  width: 200px;
  height: 100px;
  background: red;
}

window.onload = function() {
  setTimeout(function() {
      document.getElementById("box").className = "red";
  }, 100)
}

JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.38.13"></script>

配合 transform 就能够实现更加酷炫的动画了。

JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.38.13"></script>

除了上面这个简单的旋转,还可以实现更加实用的效果呢 :)

选项卡切换“背景颜色”滑动

<div class="box">
    <div class="box-content" id="box1"></div>
    <div class="box-content" id="box2"></div>
    <div class="box-switch" id="box-switch"></div>
  </div>

.box {
  height: 100px;
  width: 300px;
}
.box {
  position: relative;
}
.box-content {
  display: inline-block;
  height: 100px;
  width: 140px;
  border: 1px solid red;
  cursor: pointer;
}
.box-switch {
  position: absolute;
  left: 1px;
  top: 1px;
  height: 100px;
  width: 140px;
  background: green;
  transition: .15s ease-out;
  transform: translateZ(0); // 开启硬件加速
}
.box-switch-on {
  left: 147px;
}

window.onload = function() {
  var _box1 = document.getElementById("box1"),
      _box2 = document.getElementById("box2");

  var _box_switch = document.getElementById("box-switch");


  _box1.addEventListener('click', function() {
    _box_switch.className = "box-switch";  
  }, false);

  _box2.addEventListener('click', function() {
    _box_switch.className = "box-switch box-switch-on";  
  }, false);

} 

效果如下:

JS Bin on jsbin.com<script src="http://static.jsbin.com/js/embed.min.js?3.38.21"></script>

记得做动画的时候别忘记开启硬件加速,不然在移动设备上可能会有性能问题,更详细的介绍参见在桌面端和移动端用CSS开启硬件加速

如果你不是为了兼容低级 PC 浏览器,最好不要使用 left 的这种方式,因为这样可能会造成重排(reflow/relayout),请使用 transform: translateX(147px); 的这种方式。 相关讨论参见在移动端使用transform: translate代替top left marg等做位移有好处么 ?, 感谢 @banbanchs

关于更加详细的 transform 介绍,可以参见 《好吧,CSS3 3D transform变换,不过如此》

关于 CSS 动画性能问题,可以参见两张图解释CSS动画的性能

animation

用上面所说的 transition 来实现动画无疑是非常优雅的,但是实现动画的种类貌似还是有限制的,那么如何去实现比较随心所欲的动画呢? 这个时候可能就需要 animation 的出场了。

animation 依旧非常简单,它需要你申明动画执行的时间和动画执行的函数即可:

.box {
   width: 100px;
   height: 200px;
   background: red;
 }
 .box:hover {
   animation: 1s rainbow forwards;
 }

@keyframes rainbow {
  50% { 
    width: 200px;
    background: yellow;
  }
  100% { 
    height: 100px;
    background: green;
  }
}

关于更加详细的 animation 介绍可以参见 《CSS 动画简介》

Vue 中怎么搞?

MV* 的框架中,都是不建议对 DOM 进行直接操作的,一般来说,都提供了一些自己框架的接口,比如 Vue 中:

过渡-Vue中文文档

show v-for 都做了一些钩子,我们可以借助这些钩子结合相关的生命周期实现相关的动画。

拓展文章推荐:


捐赠

写文不易,赠我一杯咖啡增强一下感情可好?

alipay

@rccoder rccoder added the CSS label Jul 31, 2016
@ahonn
Copy link

ahonn commented Aug 1, 2016

赞。transition 与 animation 是很好玩的两个东西。

小建议:在 div#box 上添加多一个 class,把 CSS 中 #box 的样式添加到 class 上,不要给 id 加样式,这样就不需要 !important 了。

@rccoder
Copy link
Owner Author

rccoder commented Aug 1, 2016

@ahonn 恩,谢谢指导

@lscho
Copy link

lscho commented Aug 2, 2016

把vue这部分写一下啊

@zanseven007
Copy link

可以的!拓展文章不错

@sdvcrx
Copy link

sdvcrx commented Aug 4, 2016

选项卡切换“背景颜色”滑动例子中,建议是在移动端用 transform: translateX 替换 left 以避免页面重排。

.box-switch-on {
  /* left: 147px; */
transform: translateX(147px);
}

@rccoder
Copy link
Owner Author

rccoder commented Aug 4, 2016

@banbanchs Thx,已经注明

@codetodamoon
Copy link

2 similar comments
@norfish
Copy link

norfish commented Jan 21, 2018

@luckyscript
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants