rccoder / blog

😛 个人博客 🤐 订阅是 watch 是 watch 是 watch 是 watch
584 stars 36 forks source link

你不知道的 transition 与 animation #11

Open rccoder opened 8 years ago

rccoder commented 8 years ago

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

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

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

即:

transition: property duration timing-function delay;

需要注意的有下面几点:

就实际情况来说,利用 :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

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

JS Bin on jsbin.com

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

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

<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

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

ahonn commented 8 years ago

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

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

rccoder commented 8 years ago

@ahonn 恩,谢谢指导

lscho commented 8 years ago

把vue这部分写一下啊

zanseven007 commented 8 years ago

可以的!拓展文章不错

sdvcrx commented 8 years ago

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

.box-switch-on {
  /* left: 147px; */
transform: translateX(147px);
}
rccoder commented 8 years ago

@banbanchs Thx,已经注明

codetodamoon commented 8 years ago

norfish commented 6 years ago

luckyscript commented 6 years ago