本文是对 css 的动画应用的简单讨论, 这里的重点是复合运动.
我们知道 css 的动画主要有两种方式过渡 (transition) 和动画 (animation) 来实现.
比如我想鼠标移入时, 旋转一圈, 可以这么做:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- transition:transform 2s linear;
- }
- div:hover{
- transform:rotate(360deg);
- }
- </style>
复合运动, 既旋转又平移呢? 这个很好做, transform 首先是支持复合变换的:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- transition:transform 2s linear;
- }
- div:hover{
- transform:rotate(360deg) translateX(400px);
- }
- </style>
但是实现的效果跟我们想象不一样. 上面效果走的是螺旋线, 这是因为 transform 变换是有顺序的. 上面的写法是先平移, 再旋转, 因此旋转的中心一直再变. 我们可以交换一下顺序:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- transition:transform 2s linear;
- }
- div:hover{
- transform:translateX(400px) rotate(360deg);
- }
- </style>
之前的效果是旋转和平移的时间都是两秒. 我希望平移的时间是 1s, 那么只用 transform 应该是做不到的. 我们可以使用 transition 的复合运动:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- position:relative;
- left:0;
- transition:transform 2s linear, left 1s linear;
- }
- div:hover{
- transform:rotate(360deg);
- left:400px;
- }
- </style>
因为旋转的时间是平移的两倍, 因此效果是平移完时, 旋转才进行了一半.
如果我希望效果是反过来的, 即先旋转 1s, 然后再边平移边旋转, 可以使用延迟:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- position:relative;
- left:0;
- transition:transform 2s linear, left 1s 1s linear;
- }
- div:hover{
- transform:rotate(360deg);
- left:400px;
- }
- </style>
此时我又希望情况变成这样, 不要之前一秒的旋转了, 直接从旋转的一半开始, 边旋转边平移.
此时要使用负延迟:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- position:relative;
- left:0;
- transition:transform 2s -1s linear, left 1s linear;
- }
- div:hover{
- transform:rotate(360deg);
- left:400px;
- }
- </style>
transition 不是强大的动画, 有很多局限性.
第一, 不支持无限动画.
第二, 触发条件需要属性变化.
而 animation 比较强大, 用 "帧" 的观点来说, transition 只是 animation 的一帧.
比如说 2 次旋转:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:rotate 2s linear 2;
- }
- @keyframes rotate{
- 100%{
- transform:rotate(360deg);
- }
- }
- </style>
旋转加平移:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:animate 2s linear infinite;
- }
- @keyframes animate{
- 100%{
- transform:translateX(400px) rotate(360deg);
- }
- }
- </style>
我希望像过渡一样, 移入旋转平移, 移出是逆向操作. 那么 animation 能实现反复式旋转吗?
答案是可以的, 定义旋转方向为 alternate:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:animate 2s linear infinite alternate;
- }
- @keyframes animate{
- 100%{
- transform:translateX(400px) rotate(360deg);
- }
- }
- </style>
上面的交替效果也可以通过中间帧的方式来实现:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:animate 4s linear infinite;
- }
- @keyframes animate{
- 50%{
- transform:translateX(400px) rotate(360deg);
- }
- }
- </style>
animation 也是有复合效果的, 因而可以实现交替动画.
比如, 先旋转 1s, 然后再平移 1s, 然后再放缩 1s:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:rotate 1s linear,translate 1s 1s linear,scale 1s 2s linear;
- }
- @keyframes rotate{
- 100%{
- transform:rotate(360deg);
- }
- }
- @keyframes translate{
- 100%{
- transform:translateX(400px);
- }
- }
- @keyframes scale{
- 100%{
- transform:scale(1.5);
- }
- }
- </style>
但是效果还是跟我们想象中的不太一样, 我们希望平移后直接再那个位置进行放缩.
因此我们要在最后那个动画上做点文章:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:rotate 1s linear,translate 1s 1s linear,scale 1s 2s linear;
- }
- @keyframes rotate{
- 100%{
- transform:rotate(360deg);
- }
- }
- @keyframes translate{
- 100%{
- transform:translateX(400px);
- }
- }
- @keyframes scale{
- 0%{
- transform:translateX(400px);
- }
- 100%{
- transform:translateX(400px) scale(1.5);
- }
- }
- </style>
此效果只用一个动画的关键帧应该也能做到, 留作作业.
这里再讨论一个时期, 我们希望整个动画停留在最后一帧的最终效果上, 那么请使用 forwards:
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:rotate 1s linear,translate 1s 1s linear,scale 1s 2s linear forwards;
- }
- @keyframes rotate{
- 100%{
- transform:rotate(360deg);
- }
- }
- @keyframes translate{
- 100%{
- transform:translateX(400px);
- }
- }
- @keyframes scale{
- 0%{
- transform:translateX(400px);
- }
- 100%{
- transform:translateX(400px) scale(1.5);
- }
- }
- </style>
能否运动中, 当我 hover 时, 希望暂停:
也可以做到
html 代码
- <div>div</div>
- <style>
- div{
- margin:100px;
- width:100px;
- height:100px;
- background:#00ffff;
- animation:rotate 1s linear,translate 1s 1s linear,scale 1s 2s linear forwards;
- }
- @keyframes rotate{
- 100%{
- transform:rotate(360deg);
- }
- }
- @keyframes translate{
- 100%{
- transform:translateX(400px);
- }
- }
- @keyframes scale{
- 0%{
- transform:translateX(400px);
- }
- 100%{
- transform:translateX(400px) scale(1.5);
- }
- }
- div:hover{
- animation-play-state:paused;
- }
- </style>
最后总结一下, 本文通过简单例子尽量涉及了动画的方方面面. 对动画感兴趣的同学可以参考一下,
https://notes/17398/b76d11cd99f4d9488ff13e834db4c78b.html
本文完.