Javascript 以编程方式更改动画规则中的 webkit 转换值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5105530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
programmatically changing webkit-transformation values in animation rules
提问by clamp
I have this stylesheet:
我有这个样式表:
@-webkit-keyframes run {
0% {
-webkit-transform: translate3d(0px, 0px, 0px);
}
100% {
-webkit-transform: translate3d(0px, 1620px, 0px);
}
}
Now, I would like to modify the value of 1620px depending on some parameters. Like this:
现在,我想根据一些参数修改 1620px 的值。像这样:
@-webkit-keyframes run {
0% {
-webkit-transform: translate3d(0px, 0px, 0px);
}
100% {
-webkit-transform: translate3d(0px, height*i, 0px);
}
}
I would prefer to be able to use JavaScript and jQuery, though a pure CSS solution would be ok.
我更希望能够使用 JavaScript 和 jQuery,尽管纯 CSS 解决方案也可以。
This is for an iPhone game that runs in it's mobile Apple Safari browser.
这是针对在其移动 Apple Safari 浏览器中运行的 iPhone 游戏。
回答by Eli Grey
Use the CSSOM
使用 CSSOM
var style = document.documentElement.appendChild(document.createElement("style")),
rule = " run {\
0% {\
-webkit-transform: translate3d(0, 0, 0); }\
transform: translate3d(0, 0, 0); }\
}\
100% {\
-webkit-transform: translate3d(0, " + your_value_here + "px, 0);\
transform: translate3d(0, " + your_value_here + "px, 0);\
}\
}";
if (CSSRule.KEYFRAMES_RULE) { // W3C
style.sheet.insertRule("@keyframes" + rule, 0);
} else if (CSSRule.WEBKIT_KEYFRAMES_RULE) { // WebKit
style.sheet.insertRule("@-webkit-keyframes" + rule, 0);
}
If you want to modify a keyframe rule in a stylesheet that's already included, do the following:
如果要修改已包含的样式表中的关键帧规则,请执行以下操作:
var
stylesheet = document.styleSheets[0] // replace 0 with the number of the stylesheet that you want to modify
, rules = stylesheet.rules
, i = rules.length
, keyframes
, keyframe
;
while (i--) {
keyframes = rules.item(i);
if (
(
keyframes.type === keyframes.KEYFRAMES_RULE
|| keyframes.type === keyframes.WEBKIT_KEYFRAMES_RULE
)
&& keyframes.name === "run"
) {
rules = keyframes.cssRules;
i = rules.length;
while (i--) {
keyframe = rules.item(i);
if (
(
keyframe.type === keyframe.KEYFRAME_RULE
|| keyframe.type === keyframe.WEBKIT_KEYFRAME_RULE
)
&& keyframe.keyText === "100%"
) {
keyframe.style.webkitTransform =
keyframe.style.transform =
"translate3d(0, " + your_value_here + "px, 0)";
break;
}
}
break;
}
}
If you don't know the order but do know the URL of the CSS file, replace document.styleSheets[0]
with document.querySelector("link[href='
your-css-url.css
']").sheet
.
如果您不知道顺序但知道 CSS 文件的 URL,请替换document.styleSheets[0]
为.document.querySelector("link[href='
your-css-url.css
']").sheet
回答by warmanp
Have you tried declaring the keyframe portion of your css in a <style>
element in the head of your html document. You can then give this element an id or whatever and change it's content whenever you like with javaScript. Something like this:
您是否尝试过<style>
在 html 文档头部的元素中声明 css 的关键帧部分。然后你可以给这个元素一个 id 或其他任何东西,并在你喜欢的时候用 javaScript 改变它的内容。像这样的东西:
<style id="keyframes">
@-webkit-keyframes run {
0% { -webkit-transform: translate3d(0px,0px,0px); }
100% { -webkit-transform: translate3d(0px, 1620px, 0px); }
}
</style>
Then your jquery can change this as normal:
然后你的 jquery 可以像往常一样改变它:
$('#keyframes').text('whatever new values you want in here');
回答by Tokimon
Well from your example it seems to me that CSS animations may be overkill. Use transitions instead:
好吧,从你的例子来看,在我看来 CSS 动画可能有点矫枉过正。改用过渡:
-webkit-transition: -webkit-transform .4s linear; /* you could also use 'all' instead of '-webkit-transform' */
and then apply a new transform to the element via js:
然后通过 js 对元素应用新的转换:
$("<yournode>")[0].style.webkitTransform = "translate3d(0px,"+ (height*i) +"px,0px)";
It should animate that.
它应该动画。
回答by FelipeAls
I didn't get when you wanted to modify these values (i.e. use variables) but nevertheless here are 3 to 4 solutions and 1 impossible solution (for now).
我不知道您何时想要修改这些值(即使用变量),但是这里有 3 到 4 个解决方案和 1 个不可能的解决方案(目前)。
server-side calculation: in order to serve a different CSS from time to time, you can tell PHP or any server-side language to parse
.css
files as well as.php
or.html
and then use PHP variables in-between PHP tags. Beware of file caching: to avoid it, you can load a stylesheet like style.css?1234567890random-or-time it will produce an apparent different file and thus won't be cachedSASSis also a server-side solution that needs Ruby and will provide you an existing syntax, probably cleaner than a hand-made solution as others have already about problems and solutions
LESSis a client-side solution that will load your .less file and a less.js file that will parse the former and provide you variables in CSS whatever your server is. It can also work server-side with node.js
CSS being dynamically modifiedwhile your page is displayed?
For 2D there are jquery-animate-enhancedfrom Ben Barnett, 2d-transformor CSS3 rotateare pitched the other way around (they use CSS3 where possible and where there are no such functions, they fallback to existing jQuery .animate() and IE matrix filter) but that's it.
You could create a plugin for jQuerythat would manage with a few parameters what you want to achieve with 3D Transformation and avoid the hassle of modifying long and complex CSS rules in the DOMCSS only: you could use -moz-calc [1][2] that works only in Firefox 4.0 with -webkit-transform that works only in ... OK nevermind :-)
服务器端计算:为了不时提供不同的 CSS,您可以告诉 PHP 或任何服务器端语言解析
.css
文件以及.php
or.html
然后在 PHP 标记之间使用 PHP 变量。当心文件缓存:为了避免它,你可以加载一个样式表,比如 style.css?1234567890random-or-time 它会产生一个明显不同的文件,因此不会被缓存SASS也是一个需要 Ruby 的服务器端解决方案,它将为您提供现有的语法,可能比其他人已经关于问题和解决方案的手工解决方案更简洁
LESS是一个客户端解决方案,它将加载您的 .less 文件和一个 less.js 文件,该文件将解析前者并为您提供 CSS 中的变量,无论您的服务器是什么。它也可以与 node.js 一起在服务器端工作
显示页面时动态修改CSS ?
对于 2D,有来自 Ben Barnett 的jquery-animate-enhanced,2d-transform或CSS3 旋转是相反的(他们在可能的情况下使用 CSS3,并且在没有此类功能的情况下,他们回退到现有的 jQuery .animate() 和 IE矩阵过滤器)但就是这样。
您可以为 jQuery 创建一个插件,该插件将使用一些参数来管理您想要通过 3D 转换实现的目标,并避免在 DOM 中修改长而复杂的 CSS 规则的麻烦仅 CSS:您可以使用仅适用于 Firefox 4.0 的-moz-calc [ 1][ 2] 和仅适用于...的-webkit-transform ......好吧没关系:-)
回答by Al.
A 'Chunky' solution?
一个“矮胖”的解决方案?
Create transforms for heights within your chosen granularity, say 0-99, 100-199, 200-299, etc. Each with a unique animation name identifier like:
在您选择的粒度范围内为高度创建变换,例如 0-99、100-199、200-299 等。每个变换都有一个唯一的动画名称标识符,例如:
@-webkit-keyframes run100 {
0% { -webkit-transform: translate3d(0px,0px,0px); }
100% { -webkit-transform: translate3d(0px,100px,0px); }
}
@-webkit-keyframes run200 {
0% { -webkit-transform: translate3d(0px,0px,0px); }
100% { -webkit-transform: translate3d(0px,200px,0px); }
}
then create matching css classes:
然后创建匹配的 css 类:
.height-100 div {
-webkit-animation-name: run100;
}
.height-200 div {
-webkit-animation-name: run200;
}
then with javascript decide which chunk you're in and assign the appropriate class to the surrounding element.
然后用 javascript 决定你在哪个块中,并将适当的类分配给周围的元素。
$('#frame').attr('class', '').addClass('height-100');
Might be ok if the granularity doesn't get too fine!
如果粒度不太细可能没问题!
回答by probbins222
Try something like this:
尝试这样的事情:
var height = {whatever height setting you want to detect}; element.style.webkitTransform = "translate3d(0px," + height*i + ",0px)";
回答by Ben Jaffe
I used warmanp's solution and it worked, but with a bit of very important tweaking.
我使用了 warmanp 的解决方案并且它有效,但有一些非常重要的调整。
$('#ticket-marquee-css').text(
"@-webkit-keyframes marqueeR{ 0%{text-indent: -" + distanceToMove + "px;} 100%{text-indent: 0;} }" +
"@-webkit-keyframes marqueeL{ 0%{text-indent: 0;} 100%{text-indent: -" + distanceToMove + "px;} }"
);
In order to get the CSS transition to update, instead of using the previously-defined values, I had to make the animation stop, then restart. To do this, I placed a class of "active" on the elements, and made the CSS only apply the transition to the elements that had that class
为了让 CSS 过渡更新,而不是使用先前定义的值,我不得不停止动画,然后重新启动。为此,我在元素上放置了一个“active”类,并使 CSS 仅将过渡应用于具有该类的元素
#marquee1.active {-webkit-animation-name: marqueeL;}
#marquee2.active {-webkit-animation-name: marqueeR;}
Then I just had to toggle the "active" class off, wait for it to apply in the DOM (hence the setTimeout), then reapply it.
然后我只需要关闭“活动”类,等待它在 DOM 中应用(因此是 setTimeout),然后重新应用它。
$('.ticket-marquee').removeClass('active');
setTimeout(function() { $('.ticket-marquee').addClass('active'); },1);
And that works great! Now I can dynamically change the distance the text moves!
这很好用!现在我可以动态改变文本移动的距离了!