byzhangxinxu from https://www.zhangxinxu.com/wordpress/?p=7934
一, 回顾之前的 JS 实现
差不多 5 年前, 写了篇文章, 名为 "JavaScript 与元素间的抛物线轨迹运动 http://www.zhangxinxu.com/wordpress/?p=3855"(忽略前面几段的牢骚), 然后写个 JS 方法, 可以实现任意元素的抛物线运动效果, 兼容到 IE6 浏览器, 语法如下:
funParabola(element, target, options);
就可以实现 element 元素到 target 元素的抛物线运动效果, 类似这样:
具体参数含义见原文, 这不不再重复叙述.
实际上, 纯 CSS 也是可以实现 DOM 元素的抛物线运动效果的.
应该是数年前, 我看过一篇外文, 就是水平和垂直运动使用不同的 timing-function 可以得到曲线效果, 记在了脑子里. 然后, 这周一例会上的时候, 和小伙伴提到直接 CSS3 animation 也能实现抛物线效果, 感觉大家有些懵, 知道可以这样, 但完全脑补不出来, 我意识到, 可以写篇文章再重提此技术 tips, 相信还是有很多小伙伴不知道.
二, 效果抢先体验
您可以狠狠地点击这里: CSS3 实现的购物车抛物线运动 demo https://www.zhangxinxu.com/study/201808/css3-parabola-shopping.php
点击 demo 页面的 "加入购物车" 按钮, 即可体验抛物线运动效果, 如下 GIF 截屏:
此抛物线效果的核心就是 CSS 代码实现的. 原理如下:
抛物线运动元素使用至少内外两层标签, 例如, 本 demo 抛物线运动物体是 CSS 世界这本书的缩略图, 我们可以外面一层 <div> , 里面是 <img> 图片:
<div class="fly-item"><img src="./book.jpg"></div>
然后内外两次标签一个负责水平方向的 translate 移动, 一个负责垂直方向的 translate 移动, 然后使用不同的缓动函数, 也就是使用不同的 timing-function , 在 CSS3 animation 动画效果中是
animation-timing-function
属性, 在 CSS3 transition 过渡效果中是
transition-timing-function
属性, 本 demo 使用的是 transition 过渡, 因此, CSS 代码如下:
- .fly-item {
- /* 水平移动, 线性匀速 */
- transition-timing-function: linear;
- }
- .fly-item> img {
- /* 垂直移动, 先慢后快 */
- transition-timing-function: cubic-bezier(.55,0,.85,.36);
- }
然后同时执行 translate 移动, 抛物线效果就出现了.
这其实也不难理解, 比方说我们扔铅球, 其运动轨迹实际上是水平推力和地球引力共同作用的结果, 由于空气阻力可以忽略不计, 因此, 水平方向我们可以看成是匀速运动, 而垂直方向由于重力加速度的存在, 因此会越来越快. 正好和上面 CSS 代码的缓动曲线是一致的, 因此出现了抛物线运动.
还是有些懵? 不急, 下面的效果分解一定可以让你明白.
三, 向量分解与抛物线运动
平常我们是水平垂直位移作用在一个元素上的, 例如:
- .example {
- transform: translate(100px, 100px);
- }
此时, 无论你是动画还是过渡效果, 元素一定是直线运动, 因为 x, y 方向瞬时速度总是一样的. 例如默认 ease 缓动下的 x, y 分解效果图:
可以看到, 虽然运动速度确实有快慢, 但是由于 x, y 同一时间变化的距离是一样的, 因此, 最后的轨迹是一条直线.
但是, 如果我们稍作调整, 把水平运动改成 linear , 垂直运动改成 ease-in , 如下:
- .ball-x { animation-timing-function: linear; }
- .ball-y { animation-timing-function: ease-in; }
我们就可以看到运动轨迹变成弧形了:
是不是有点抛物线的感觉出来了?
ease-in 运动的缓动还不是很强烈, 因此, 抛物线效果不是很重, 我们可以借助 http://cubic-bezier.com/ 工具调一个先慢后快很明显的贝塞尔曲线, 例如
cubic-bezier(.55, 0, .85, .36)
, 如下截图:
- .ball-x { animation-timing-function: linear; }
- .ball-y { animation-timing-function: cubic-bezier(.55, 0, .85, .36); }
此时, 分解和组合 x,y 运动后的实时效果如下:
上面的运动就是本文抛物线 demo 使用的运动效果, 所以抛物线效果的实现的关键就是 x,y 方向运动分解, 同时分别设置不同的缓动.
我们还可以设置 cubic-bezier 值大于 1, 以得到更强烈的带有弹性效果的运动轨迹, 例如:
- .ball-x { animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64); }
- .ball-y { animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1); }
效果如下, 球球直接飞出了田字形区域, 还拐了一个弯:
四, 没有防备的结语
1. demo 页面还有话说
抛物线运动可以纯 CSS 实现, IE10 + 浏览器都可以实现, 移动端页面可以自如使用. 但是, 实际开发还是需要 JS 配合.
demo 页面中可以看到一定量的 JS 代码, 这些 JS 与抛物线效果的运行轨迹并无关系, 只是用来确定抛物线运动的起点和终点.
2. 第 2 个 5 年
时光荏苒, 白驹过隙, 五年时光弹指间一飞而过, 五年可以改变很多东西, 前端圈也不例外, 越来越娱乐圈化, PWA, 轻应用, 小程序, React/vue.js 新技术新应用层出不穷, 大家纷纷表示学不动. 自己也明显感到上年纪了, 和公司小鲜肉们一起打篮球, 发现真的不行了, 爆发力没有了, 以前都是一步过; 弹跳力也没有了, 以前公认篮板王, 弹簧腿; 体能也没有了, 动作容易变形, 不行了不行了, 我要找找除了钓鱼意外其他适合老年人的运动了.
3. 一开始提到的外文
第一段开头提到一个运动曲线的老外的文章, 我谷果了下, 找到了: Moving along a curved path in CSS with layered animation http://tobiasahlin.com/blog/curved-path-animations-in-css/
4. 感谢的话语
感谢同事们积极的反馈, 让我意识到本文的价值所在, 没有他们就没有这篇文章的诞生.
感谢正在阅读本文的你, 忍受文章糟糕的版式和啰嗦的话语还能看到这里, 我给你比个心.
最后, 感谢你对本文的大力转发支持, 谢谢! 谢谢!
来源: http://www.tuicool.com/articles/rMVV7r