CSS Secret——Transitions & Animations
2016-07-08 16:21
441 查看
弹性动画
在真实世界中,很少有物体是线性的从A移动到B。想让你的界面动画显得更加生动,你需要模拟弹性的动画。从技术角度来讲,弹性动画就是在动画达到终止值时,回去一点,再达到终止值时再回去一点,这一点比上一次要小。最终停在终止值。
我们可以使用最强大的关键帧动画来做这件事。
我们使用一个点击input弹出输入提示框来做例子:
<label> Your username: <input id="username" /> <span class="callout">Only letters, numbers, underscores (_) and hyphens (-) allowed!</span> </label>
其基本样式:
.callout { position: absolute; max-width: 14em; padding: .6em .8em; border-radius: .3em; margin: .3em 0 0 -.2em; background: #fed; border: 1px solid rgba(0,0,0,.3); box-shadow: .05em .2em .6em rgba(0,0,0,.2); font-size: 75%; } .callout:before { content: ""; position: absolute; top: -.4em; left: 1em; padding: .35em; background: inherit; border: inherit; border-right: 0; border-bottom: 0; transform: rotate(45deg); }
使用关键帧动画:
@keyframes elastic-grow { from { transform: scale(0); } 70% { transform: scale(1.1); animation-timing-function: cubic-bezier(.1,.25,1,.25); /* Reverse ease */ } } input:not(:focus) + .callout { transform: scale(0); } input:focus + .callout { animation: elastic-grow .5s; } .callout { transform-origin: 1.4em -.4em; }
但是使用关键帧动画在这里有点大材小用了,我们直接使用cubic-bezier()来控制transform的执行程度就好了。
input:not(:focus) + .callout:not(:hover) { transform: scale(0); } .callout { transition: .5s cubic-bezier(.25,.1,.3,1.5) transform; transform-origin: 1.4em -.4em; }
这里当点击input时scale会从0最终变到1,但是由于cubic-bezier()的控制,这个过程并不是单调的,在50%时scale第一次达到1,70%时为1.1,100%时再回到1。这就达到了我们刚才要的效果。
但是这样还不够,在input失去焦点的时候,这个曲线就有问题了,会使scale变为-0.1,这个是不可接受的。于是我们需要一个新的transform来覆盖掉他。不用显示声明,使用默认的ease函数就好。
input:not(:focus) + .callout:not(:hover) { transform: scale(0); transition: .25s transform; } .callout { transition: .5s cubic-bezier(.25,.1,.3,1.5) transform; transform-origin: 1.4em -.4em; }
逐帧动画
有时动画比较复杂,我们不方便使用CSS来创建,而是想用图片一帧一帧的播放,有人说那还不如用gif呢。但是gif不支持透明色,颜色位数太少,不好维护等等,都是问题。我们可以使用一个包含所有帧的PNG sprite,然后使用动画在里面切换。当然这时就不能使用连续的cubic-bezier来控制动画进程了。使用step。这个函数是间断的,可以控制分几步完成动画,这正是我们想要的。
@keyframes loader { to { background-position: -800px 0; } } .loader { width: 100px; height: 100px; background: url(../img/loader.png) 0 0; animation: loader 1s infinite steps(8); }
闪烁效果
闪烁效果可以使用动画来模拟:@keyframes blink-smooth { 50% { color: transparent } } .highlight { animation: 1s blink-smooth 3; }
这样看起来是我们想要的结果,但是要注意的是这里字出现和消失时的时间函数是一样的,都是加速着出现或消失,在这里或许看不出大问题,但是我们还是想要其出现和消失的过程是完全对称的,包括时间函数。
这里就可以使用animation-direction,它可以翻转每一个动画的过程,或者每奇数个,或者每偶数个。
这里我们就可以翻转每偶数个,前面的尾和后面的尾接起来,原来的两个由黑变白的动画过程被合为了一个。时间函数也完全对称了。
@keyframes blink-smooth { to { color: transparent } } .highlight { animation: .5s blink-smooth 6 alternate; }
打字特效
<h1 id="typeEffect">CSS is awesome!</h1> @keyframes typing { from { width: 0 } } @keyframes caret { 50% { border-color: currentColor; } } #typeEffect { width: 15ch; /* Width of text */ overflow: hidden; white-space: nowrap; border-right: .05em solid transparent; animation: typing 6s steps(15), caret 1s steps(1) infinite; }
ch这个单位在大多数字体中可以代表一个字符的长度,所以我们将动画设置为通过15步将宽度从0变为15ch。并设置一个永远闪烁的右边框,模拟输入光标。
状态连续的动画
有很多动画是在用户和它所在的元素有一些交互的时候才开始的,比如用户将鼠标浮动在某个元素上面,这个元素开始应用一些动画。这就涉及到一个问题,当动画还没播完的时候,用户就结束了与该元素的交互,这时的动画该做什么处理?根据具体的使用场景,这里有可能会有两种处理:回到初始状态,等下次交互开始时再重新播放动画,那么回到初始状态的过程我们当然希望还是一个动画的过程,要不就太突兀了;还有一种就是直接暂停动画,下次用户恢复与该元素的交互时,再从上次停下的地方开始动画。
这里要提一下animation和transition的区别:
animation用作动画时,如果在动画未完成时就停止动画的执行,动画会直接跳回初始状态。在动画结束时,会直接跳回初始状态。可以暂停动画
transition用作动画时,如果在动画未完成时就停止动画的执行,动画会反向播放回原始状态。在动画结束时,会停在结束状态。不能暂停动画。
由于存在这些区别,animation和transition天然的就分别适应上面两种情况。
可以用这两个例子试试:
@keyframes test { to { width:400px; } } #testAnimation{ height:100px; width:300px; background-color: #0074d9; color: #fff; } #testAnimation:hover{ animation: test 2s; //width:400px; } #testTransition{ height:100px; width:300px; background-color: #0074d9; transition: 2s width; color: #fff; } #testTransition:hover{ width:400px; }
transition的那种情况比较简单,这里就来说说要暂停动画的那个情况。
@keyframes panoramic { to { background-position: 100% 0; } } .panoramic { width: 150px; height: 150px; background: url('../img/tiger.jpg'); background-size: auto 100%; animation: panoramic 10s linear infinite alternate; animation-play-state: paused; } .panoramic:hover, .panoramic:focus { animation-play-state: running; }
动画用在元素本身,并暂停,在元素获得交互的时候再播放动画。
沿着环形路径的动画
我们想要一个元素沿着环形路径转圈圈。两个元素的办法
<div class="path"> <div class="avatar"> <img src="img/marker_red.png"/> </div> </div>
我们使用这样的HTML结构,path是一个圆形,avatar使用一个以圆为中心的rotate来旋转,当大的div沿着path旋转的时候,里面的img使用另一个小的rotate来抵消,使其一直是正的。
.path { width:300px; height:300px; border-radius: 50%; background-color: #ffbb33; text-align: center; } @keyframes spin { to { transform: rotate(1turn); } } @keyframes spin-reverse { from { transform: rotate(1turn); } } .avatar { animation: spin 3s infinite linear; transform-origin: 50% 150px; /* 150px = path radius */ //display: inline; } .avatar > img { animation: spin-reverse 3s infinite linear; }
这里有优化的空间,这两个动画本质上是一样的,唯一不同的就是顺序,一个是从正着转360度,一个是反着转360度。那么这时,reverse就派上用场了。
@keyframes spin { to { transform: rotate(1turn); } } .avatar { animation: spin 3s infinite linear; transform-origin: 50% 150px; /* 150px = path radius */ } .avatar > img { animation: inherit; animation-direction: reverse; }
一个元素的办法
之前我们使用两个元素,最主要的问题是origin只能有一个,而两个旋转的元素并不是绕着一个点旋转的。但是我们可以绕过origin,看下面这两种变换,其实是同一种:
transform: rotate(30deg); transform-origin: 200px 300px;
transform: translate(200px, 300px) rotate(30deg) translate(-200px, -300px); transform-origin: 0 0;
所以你发现了么,其实origin是个语法糖。
这样的话,我们就不需要两个元素了:
<div class="path onlyEle"> <img src="img/marker_red.png" class="avatar"/> </div>
@keyframes spin1 { from { transform: translate(50%, 150px) rotate(0turn) translate(-50%, -150px) translate(50%,50%) rotate(1turn) translate(-50%,-50%) } to { transform: translate(50%, 150px) rotate(1turn) translate(-50%, -150px) translate(50%,50%) rotate(0turn) translate(-50%, -50%); } } .onlyEle .avatar { animation: spin1 3s infinite linear; }
但是这里使用时有可能会有一点卡。
相关文章推荐
- Web布局连载——两栏固定布局(五)
- [div+css]晒晒最新制作专题推广页模板
- 盒子模型
- CSS选择器
- CSS样式优先权
- [css] line-height 百分比单位和数值单位的区别
- Apple官网研究之使用Justify布局导航
- 关于前端的思考与感悟
- rem : web app适配的秘密武器
- jquery高级应用之Deferred对象
- 移动端点击事件全攻略,这里的坑你知多少?
- $q 实例分析 Angular 中的 Promise
- 浏览器中唤起native app || 跳转到应用商城下载
- Angular directive 实例详解
- 关于浮动与清除浮动,你应该知道的
- 设计更快的网页(三):字体和 CSS 调整
- Gifski:一个跨平台的高质量 GIF 编码器
- 纯CSS制作的新闻网站中的文章列表