专栏首页程序员的诗和远方CSS3动画-抛物线运动

CSS3动画-抛物线运动

今天来说下CSS3动画,目标是让一个方块做抛物线运动。主要用到的CSS3属性有animation,transform,@keyframes,transition等。


Animation版-0

我们先建立一个HTML文件,test.html:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" type="text/css" href="animation.css"/>
</head>
<body>
<div class="item"></div> 
</body>
</html>

因为animation属性可以通过@keyframes 规则创建动画,那么如果我们要做抛物线,可以尝试简单定义几个阶段的位置。 编写我们的CSS文件,animation.css:

.item {
  width:50px;
  height: 50px;
  display: inline-block;
  position: absolute;
  top: 100px;
  background-color: red;
}

div { 
      animation: example 3s linear 1s 1; 
      -webkit-animation: example 3s linear 1s 1;
      -moz-animation: example 3s linear 1s 1;
 }

@-moz-keyframes example { 
     0% { transform: translate3d(0px, 0, 0);        } 
     25% { transform: translate3d(100px, -40px, 0); }
     50% { transform: translate3d(200px, -56px, 0); }
     75% { transform: translate3d(300px, -68px, 0); } 
    100% { transform: translate3d(400px, -80px, 0); } 
}
 @-webkit-keyframes example { 
     0% { transform: translate3d(0px, 0, 0);        } 
     25% { transform: translate3d(100px, -40px, 0); }
     50% { transform: translate3d(200px, -56px, 0); }
     75% { transform: translate3d(300px, -68px, 0); } 
    100% { transform: translate3d(400px, -80px, 0); } 
}

运行一下,只能用惨不忍睹来形容了。写到这里肯定要被喷了,这简直就是坑爹啊。 首先这种做法并不是抛物线,只是几段线段拼在一起,如果把百分比做的细一点,可以类似于抛物线,但是大大加大了coding的时间,而且只是在模拟抛物线,还不如使用抛物线的公式,通过javascript去计算每个点的坐标。

这一版是纯粹的反面教材。


Animation版-1

重新分析一下这个问题,抛物线其实是水平方向的匀速运动和垂直方向的匀加速运动。那么我们可以在item外面套一个div,里面那个控制水平方向的运动,速度曲线用linear,外面那个控制垂直方向的运动,速度曲线用ease-in。 test.html:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" type="text/css" href="animation.css"/>
</head>
<body>
<div class="wraper"><div class="item"></div></div>
</body>
</html>

然后是animation.css:

.item, .item2 {
  width:50px;
  height: 50px;
  display: inline-block;
  position: absolute;
  top: 100px;
  left: 0px;
  background-color: red;
}
.wraper {
    animation: vertical-animation 3s ease-in 1s 1; 
    -webkit-animation: vertical-animation 3s ease-in 1s 1;
    -moz-animation: vertical-animation 3s ease-in 1s 1;
}

.wraper .item {
    animation: hor-animation 3s linear 1s 1; 
    -webkit-animation: hor-animation 3s linear 1s 1;
    -moz-animation: hor-animation 3s linear 1s 1;
}

@-moz-keyframes hor-animation { 
    0% { transform: translateX(0px);     } 
    100% { transform: translateX(400px); } 
}
 @-webkit-keyframes hor-animation { 
    0% { transform: translateX(0px);     } 
    100% { transform: translateX(400px); }
}

@-moz-keyframes vertical-animation { 
    0% { transform: translateY(0px);     } 
    100% { transform: translateY(400px); } 
}
 @-webkit-keyframes vertical-animation { 
    0% { transform: translateY(0px);     } 
    100% { transform: translateY(400px); } 
}

ok,运行一下,不错像个抛物线。


Transition版-1

刚才那种方式,需要多加一个dom元素,那有没有办法不加呢。当然有,可以对postion:absolute使用transition属性,分别控制top和left的变化,top变化时间曲线为ease-in,left变化的时间曲线为linear。 我们加多一个item2来做这件事情: test.html:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" type="text/css" href="animation.css"/>
</head>
<body>
<div class="wraper"><div class="item"></div></div>
<div class="item2"></div>
<script type="text/javascript" src="animation.js"></script>
</body>
</html>

animation.css:

.item, .item2 {
  width:50px;
  height: 50px;
  display: inline-block;
  position: absolute;
  top: 100px;
  left: 0px;
  background-color: red;
}

.wraper {
    animation: vertical-animation 3s ease-in 1s 1; 
    -webkit-animation: vertical-animation 3s ease-in 1s 1;
    -moz-animation: vertical-animation 3s ease-in 1s 1;
}

.wraper .item {
    animation: hor-animation 3s linear 1s 1; 
    -webkit-animation: hor-animation 3s linear 1s 1;
    -moz-animation: hor-animation 3s linear 1s 1;
}

@-moz-keyframes hor-animation { 
    0% { transform: translateX(0px);     } 
    100% { transform: translateX(400px); } 
}
 @-webkit-keyframes hor-animation { 
    0% { transform: translateX(0px);     } 
    100% { transform: translateX(400px); }
}

@-moz-keyframes vertical-animation { 
    0% { transform: translateY(0px);     } 
    100% { transform: translateY(400px); } 
}
 @-webkit-keyframes vertical-animation { 
    0% { transform: translateY(0px);     } 
    100% { transform: translateY(400px); } 
}

.item2 {
  top: 150px;
  left: 0px;
  transition: top 3s ease-in 1s,
        left 3s linear 1s;
  -webkit-transition: top 3s ease-in 1s,
            left 3s linear 1s;
  -moz-transition: top 3s ease-in 1s,
           left 3s linear 1s;
}

这里我们需要多加一个javascript文件来控制item2 top和left属性的改变。 animation.js:

window.onload = function(){
  var item2 = document.querySelector(".item2");

  item2.style.top = "550px";
  item2.style.left = "400px";
}

ok,运行一下,也是一个抛物线运动。


问题来了

首先是item和item2的运动不一致,item总是比item2先运动。 是不是页面载入的问题,那我们稍微改动一下,让他们尽量是同时运动的。 在css中,先让item暂停,

.wraper {
    animation: vertical-animation 3s ease-in 1s 1; 
    -webkit-animation: vertical-animation 3s ease-in 1s 1;
    -moz-animation: vertical-animation 3s ease-in 1s 1;
    animation-play-state:paused;
    -webkit-animation-play-state:paused;
}

.wraper .item {
    animation: hor-animation 3s linear 1s 1; 
    -webkit-animation: hor-animation 3s linear 1s 1;
    -moz-animation: hor-animation 3s linear 1s 1;
    animation-play-state:paused;
    -webkit-animation-play-state:paused;
}

这里通过添加animation-play-state:paused来让动画一开始是暂停的。 在javascript中控制动画的运行,以及item2的top和left值得改变。

window.onload = function(){
  var item2 = document.querySelector(".item2"),
    item = document.querySelector(".item"),
    warper = document.querySelector(".warper");

  item2.style.top = "550px";
  item2.style.left = "400px";
  item.style.animationPlayState = "running";
  item.style.webkitAnimationPlayState = "running";
  warper.style.animationPlayState = "running";
  warper.style.webkitAnimationPlayState = "running";
}

好了,再运行一下,还是item先运动。并且感觉item2有点卡顿。

GPU硬件加速

这里终于要说到重点了,我们打开chrome的调试工具,观察一下两种方案的paint耗时。 首先是transition版,也就是item2.

可以看到,其中绿色的那一块,大概是有96ms花在painting上。 然后我们再看看animation版的,也就是item:

哇,花在painting上的时间只有0.68ms。 进一步咋网上搜索了一下,原来是使用translate会触发硬件加速。大大缩短的painting的时间。transition呢没有利用到硬件加速,而且会触发多次repaint,所以会感觉有点卡顿,不够流畅。


结语

首先,我们分析问题的时候,不应该只是看到事物的表面行为不应该单纯的模拟表面,而应该思考本质。就像做抛物线,不能只是模拟运动轨迹,而更应该理解抛物线运动的实质。 还有,不禁要感叹一句,CSS3还真是博大精深啊。

参考:

http://blog.bingo929.com/transform-translate3d-translatez-transition-gpu-hardware-acceleration.html http://www.admin10000.com/document/4339.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 20180930_ARTS_week14

    想到这个的思路是因为解的过程中,发现如果遇到左边的,需要存起来,后面可能有用(类似入栈),遇到右边的,需要比对前一个值,并且比完如果匹配就没用了(这类似出栈)。...

    Bob.Chen
  • 20180708_ARTS_week02

    Add Two Numbers You are given two non-empty linked lists representing two non-ne...

    Bob.Chen
  • Canvas画图-鼠标移动图形

    之前那篇Canvas画图-鼠标涂鸦已经可以实现与Canvas的简单交互,这篇会介绍Canvas中实现交互性的一个重要方法isPointInPath。 基本...

    Bob.Chen
  • css3 动画应用 animations 和transtions transform在加上JavaScript 可以实现硬件加速动画。

    transitions(过渡) 被应用于元素指定的属性变化时,该属性经过一段时间逐渐的过渡到最终想要的值。   主要包括四个属性:     执行变换的属性:...

    用户1197315
  • 网页|CSS的动画实现

    一些CSS属性是可以实现动画效果,即我们可以用CSS实现动画和过渡。而动画属性的实现其实就是,属性逐渐地从一个值变化到另一个值,比如尺寸大小、数量、百分比和颜色...

    算法与编程之美
  • 系统时间——ntpd 原

    The ntpd program is an operating system daemon which sets and maintains the syst...

    阿dai学长
  • 如何管理好10万行代码的前端单页面应用

    蚂蚁金服数据平台前端团队主要负责多个数据相关的PC Web单页面应用程序,业务复杂度类比Excel等桌面应用,业务前端代码量在几万行~几十万行,随着产品不断完善...

    疯狂的技术宅
  • 专访华热科技高级架构师刘紫健:没有大数据,智慧供热的目标就无法达成

    华热科技高级架构师 刘紫健 智慧供热是实现“智慧城市”建设中极其重要的一个环节,而大数据和智慧供热的关系更是密不可分。那么,到底什么是智慧供热?供热和大数据有...

    数据猿
  • 如何利用云安全运营中心监测数据泄露

    ➢5月,三星手机厂商多个内部项目代码泄露,包括SmartThings敏感的源代码、证书和密钥。

    王录华
  • 数据泄露到底有哪些危害? IBM《2019 年全球数据泄露成本报告》出炉

    IBM 安全事业部日前公布了一项年度调研结果,揭示了数据泄露对企业财务产生的影响。报告表明,过去 5 年数据泄露成本上升了 12%,目前数据泄露的平均成本已达到...

    数据猿

扫码关注云+社区

领取腾讯云代金券