js动态设置关键侦@keyframes的方法技巧
作者:Champion.XL
1.前置知识
关键侦@keyframes规则通过在动画序列中定义关键侦的样式来控制CSS动画序列的中间步骤
@keyframes slidein {
from {
transform: translateX(0%);
}
to {
transform: translateX(100%);
}
}
// from 等价于 0%;to 等价与 100%
// 或者
@keyframes slidein {
0% {
top: 0;
left: 0;
}
30% {
top: 50px;
}
68%,
72% {
left: 50px;
}
100% {
top: 100px;
left: 100%;
}
}
注意,如果在CSS中定义了两个相同名字的keyframes,后这会覆盖前者


如上图所示,定义了两个相同的动画侦之后,最终在浏览器中应用的是后者
2.js动态控制keyframes
背景
在 Vue 项目中由于 css 样式是直接写在 style 标签中的,那些值都是事先写死的,比如说上面的 translateX(disX),disX 是通过 js 动态计算出来的。如果要实现动画的效果是通过js动态计算出来的,会比较困难。所以可以通过 js 去设置 styleSheet 里面的样式规则,从而能够动态的控制 keyframes
StyleSheet是javaScript中表示样式表的接口,而styleSheet是一个DOM元素的对应属性,用于获取该元素所关联的样式表
- 获取样式表:通过
styleSheet属性可以获取元素关联的样式表
// 获取第一个样式表 const firstStyleSheet = document.styleSheet[0] // document.styleSheet 可以理解为一个二维数组(但是不是数组) // 有多个样式表,每个样式表中都有多条规则
- 插入样式列表:通过样式列表的
insertRules方法可以在样式列表中插入新的规则
const styleSheet = document.styleSheet[0]
styleSheet.insertRule(`.styleSheetCls { width: 200px; height: 200px}`,0)
// insertRule 方法中的第二个参数表示将样式插入样式表的哪里
// 这个规则会出现在第一个样式表的第一条
- 删除样式规则:使用样式表的
deleteRule方法可以删除指定位置的规则
const styleSheet = document.styleSheet[0] styleSheet.deleteRule(0) // 删除第一个样式表的第一条
我们可以通过styleSheet的insertRule方法动态的添加关键侦样式
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态添加 Keyframes</title>
<style id="dynamic-styles"></style>
</head>
<body>
<div id="myDiv"></div>
<script>
// 获取样式表
// 这里始终将新的 keyframes 规则添加在第一个样式表的第一条
const styleSheet = document.styleSheet[0];
let dis = 0
//... 动态计算 dis 的值
// 动态创建 @keyframes
const keyframesName = 'dynamicAnimation';
const keyframesRule = `@keyframes ${keyframesName} {
0% { transform: translateX(${dis}px); }
25% { transform: translateX(-${dis}px) rotate(0.5deg); }
50% { transform: translateX(${dis}px) rotate(-0.5deg); }
75% { transform: translateX(-${dis}px) rotate(0.5deg); }
100% { transform: translateX(0); }
}`
`@keyframes dynamicAnimation{
0% { transform: translateX(5px); }
100% { transform: translateX(0); }
}`
// 每次添加新的规则之前,可以将之前的规则给删除掉,这样就可以避免第一个样式表的规则里面有多条重复名称的 keyframes,避免相同名字的 keyframes 前者被后者覆盖
// 获取第一个样式表的第一条规则的名称
const firstRules = styleSheet.rules || styleSheet.cssRules
// 这里是以防第一条规则不是 keyframes 规则,从而导致获取 name 失败
const ruleName = firstRules[0].name ? firstRules[0].name : ''
if(ruleName === keyframesName) {
/**
* 这里能够直接删除,是因为我始终将 keyframes 添加在第一个样式表的第一条规则中
* 如果不能确定样式位置,那么就需要遍历整个样式表,找到目标样式表的位置
* document.styleSheet 可以理解为一个二维数组(但是不是数组,不适合使用数组的遍历方式进行遍历)
* 有多个样式表,每个表中都有多条规则
**/
styleSheet.deleteRule(0)
}
// 这里始终将新的 keyframes 规则添加在第一个样式表的第一条
styleSheet.insertRule(keyframesRule, 0);
// 动态应用 @keyframes
const myDiv = document.getElementById('myDiv');
myDiv.style.animation = `${keyframesName} 2s ease-in-out`;
</script>
</body>
</html>
3. 编写技巧
- 在编写
keyframes规则时,我比较推荐在在style标签中将动画规则写好了在复制到JavaScript逻辑代码中,因为如果动画规则编写有问题,那么在insertRule插入样式的时候,可能会导致样式表识别不了 - 查看是否添加成功,可以在控制台打印出来样式表,寻找我们添加的规则,如下图
可以看到第一个样式表中的第一个样式是我们添加的
keyframes样式,并且识别成功了会有CSSKeyframesRule的属性,里面就是我们定义的每一帧的动画样式
补充知识:js动态修改@keyframes属性值
CSS3中增加了@keyframes规则用于创建动画,创建动画的原理是,将一套 CSS 样式逐渐变化为另一套样式。也就是说通过改变CSS样式而达到动画的效果,所以,要动态去改变动画,只有修改样式。
document.styleSheets这个接口可以获取网页上引入的link样式表和style样式表。如下:

拿到样式表后就可以操作样式啦~
insertRule方法用来给当前样式表插入新的样式规则。举个栗子:

insertRule(rule,index)
rule:要添加到样式表的规则。index:要把规则插入或附加到 cssRules 数组中的位置。
js既然可以改变样式了,那传值就方便啦!
var param = 20;
var style = document.styleSheets[0];
style.insertRule("@keyframes rotate_before{from{ transform: translate(0%,0%); }to{ transform: translate(0%,-"+param +"%);}}",9);//写入样式
根据具体需求传值并修改样式就酱。
总结
到此这篇关于js动态设置关键侦@keyframes的文章就介绍到这了,更多相关js动态设置关键侦@keyframes内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

