欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

CSS分层动画可以让元素沿弧形路径运动

来源:本站整理 作者:佚名 时间:2016-07-31 TAG: 我要投稿

CSS 的animations (动画) 和transitions(变换)擅于实现从点 A 到点 B 的直线运动,运动轨迹是直线路径。给一个元素添加了 animation 或者 transition 以后,无论你如何调整贝塞尔曲线,都无法让它沿着弧形路径运动。你可以通过自定义 timing function 属性,做出弹动的效果,但是它沿着 X 和 Y 轴相对移动的值永远是相同的。
与其使用 JavaScript 实现外观自然的运动,不如尝试用这种简单的方式:分层动画,绕过已有的限制。通过使用两个或多个元素实现动画效果,我们可以更加细粒度地控制某个元素的路径,沿着 X 轴运动使用一种 timing function ,沿着 Y 轴运动使用另一种 timing function 。
问题所在

当我们深入探讨解决方案之前,看看到底问题在哪。CSS animations 和 transitions 限制我们只能沿直线路径运动。元素总是沿着点 A 到点 B 的最短路径运动,如果我们另辟蹊径,告诉 CSS 沿着“更好的路径”,而不是“最短路径”运动呢?
用 CSS (开启硬件加速)实现两点之间的运动,最直截了当的方式是使用 transform 的 translate 在一定时间内移动某个元素。这就产生了直线运动。在 @keyframes 中,我们打算在 (0,0) 和 (100,-100) 间来回运动,见上图例子:
@keyframes straightLine {
  50% {
    transform: translate3D(100px, -100px, 0);
  }
}
.dot {
  animation: straightLine 2.5s infinite linear;
}
这些看起来并不难懂,但我们稍等片刻,思考一下我们需要的解决方案,拆分开来的动画,视觉上长什么样子呢。
0% 时,元素从 (0,0) 出发, 50% 时,我们用了 translate3D(100px, -100px, 0) 把它移动到 (100,-100) ,然后原路返回。换句话说,我们把元素向右移动了 100px ,向上移动了 100px ,两个方向联合作用使元素沿着一个角度运动。

解决方案:每个轴执行自己的动画函数
那么,原先展示的例子中我们如何实现的弧形路径呢?为了让创建的路径不是直线,我们想让元素沿 X 轴和 Y 轴的运动速度不同步。
先前例子中都用到了 linear 线性运动函数,如果我们给运动的元素包裹一个容器,我们可以为 X 轴应用一种动画函数, Y 轴应用另一种动画函数。以下例子,我们在 X 轴使用 ease-in , Y 轴使用 ease-out 。

每个轴元素的具体实现
不幸的是,我们不能只把 transform 动画简单叠加:因为只有最后声明的动画会执行。那么我们如何把两个动画效果联合起来呢?可以把一个元素放入另一个元素内部,给容器元素加一种动画,给里面的子元素添加另一种动画。
在以上例子中,你已经看到一个点沿着弧形路径运动,看到两个独立的元素一起做动画,只不过容器元素是完全透明的。为了清晰地看到两个元素沿着弧形路径是如何相互作用的,我们给容器元素加个边框看看呗:

那个点藏在带边框的盒子内部,跟随盒子一起沿 X 轴远动,同时它自己又在 Y 轴方向上下运动。去掉容器盒子的边框,我们就得到了弧形路径。与其在 HTML 中用两个元素,还不如用伪元素实现嘞。如果 HTML 是这样:
我们可以添加伪元素:
.dot {
  /* 容器:沿 X 轴运动 */
}
.dot::after {
  /* 黑点儿,沿 Y 轴运动 */
}
然后,我们需要两块独立的动画代码: X 轴, Y 轴各一块。注意一处用了 ease-in ,另一处用了 ease-out :
.dot {
  /*省略 一些布局代码...*/
  animation: xAxis 2.5s infinite ease-in;
}
.dot::after {
  /* 渲染小黑点儿*/
  animation: yAxis 2.5s infinite ease-out;
}
@keyframes xAxis {
  50% {
    animation-timing-function: ease-in;
    transform: translateX(100px);
  }
}
@keyframes yAxis {
  50% {
    animation-timing-function: ease-out;
    transform: translateY(-100px);
  }
}
加上 WebKit 前缀,用一些自定义的贝塞尔曲线代替 ease-in 和 ease-out ,我们就可以实现文章最开头展示的效果:
.demo-dot {
  -webkit-animation: xAxis 2.5s infinite cubic-bezier(0.02, 0.01, 0.21, 1);
  animation: xAxis 2.5s infinite cubic-bezier(0.02, 0.01, 0.21, 1);
}
.demo-dot::after {
  content: '';
  display: block;
  width: 20px;
  height: 20px;
  border-radius: 20px;
  background-color: #fff;
  -webkit-animation: yAxis 2.5s infinite cubic-bezier(0.3, 0.27, 0.07, 1.64);
  animation: yAxis 2.5s infinite cubic-bezier(0.3, 0.27, 0.07, 1.64);
}
@-webkit-keyframes yAxis {
  50% {
    -webkit-animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1);
    animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1);
    -webkit-transform: translateY(-100px);

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载