使用Sass来定义Keyframes
CSS的Animation成为Web Animation中主要实现方式之一。使用CSS 的animation
可以在Web中实现一些动画效果。而其中最为关键的还是依赖于@keyframes
,让动画可以根据帧定制不同的动画效果。
其实这篇文章的主要目的不是要给大空介绍@keyframes
的语法和使用方法。因为,大家对它并不会陌生,而且也知道怎么使用?那么大家在使用keyframes
的时候是不是碰到一些烦恼,对于不同的动画效果,都需要去创建一个keyframes
,而且对于一个复杂的动画,一个动画中用到多个元素元素时,是不是感觉到管理和维护keyframes
比较痛苦,易出错。
如果你有上述这样的烦恼,那么下面的内容值得你花点时间继续往下阅读。
CSS中的keyframes
简单的回忆一下,如果要使用animation
创建一个动效,就必须先用keyframes
创建一个动效。
@keyframes animation-name {
...
}
由于各浏览器厂商对animation
支持程度不一样,早期为了兼容各浏览器,需要添加各种前缀:
@-webkit-keyframes animation-name {...}
@-moz-keyframes animation-name {...}
@-o-keyframes animation-name {...}
@keyframes animation-name {...}
虽然后面有了Autoprefixer的出现,让我们变得轻松了些。可以根据不同的配置,在编译代码的时候就会自动根据配置添加需要的前缀。在Autoprefixer的帮助之下,我们可以在代码中直接写:
@keyframes animation-name {...}
但这仅仅是解决了浏览器厂商的前缀的维护问题,但对于整个代码维护并没有帮我们减轻。
SCSS中的keyframes
Autoprefixer还没有出现之前,SCSS其实帮助我们解决一些前缀的事项,言外之意,就是给keyframes
定义一个混合宏(mixins):
@mixin keyframes($animationName) {
@-webkit-keyframes #{$animationName} {
@content;
}
@-moz-keyframes #{$animationName} {
@content;
}
@-o-keyframes #{$animationName} {
@content;
}
@keyframes #{$animationName} {
@content;
}
}
在调用的时候,可以直接这样使用
@include keyframes(move-the-object) {
0% {
transform: translateX(0);
}
100% {
transform: translateX(200px);
}
}
当然,如果你的工作环境中已经配置了Autoprefixer的话,上面的混合宏可以直接写:
@mixin keyframes($animationName) {
@keyframes #{$animationName} {
@content;
}
}
回到keyframes
调用上面来,除了独立调用声明好的混合宏之外,还可以跟随元素一起调用:
.animation {
animation: move-the-object 2s ease both;
@include keyframes(move-the-object) {
0% {
transform: translateX(0);
}
100% {
transform: translateX(200px);
}
}
}
同样能编译出来:
除此之外,如果你想让你的animation-name
有一个随机名称,可以借助Sass中的unique-id()
函数功能。
@mixin animation-keyframes {
$animation-name: unique-id();
animation-name: $animation-name;
@keyframes #{$animation-name} {
@content;
}
}
像下面这样调用,就能随机产生一个keyframes
的名称:
.animation {
animation: 2s ease both;
@include animation-keyframes {
0% {
transform: translateX(0);
}
100% {
transform: translateX(200px);
}
}
}
编译出来的代码如下:
当然,上面的keyframes
混合宏是一种简单的声明方式,如果你想让它变得更强大也是可以的,比如:
@mixin animation($options: ()) {
$options: map-merge((
animationName: animation,
duration: 1,
waitTime: 0,
timingFunction: linear,
iterationCount: infinite
), $options);
$name: map-get($options, animationName);
$kf: map-get($options, keyframes);
$kfLength: length($kf);
$duration: map-get($options, duration);
$waitTime: map-get($options, waitTime);
$timingFunction: map-get($options, timingFunction);
$iterationCount: map-get($options, iterationCount);
$counter: 1; // index of 'each'
@keyframes #{$name} {
@each $frame, $prop in $kf {
#{$frame * $duration / ($duration + $waitTime)}% {
@each $k, $v in $prop {
#{$k}: #{$v}
}
}
// if last in loop and waitTime is not 0, add the last frame as 100% (this is what creates the pause)
@if $counter == $kfLength and $waitTime > 0 {
100% {
@each $k, $v in $prop {
#{$k}: #{$v}
}
}
}
$counter: $counter+1;
}
}
animation: #{$name} #{$duration}s #{$timingFunction} #{$iterationCount};
}
上面一堆的代码,其实并不复杂,稍微了解Sass基础的都读得懂上面的代码,这里就不做过多的阐述。那么调用的时候,只需要这样:
.anime {
@include animation(
(
animationName: zoom,
keyframes: (
0: (
transform: scale(1),
background-color: blue
),
50: (
transform: scale(2),
background-color: green
),
100: (
transform: scale(3),
background-color: red
)
),
duration: 2,
waitTime: 1,
timingFunction: ease,
iterationCount: infinite
)
);
}
编译出来的代码如下:
混合宏@include waitAnimate((options));
包括以下一些参数:
选项 | 描述 | 类型 | 是否必须 | 默认值 |
---|---|---|---|---|
animationName |
animation-name 的值,也就是动画名称 |
string | NO | animation |
keyframes |
0% 至100% 的动画规则,也就是@keyframes 的帧运动 |
Sass map Object | YES | 无 |
duration |
animation-druration 的值,动画播放持续时间 |
Number | NO | 1s |
waitTimg |
animation-delay 的值,动画延迟播放时间 |
Number | NO | 0 |
timingFunction |
animation-timing-function 的值,动画播放函数 |
String | NO | linear |
iterationCount |
animation-iteration-count 的值,动画播放次数 |
String | NO | infinite |
把上面的混合宏中的animationName
的值换成unique-id()
函数,就可以获取随机的animation-name
值,而且在调用混合宏@nimation
可以不给animationName
设置值:
不过这种方式略有一个缺陷,就是不能一直同时声明多个animation-name
。如果希望同时声明多个,需要在上面的基础上进行修改或者扩展。感兴趣的同学可以尝试一下。
其实上述的方法只是Sass实现keyframes
的几种而以,在网络上这样的混合宏方法有很多种。大家也可以根据自己平时常使用的方式,可以定制适合自己的keyframes
混合宏。最后给大家推荐一个ZURB团队做的MOTION UI,这里面声明keyframes
也非常有特色,感兴趣的同学可以去查看源码。
总结
文章主要介绍了如何使用Sass的方式给@kefyframes
声明一个混合宏,并且通过@include
来调用声明好的混合宏。并且简单的介绍了如何通过声明的keyframes
来更好的维护我们的代码。最后希望这篇文章对于你平时写代码有所帮助,如果您有更好的方案或者思路,欢迎在下面的评论中与我们一起分享。