【问题标题】:programmatically changing webkit-transformation values in animation rules以编程方式更改动画规则中的 webkit-transformation 值
【发布时间】:2011-07-03 14:16:51
【问题描述】:

我有这个样式表:

        @-webkit-keyframes run {
            0% {
                -webkit-transform: translate3d(0px, 0px, 0px);
            }            
            100% {
                -webkit-transform: translate3d(0px, 1620px, 0px);
            }
        }

现在,我想根据一些参数修改 1620px 的值。像这样:

        @-webkit-keyframes run {
            0% {
                -webkit-transform: translate3d(0px, 0px, 0px);
            }            
            100% {
                -webkit-transform: translate3d(0px, height*i, 0px);
            }
        }

我希望能够使用 JavaScript 和 jQuery,尽管纯 CSS 解决方案也可以。

这适用于在其移动 Apple Safari 浏览器中运行的 iPhone 游戏。

【问题讨论】:

  • 最好的方法是通过 javascript 生成 css 规则 - WWDC 2010 CSS3 Animation session 有一个示例代码,请查看。

标签: javascript css safari webkit mobile-safari


【解决方案1】:

使用 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);
}

如果要修改已包含的样式表中的关键帧规则,请执行以下操作:

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

如果您不知道顺序但知道 CSS 文件的 URL,请将 document.styleSheets[0] 替换为 document.querySelector("link[href='your-css-url.css']").sheet

【讨论】:

  • 太棒了!很好的答案!这对我帮助很大!
  • 也许我说得太早了。我不断收到此错误:未捕获错误:SYNTAX_ERR:DOM 异常 12,我也收到未捕获错误:SYNTAX_ERR:DOM 异常 1
  • 最后一个 insertRule 行应该将它添加到索引 0 而不是 1,这就是 DOM Exception 1 的原因
  • If 的第一部分可能应该重新排序。见stackoverflow.com/questions/20007992/…
【解决方案2】:

您是否尝试在 html 文档头部的 <style> 元素中声明 css 的关键帧部分。然后,您可以给这个元素一个 id 或其他任何东西,并随时使用 javaScript 更改它的内容。像这样的:

<style id="keyframes">
        @-webkit-keyframes run {
            0%    { -webkit-transform: translate3d(0px,0px,0px); }            
            100%  { -webkit-transform: translate3d(0px, 1620px, 0px); }
        }
</style>

然后你的 jquery 可以正常改变这个:

$('#keyframes').text('whatever new values you want in here');

【讨论】:

  • Javascript 等价于这个伟大的解决方案:document.getElementById('keyframes').innerHTML = "new css animation values" ;
【解决方案3】:

从你的例子看来,在我看来 CSS 动画可能有点矫枉过正。改用过渡:

-webkit-transition: -webkit-transform .4s linear; /* you could also use 'all' instead of '-webkit-transform' */

然后通过js对元素应用新的变换:

$("<yournode>")[0].style.webkitTransform = "translate3d(0px,"+ (height*i) +"px,0px)";

它应该是动画。

【讨论】:

  • 应该是$("&lt;yournode&gt;")[0] .style. webkitTransform
  • @Tokimon 我为你解决了这个问题。谢谢你的回答,对我很有帮助。
【解决方案4】:

当您想要修改这些值(即使用变量)时我没有得到,但这里有 3 到 4 个解决方案和 1 个不可能的解决方案(目前)。

  • 服务器端计算:为了不时提供不同的 CSS,您可以告诉 PHP 或任何服务器端语言解析 .css 文件以及 @ 987654330@ 或 .html 然后在 PHP 标记之间使用 PHP 变量。注意文件缓存:为避免这种情况,您可以加载样式表,如 style.css?1234567890random-or-time 它会生成明显不同的文件,因此不会被缓存

  • SASS 也是一个需要 Ruby 的服务器端解决方案,它会为您提供现有的语法,可能比其他人已经提出的问题和解决方案的手工解决方案更简洁

  • LESS 是一个客户端解决方案,它将加载您的 .less 文件和一个 less.js 文件,该文件将解析前者并在 CSS 中为您提供变量,无论您的服务器是什么.它还可以与 node.js 一起在服务器端工作

  • CSS 在显示页面时被动态修改
    对于 2D,有来自 Ben Barnett 的 jquery-animate-enhanced2d-transformCSS3 rotate 则相反(它们在可能的情况下使用 CSS3 并且在没有此类功能的情况下,它们回退到现有的 jQuery .animate() 和 IE 矩阵过滤器),仅此而已。
    您可以 create a plugin for jQuery 使用一些参数来管理您希望通过 3D 转换实现的目标,并避免在 DOM 中修改冗长而复杂的 CSS 规则的麻烦

  • 仅限 CSS:您可以使用仅适用于 Firefox 4.0 的 -moz-calc [1][2] 和仅适用于 .. . 好吧没关系:-)

【讨论】:

  • calc() 也适用于 IE9。此外,转换适用于每个现代浏览器,而不仅仅是 Webkit(当然要使用适当的前缀)。
  • 感谢您的详细解答!我想在页面加载后随时修改这些值,所以不幸的是服务器端解决方案不是一个选项。我会看看你提到的其他解决方案。
  • “你可以为 jQuery 创建一个使用几个参数来管理的插件”是极端的矫枉过正。对于这个用例,CSSOM 实际上非常简单。他只是将insertRule 单个CSSStyleRule 转换为CSSStyleSheet。这是一个函数调用。
【解决方案5】:

试试这样的:

var height = {您要检测的任何高度设置}; element.style.webkitTransform = "translate3d(0px," + height*i + ",0px)";

【讨论】:

  • 谢谢,但这实际上并不是我想要的。我想更改现有动画规则中的值
【解决方案6】:

“矮胖”的解决方案?

在您选择的粒度范围内为高度创建变换,例如 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); }
}

然后创建匹配的 css 类:

.height-100 div { 
    -webkit-animation-name: run100;  
}

.height-200 div { 
    -webkit-animation-name: run200;  
}

然后使用 javascript 确定您所在的块并将适当的类分配给周围的元素。

$('#frame').attr('class', '').addClass('height-100');

如果粒度不太细可能还好!

【讨论】:

    【解决方案7】:

    我使用了 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;} }"
    );
    

    为了更新 CSS 过渡,我不得不让动画停止,然后重新启动,而不是使用之前定义的值。为此,我在元素上放置了一个“活动”类,并使 CSS 仅将过渡应用于具有该类的元素

    #marquee1.active {-webkit-animation-name: marqueeL;}
    #marquee2.active {-webkit-animation-name: marqueeR;}
    

    然后我只需要关闭“活动”类,等待它在 DOM 中应用(因此是 setTimeout),然后重新应用它。

    $('.ticket-marquee').removeClass('active');
    setTimeout(function() { $('.ticket-marquee').addClass('active'); },1);
    

    效果很好!现在我可以动态改变文本移动的距离!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-09
      • 1970-01-01
      • 2016-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-01
      相关资源
      最近更新 更多