CSS CSS使用技巧

CSS使用技巧-过渡与动画

Posted on 2018-04-18,8 min read

前言

CSS过渡动画是CSS3的一大新亮点,这种本该由CSS实现的效果过去一直是使用脚本来实现,多多少少会影响性能,现在我们拥有了强大的CSS过渡动画功能后,将会有一个崭新的世界。

前置知识

CSS动画
CSS过渡
CSS转换

1.缓动效果

现在我们实现一个自由落体的运动效果,我们的CSS样式可能这样写,核心代码:

@keyframes bounce {
    60%, 80%, to {
        transform: translateY(350px);
        animation-timing-function: ease-in;
    }
    70% {
        transform: translateY(250px)
    }
    90% {
        transform: translateY(300px)
    }
}
.ball{
    animation: bounce 3s ease-out;
}


这里传递了transition-timing-function的值,他有6个值,前五个值分别对应以下:

最后一个值是一个cubic-bezier(x1,y1,x2,y2)函数,可以定义自己想要的值,(x1,y1)表示第一个控制点的坐标,即上图中左下角的那个坐标,(x2,y2)表示第二个控制点的坐标,即上图中右上角的那个坐标,cubic-bezier函数简单来说就是控制在一段时间内动画执行的进度函数,类似于下面这个二位坐标系:

x轴坐标代表时间,取值范围是[0,1],因为我们不可能超越时间,y轴坐标表示执行进度,我们可以通过编辑这个曲线,从而创造出符合我们预期的效果,这里有个在线的工具可以生成这个函数图像,链接如下:
cubic-bezier

现在我们想要实现这种效果,请问改如何实现:

css核心代码:

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;
}

这里关键的是cubic-bezier函数,它在执行的过程中会将目标对象放大到自身的1.1倍之后,再返回到原始大小,它的函数图大概这样:

在这里我们并没有运用动画,而只是利用过度加一点小技巧就实现了平滑的放大->原始大小->隐藏的过渡效果。

2.逐帧动画

假如我们想要实现加载的等待动画效果,不使用gif实现,那怎么实现:

在网上有一种解决方案,就是使用背景来解决,通过脚本控制背景显示位置,从而达到一帧一帧加载图片,但是这都需要脚本,我们能不能通过CSS来实现这种效果呢,尝试的代码如下:

背景放置了每个不同阶段的静态帧:

@keyframes loader {
    to { background-position: -800px 0; }
}

.loader {
    width: 100px; height: 100px;
    background: url(http://dabblet.com/img/loader.png) 0 0;
    animation: loader 1s infinite linear;
}


怎么在连续动,这什么鬼,原来是动画会有一个过度效果,所以会连续动,而我们的目的只是想逐帧的变换,那有没有什么办法,好在CSS中有一个steps属性,专门用来显示逐帧变换的,简单来说他会将一个动画分割成n个步骤,每隔一段时间执行下一个步骤,中间没有过度行为,这正好满足我们的要求,代码如下:

@keyframes loader {
    to { background-position: -800px 0; }
}

.loader {
    width: 100px; height: 100px;
    background: url(http://dabblet.com/img/loader.png) 0 0;
    animation: loader 1s infinite linear steps(8);
}
3.闪烁效果

有时候我们想要实现文字闪烁效果以提醒用户有新消息又或者提醒用户某些重要的东西,那我们怎么去实现,可能我们可以通过opacity属性实现透明闪烁效果,又或者通过文字颜色透明提醒,我们的代码可能是这样的:

@keyframes blink{ to { color: transparent } }
.blink{
    animation: 1s blink 3;
}


乍看感觉很突兀,显示的时候一下子就显示出来了,我们能不能让它有个平缓的过程,于是我们将循环过程的切换放在中间,也就是在50%的时候就让它切换回来,代码如下:

@keyframes blink{ 50% { color: transparent } }
.blink{
    animation: 1s blink 3;
}

我们知道这个动画一致都处于加速过程中,为了让它更加随机化,我们增加animation-direction属性,让其更加随机化一点:

@keyframes blink{ 50% { color: transparent } }
.blink{
    animation: 1s blink 3;
    animation-direction: alternate;
}
4.打字动画

加入我们要实现下面这种结果,这在web模拟终端经常会实现的效果之一:

首先我们想到当然是下面这行代码:

@keyframes typing {
    from {width: 0}
}
.typing{
    width: 14ch;
    animation: typing  8s steps(14),caret 1s steps(1) infinite;
    font-family: monospace;
}


一看结果,发现没有设置不换行样式以及溢出隐藏的样式,这里使用的是前面提到的步进函数,因为我们不需要过渡,这里还用到了一个ch单位,这个是css3中新单位,代表0字符的宽度,不常用,但在等宽字体中好使,我们还要加上右边框,所以最后修改代码之后:

@keyframes typing {
    from {width: 0}
}
@keyframes caret {
    50% {border-color:currentColor}
}
.dot{
    width: 14ch;
    animation: typing  8s steps(14),caret 1s steps(1) infinite;
    white-space: nowrap;
    overflow: hidden;
    font-family: monospace;
    border-right: .05em solid transparent;
}
5.状态平滑的动画

如果我们的动画一开始是默认执行的,而是用户有交互的时候采取执行,比如hover事件,但是当用户移除的时候,那么此时的动画将会如何运行呢,是继续执行一个周期,还是停留在原地呢,都不是而是迅速的返回到起始状态,给人的感觉就好像是出bug的感觉:

那有没有什么办法让其有一个过渡状态呢,好在css中有一个animation-play-state属性,它可以控制动画执行与暂停,于是我们有以下代码:

@keyframes panoramic {
    to { background-position: 100% 0; }
}

    .panoramic {
    width: 150px; height: 150px;
    background: url('1.jpg');
    background-size: auto 100%;
    animation: panoramic 10s linear infinite alternate;
    animation-play-state: paused;
}

.panoramic:hover, .panoramic:focus {
    animation-play-state: running;
}

在这段代码中我使用background-position水平方向的过渡从而实现图片缓慢从左到右运动,在默认情况下是暂停动画,当鼠标移上去的时候才开始执行动画,就解决了前面的问题。

6.沿环形运动的动画

如果我们想要使用CSS实现一个动画随着指定的环形路线而运动那该怎么样,可能代码如下:

<div class="path">
    <div class="av"><img src="http://lea.verou.me/book/adamcatlace.jpg" alt="" ></div>
</div>
.path{
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background: orange;
    margin: 0 auto;
    padding: 10px;
}
.path img{
    width: inherit;
}
.av{
    margin: 0 auto;
    width: 50px;
    height: 50px;
    border-radius: 50%;
    overflow: hidden;
}
@keyframes spin {
    to {transform: rotate(1turn)}
}
.av{
    animation: spin 3s infinite linear;
    transform-origin: center 150px;
}

但是这个头像在向下运动的时候却是头朝下的,我们能不能让其朝上显示呢,头像之所以会向下是因为自身在旋转,如果我们再次让其自身逆向旋转,那不就可以抵消掉旋转,就好像没有旋转一样,从而保持图片始终朝上,具体看代码:

...
@keyframes spin {
    to { transform: rotate(1turn); }
}

.avatar {
    animation: spin 3s infinite linear;
    transform-origin: 50% 150px;
}

.avatar > img {
    animation: inherit;
    animation-direction: reverse;
}

我们通过对图片应用动画,使其继承父级的旋转动画,通过animation-direction属性反转角度,从而达到我们想要的效果。

最后我们不借助父元素旋转,而使用自身旋转能否解决这个问题,关键就是transform-origin完全可以使用translate来模拟实现,前者不过是后者的语法糖而已,于是我们有以下代码:

@keyframes spin {
	from {
		transform: rotate(0turn)
		           translateY(-150px) translateY(50%)
		           rotate(1turn)
	}
	to {
		transform: rotate(1turn)
		           translateY(-150px) translateY(50%)
		           rotate(0turn);
	}
}


.av {
	animation: spin 3s infinite linear;
}
作者:落叶卢生
链接:https://luoyelusheng.com/post/CSS使用技巧-过渡与动画
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

下一篇: CSS使用技巧-结构与布局→