之前在CodePen上接触了TweenMax, 被它能做到的酷炫效果震撼了. (文末放了5个GSAP的效果GIF)

最近要做一个"收集水滴"的动效, 于是就试用了一下TweenMax实现这个效果.

什么是TweenMax

TweenMax是GSAP(GreenSock Animation Platform)创作的动画工具库. GSAP的产品除了TweenMax, 还有:

TweenMax就是GSAP的"全家桶", 包含了TweenLite, TimelineLite, TimelineMax, CSSPlugin, AttrPlugin, RoundPropsPlugin, DirectionalRotationPlugin, BezierPlugin 和 EasePack.

想起步, 先看看这个Get Started里的视频就好了.

最简单的用法就是TweenMax.to(element, duration, options);, 例如

TweenMax.to('.drop', 3, { x: 100, scale: 2, backgroundColor: #aaa })

可以让.drop元素在3秒内, 水平移动100px, 放大一倍, 背景色变为#aaa.

实现

<!-- jade -->
.container
.drop
.tank

HTML很简单, 就是.container里面一个.drop一个.tank.

以下JS让.drop飘起来飞向.tank.

var collectDrop = function() {
var $drop = $('.drop:not(.anim)'),
$tank = $('.tank'),
from = $drop.position(),
to = $tank.position(),
// 计算从水滴中心到水缸中心所需要的偏移量.
x = to.left - from.left + ($tank.width() - $drop.width()) / 2,
y = to.top - from.top + ($tank.height() - $drop.height()) / 2,
// 创建动画用水滴
$el = $drop.clone().addClass('anim').appendTo('.container'),
tl = new TimelineMax();
// 水滴升起
tl.to($el, 2, {
y: -$el.height() * 3,
scale: 2,
ease: Elastic.easeOut.config(1, 0.4)
})
// 水滴飞向水缸
.to($el, .5, {
x: x,
y: y,
backgroundColor: '#832fc2',
scale: .5,
ease: Power1.easeIn,
onComplete: function() {
$el.remove();
}
})
// 水缸动效
.to($tank, .1, {
scale: 1.3
})
.to($tank, .1, {
scale: .8
})
.to($tank, .1, {
scale: 1
});
};

这里为了实现一连串动画, 所以使用了TimelineMax. 由于script中引入了TweenMax, 所以TimelineMax也就自动被引入了.

CodePen如下, 你只要点击水滴就可以看到收集效果了.

See the Pen tweenmax collect drop by Richard Liu (@lzl124631x) on CodePen.

上面的代码中关于动效的选项, 用到了xy以利用transform变换位置, scale改变大小, backgroundColor修改颜色, onComplete为动画完成时的callback, ease设置动画的easing效果.

GSAP Ease Visualizer中可以看到更多的easing效果, 你还可以在这里修改参数, 查看效果, 然后将满意的代码复制出来.

水滴CSS

题外话, 本来只是做个动效, 元素的外观是次要的. 不过好奇能不能直接用CSS做出水滴效果, 就搜了一下"droplet css", 竟然真有这么做的. 其实原理不难(可就是想不到啊=,.=), 就是利用border-radius生成一个斜着的水滴, 然后旋转45度.

.droplet {
width: 4em;
height: 4em;
border-radius: 80% 0 55% 50% / 55% 0 80% 50%;
background-color: #07C;
transform: rotate(-45deg);
}

效果如下:

.droplet {
display: inline-block;
width: 4em;
height: 4em;
border-radius: 80% 0 55% 50% / 55% 0 80% 50%;
background-color: #07C;
transform: rotate(-45deg);
}
.droplet.before {
transform: none;
}

旋转45度后⟹

enjoycss.com上还有不少有意思的实现, 比如爱心.

(不过刚发现enjoycss.com还是alpha版本, 很多bug...比如这个爱心点进去看到的css就是有问题的)

我在这个爱心css的基础上加了个CSS动效, 让心脏活了起来, CodePen.

.heart {
display: block;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
width: 100px;
height: 90px;
position: relative;
animation: heartbeat .5s infinite;
}

.heart:before,
.heart:after {
display: block;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
width: 50px;
height: 80px;
position: absolute;
content: "";
-webkit-border-radius: 50px 50px 0 0;
border-radius: 50px 50px 0 0;
background: red;
}

.heart:before {
top: 0;
left: 50px;
-webkit-transform: rotateZ(-45deg);
transform: rotateZ(-45deg);
-webkit-transform-origin: 0 100% 0;
transform-origin: 0 100% 0;
}

.heart:after {
top: 0;
left: 0;
-webkit-transform: rotateZ(45deg);
transform: rotateZ(45deg);
-webkit-transform-origin: 100% 100% 0;
transform-origin: 100% 100% 0;
}

@keyframes heartbeat {
80% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}

动画过程中水滴的毛边问题

细心的人应该注意到了, 我上面的效果图中, 水滴在放大之后有比较明显的毛边. 我测试了下, 一旦动画停止, 毛边就消失了.

针对这个问题搜了一下, CodePen上有一个解决方案.

它的解决方法是: 假设动画中最大的放大比例是2倍, 那么一开始绘制元素的时候就用2倍的大小去绘制, 初始使用transform: scale(.5)缩小到正常比例, 然后动画放大的时候用scale(1).

我试了一下, 的确管用. 更新后的CodePen如下:

See the Pen tweenmax collect drop by Richard Liu (@lzl124631x) on CodePen.

效果图如下:

但是这个方法不够优雅, 于是继续搜了搜, 比如这个SO问题. 可是我试遍了文中讲的方法, 包括translateZ(0), -webkit-backface-visibility: hidden;, filter: blur(0);, 可惜都不管用(T_T).

请大神出手.

参考

  1. enjoycss.com
  2. GreenSock Learning Center

附上几个GSAP的酷炫CodePen, 大家感受下, CodePen上搜索GSAP或TweenMax还有很多.

  1. Draft Countdown

  2. Making muscles with MorphSVG

  3. Paranoid vs shy birds (很搞笑, 移动鼠标会让中间那只鸟转头, 两边的两只鸟会偷偷地看中间那只, 如果被中间那只发现了会脸红低头)

  4. holy running cow (有一种MineCraft的赶脚)

  5. morph guy

JS动画 | 用TweenMax实现收集水滴效果的更多相关文章

  1. 原生js动画效果(源码解析)

    在做页面中,多数情况下都会遇到页面上做动画效果,大部分都是用jquery来实现动画,今天正好看到一篇原生js实现动画效果的代码,特分享在此. 原文地址:http://www.it165.net/pro ...

  2. js 动画效果实现

    1. 实现方式 - 应用场景 自己写 - 简单的.不用 jq 的项目 jq - 普通动画 成熟插件 - 复杂动画 2. 相关文章 JavaScript基于时间的动画算法 九种原生js动画效果 Twee ...

  3. TouchPoint.js – 可视化展示 HTML 原型点击效果

    TouchPoint.js 是一个用于 HTML 原型展示的 JavaScript 库(作为UX过程的一部分),通过视觉表现用户在屏幕上的点击.TouchPoint 是高度可定制,非常适合屏幕录制,用 ...

  4. 【06-23】js动画学习笔记01

    <html> <head> <style> * { margin:0; padding:0; } #div1{ width:200px; height:200px; ...

  5. css动画与js动画的区别

    CSS动画 优点: (1)浏览器可以对动画进行优化.   1. 浏览器使用与 requestAnimationFrame 类似的机制,requestAnimationFrame比起setTimeout ...

  6. CSS VS JS动画,哪个更快[译]

    英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js ...

  7. Midnight.js – 实现奇妙的固定头部切换效果

    Midnight.js 是一款 jQuery 插件,在页面滚动的时候实现多个头设计之间的切换,所以你总是有一个头与它下面的内容层叠,看起来效果很不错. Midnight.js 可以让你轻松实现这种切换 ...

  8. 使用 HTML5 Canvas 绘制出惊艳的水滴效果

    HTML5 在不久前正式成为推荐标准,标志着全新的 Web 时代已经来临.在众多 HTML5 特性中,Canvas 元素用于在网页上绘制图形,该元素标签强大之处在于可以直接在 HTML 上进行图形操作 ...

  9. Space.js – HTML 驱动的页面 3D 滚动效果

    为了让我们的信息能够有效地沟通,我们需要创建用户和我们的媒体之间的强有力的联系.今天我们就来探讨在网络上呈现故事的新方法,并为此创造了一个开源和免费使用的 JavaScript 库称为 space.j ...

随机推荐

  1. 反编译.o到.cpp

    反编译.o到.cpp 现在有很多反编译是对Java的,而.cpp的很少 因为不同的平台.cpp生成的.o是不一样的,但是Java因为有虚拟机的中间作用,生成的.o在不同平台是一样的 反编译的机理 (通 ...

  2. 返璞归真vc++之感言

    本人自述,大专学历,感觉自己也属于好学型学生,历任班上学习委员3年有余,参与学校项目几多个,不知道不觉从11年毕业已有3个年头,3年来,不敢苟同自己的生活方式,奈何人生无奈..从刚开始的电子商务公司转 ...

  3. Unity3D编程回忆录,Unity3d视频教程,教父团队倾情之作

    之前一直在看Unity3d的视频教程,包括很多老外的视频教程,老外的教程确实不错,技术含量很高,而且讲得很激情,让我有种恨不得一秒钟就想吧unity3d学个精通的冲动,只是,毕竟是英语教程,没办法,哎 ...

  4. select绑定json数组对象 asp.net

    ashx处理页 string JsonList = "["; IList<Models.Channel> ilist = BLL.ChannelManager.GetA ...

  5. php微信支付(仅pc端扫码支付模式二)详细步骤.----仅适合第一次做微信开发的程序员

    本人最近做了微信支付开发,是第一次接触.其中走了很多弯路,遇到的问题也很多.为了让和我一样的新人不再遇到类似的问题,我把我的开发步骤和问题写出来,以供参考. 开发时间是2016/8/10,所以微信支付 ...

  6. ECSHOP购物流程收货人信息详细地址显示省市区

    方法一: 1.在flow.php中的 elseif ($_REQUEST['step'] == 'checkout') 中 $_SESSION['flow_consignee'] = $consign ...

  7. Python 信号量

    信号的概念 信号(signal)--     进程之间通讯的方式,是一种软件中断.一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号. 几个常用信号: SIGINT     终止进程  中断进 ...

  8. 帝国cms中 内容分页的SEO优化

    关于内容页如果存在分页的话,我们想区分第一页和后面数页,当前的通用做法是在标题上加入分页码,帝国cms中如何做到呢.我们可以修改在e/class/functions.php中的源码.找到找到GetHt ...

  9. lua5.3调用C/C++

    马上面临毕业设计,打算做点跟网游有关的,先从做周边工具开始,目前正在做一个协议序列化和反序列化的东西,广告一波先: https://github.com/Anti-Magic/rproto 目前非常简 ...

  10. 微信公众号jssdk使用的惨痛经历

    最近一直在做微信公众号开发,遇到个DT的问题: 大家都知道使用jssdk的时候开发人员必须在后台按照官方文档给定的规则生成签名,我前前个月就写好了这个测试demo页面,而且完全正常能用,像分享等这些功 ...