如何动态创建“@-Keyframe”CSS 动画?

IT技术 javascript jquery html css
2021-02-01 23:29:04

我需要旋转 div 并停在特定位置(将从服务器接收该值)。

我尝试使用原生 JS 进行旋转和停止,但它占用了我大量的 CPU。

我可以使用 CSS 动画进行旋转,但我需要创建一个类来动态描述停止动画的位置。就像是

@-webkit-keyframes spinIt {
    100% {
        -webkit-transform: rotate(A_DYNAMIC_VALUE);
    }
}
@-moz-keyframes spinIt {
    100% {
        -webkit-transform: rotate(A_DYNAMIC_VALUE);
    }
}

这是一个参考

http://jsfiddle.net/bVkwH/8/

提前致谢

6个回答

您可以动态插入样式表规则以覆盖头部以前的样式。这有助于避免为单个任务添加另一个库。

var style = document.createElement('style');
style.type = 'text/css';
var keyFrames = '\
@-webkit-keyframes spinIt {\
    100% {\
        -webkit-transform: rotate(A_DYNAMIC_VALUE);\
    }\
}\
@-moz-keyframes spinIt {\
    100% {\
        -webkit-transform: rotate(A_DYNAMIC_VALUE);\
    }\
}';
style.innerHTML = keyFrames.replace(/A_DYNAMIC_VALUE/g, "180deg");
document.getElementsByTagName('head')[0].appendChild(style);
这真的有效吗?我试图在头部和身体中插入一个元素,希望这能起作用(在 之后发现),但这不会触发任何关键帧。这真的经过测试了吗?我在铬。
2021-03-17 23:29:04
在 CSS3 DOM 中我们也可以使用 document.head.appendChild(style)
2021-04-06 23:29:04
是的,它已经过测试。
2021-04-10 23:29:04
创造性的答案......但在 ReactJS 中有点反模式
2021-04-12 23:29:04
这需要一个 Content-Security-Policy style-src 'unsafe-inline'
2021-04-12 23:29:04

好吧,我认为创建动态并不容易,@keyframes它们不灵活,因为它们必须是硬编码的。

过渡更容易使用,因为它们可以优雅地响应 JavaScript 执行的任何 CSS 更改。

然而,CSS 过渡可以给你带来的复杂性是非常有限的——一个多步骤的动画很难实现。

这是 CSS @keyframe 动画旨在解决的问题,但它们不提供过渡所做的动态响应级别。

但这些链接可能对你有帮助

Link1 :一个工具,可以生成带有许多小步骤的 @-webkit-keyframe 动画。这打开了无限选择缓动公式的大门。

Link2将它作为基础对您有很大帮助,因为它提供了一个 UI 来创建动画并将其导出到 CSS 代码。

我想 这个 解决方案肯定对你有用。它用于动态关键帧

过渡成功了!!谢谢老兄..我动态设置了过渡和宾果游戏!
2021-03-28 23:29:04
链接 2 被链接腐烂消耗
2021-04-06 23:29:04

让我分享一个更新的(2019 年)答案。

是的,没有 Javascript 可以使用CSS 变量(所有现代浏览器都支持)。

--lightScaleStart: 0.8;

.light {
    animation: grow 2s alternate infinite ease-in-out;
}

.light.yellow {
    --lightScaleEnd: 1.1;
}

.light.red {
    --lightScaleEnd: 1.2;
}

@keyframes grow {
  from {
    transform: scale(var(--lightScaleStart));
  }
  to {
    transform: scale(var(--lightScaleEnd));
  }
}

请参阅有关带有 CSS 变量的Codepen动态 CSS 动画的演示

编辑:这是一篇关于它CSS Tricks 文章

似乎您不能使用 CSS 变量来设置animation-timing-function关键帧内部。即,@keyframes foo { 0% { animation-timing-function: var(--some-var); …不会工作。在 Chrome 79 中测试。
2021-03-20 23:29:04
当您需要为每个元素使用不同数量的关键帧(假设为 20、30 和 40 帧)时,这没有帮助。此示例仅适用于存在少量固定关键帧的简单情况。
2021-04-12 23:29:04

亚历克斯格兰德的回答对几个关键帧非常有效。但是,假设您想一遍又一遍地动态添加关键帧,那么您的网页会很快变得非常滞后。要解决这个问题,只需停止创建新的 DOM 元素。相反,创建 1 个新的 DOM 样式表,然后将其与insertRule. 如果你想要更多的关键帧(比如你在每个动画帧中生成一个新的关键帧),那么你需要设置一个系统,在它们不再使用后删除旧的关键帧。这是如何实现这样的事情的良好开端。

var myReuseableStylesheet = document.createElement('style'),
    addKeyFrames = null;
document.head.appendChild( myReuseableStylesheet );
if (CSS && CSS.supports && CSS.supports('animation: name')){
    // we can safely assume that the browser supports unprefixed version.
    addKeyFrames = function(name, frames){
        var pos = myReuseableStylesheet.length;
        myReuseableStylesheet.insertRule(
            "@keyframes " + name + "{" + frames + "}", pos);
    }
} else {
    addKeyFrames = function(name, frames){
        // Ugly and terrible, but users with this terrible of a browser
        // *cough* IE *cough* don't deserve a fast site
        var str = name + "{" + frames + "}",
            pos = myReuseableStylesheet.length;
        myReuseableStylesheet.insertRule("@-webkit-keyframes " + str, pos);
        myReuseableStylesheet.insertRule("@keyframes " + str, pos+1);
    }
}

用法示例:

addKeyFrames(
    'fadeAnimation',
    '0%{opacity:0}' + 
    '100%{opacity:1}'
);

此外,亚历克斯大,我敢肯定,document.getElementsByTagName('head')[0]并且type = 'text/css'还没有被IE8需要,并且@keyframes不支持,直到IE10。就是说...

我喜欢插入规则!- 亚历克斯格兰德外出
2021-03-15 23:29:04

您可以更改 CSSKeyframeRule 中的样式,这对我来说在 Chrome 中很好用,就像下面的代码一样。希望这会有所帮助:)

<html>

<head>
	<style>
		#text {
			display: inline-block;
		}
	</style>
</head>

<body>
	<div id="text">TEXT</div>
	<script>
	
		// Dynamically create a keyframe animation
		document.styleSheets[0].insertRule('\
			@keyframes anim {\
				from { transform: rotateZ(0deg);   }\
				to   { transform: rotateZ(360deg); }\
			}'
		);
		var div = document.getElementById('text');
		div.style.animation = 'anim 1s linear forwards';
		
		// This function will change the anim
		function stopAtSomeDeg(d) {
			var ss = document.styleSheets[0];
			var anim;
			for (var i in ss.cssRules) {
				// Find your animation by name
				if (ss.cssRules[i].name === 'anim') {
					anim = ss.cssRules[i];
					break;
				}
			}
			var stopFrame = anim.cssRules[1]; // This indicates the second line of "anim" above.
			
			// Change any attributes
			stopFrame.style.transform = 'rotateZ(' + d + 'deg)';
		}
		
		stopAtSomeDeg(180);
	</script>
</body>
</html>