【问题标题】:CSS Transition Not FiringCSS 过渡未触发
【发布时间】:2011-10-27 12:06:00
【问题描述】:

我正在创建一个 DOM 元素(一个 div),将其添加到 DOM,然后在 javascript 中一键更改其宽度。这在理论上应该触发 CSS3 过渡,但结果是直接从 A 到 B,中间没有过渡。

如果我通过单独的测试点击事件改变宽度,一切都会按预期工作。

这是我的 JS 和 CSS:

JS(jQuery):

var div = $('<div />').addClass('trans').css('width', '20px');
$('#container').append(div);
div.css('width', '200px');

CSS(暂时只是 Mozilla):

.trans {
    -moz-transition-property: all;
    -moz-transition-duration: 5s;
    height: 20px;
    background-color: cyan;
}

我是在这里搞砸了,还是“一击即中”不是事情应该做的方式?

非常感谢所有帮助。

【问题讨论】:

  • 我很困惑 - 你想为高度或宽度设置动画吗?或两者?另外,使用 jquery 的 .animate() 方法是不可能的吗?因为如果不是,这就是我建议的方式。告诉我,我会写一个简单的方法来用 jQuery(或修复 CSS)。
  • @onetrickpony - 目前还不清楚您正在寻找此赏金的哪些额外信息。能否请您在评论中详细说明?
  • 我只是想知道是否有比使用超时让浏览器更新这些值更好的方法@Josh
  • @onetrickpony - 除了被接受的答案?因为这可能是最好的方法。我想我感到困惑的是您不知道转换了哪个属性的场景。
  • 当你在 CSS 文件中定义了过渡,并且不想告诉 js 时,应该只担心附加 html 和更改类

标签: jquery css transitions css-transitions


【解决方案1】:

这里有两种方法可以做到这一点。

1 - CSS 过渡

通过使用setTimeoutaddClass 方法将在后面运行而不是与前面的脚本一起运行,以便触发transition 事件

example jsfiddle

jQuery:

var div = $('<div class="trans" />');
$('#container').append(div);
// set the class change to run 1ms after adding the div
setTimeout(function() {div.addClass('wide')}, 1); 

CSS:

.trans {
    width: 20px;
    height: 20px;
    background-color: cyan;
    -webkit-transition: all 5s ease;
       -moz-transition: all 5s ease;
        -ie-transition: all 5s ease;
         -o-transition: all 5s ease;
            transition: all 5s ease;
}
.wide {
    width: 200px;
}

2 - jQuery 的.animate() 函数

example jsfiddle

jQuery:

var div = $('<div class="trans" />');
$('#container').append(div);
div.animate({'width': '200px'}, 5000); // 5 sec animation

CSS:

.trans {
    width: 20px;
    height: 20px;
    background-color: cyan;
}

【讨论】:

    【解决方案2】:

    不依赖 setTimeout 的更简洁的方法是在设置之前读取有问题的 css 属性:

    var div = $('<div />').addClass('trans');
    $('#container').append(div);
    div.css('width');//add this line
    div.css('width', '200px');
    

    在这里工作:

    http://jsfiddle.net/FYPpt/144/

    正如 Lucero 在下面的 cmets 中所解释的,这样做有必要强制浏览器计算实际值,而不是“自动”、“继承”或类似的值。如果没有实际值,浏览器将不会知道新值是对先前值的更改。

    【讨论】:

    • +1 - 根据现有值(例如“none”),浏览器需要首先处理新布局以识别触发转换的更改(例如数字到数字)。读取 CSS 属性会强制计算布局。
    • 为我节省了一些研究时间,这正是我所需要的。这么傻的要求……
    • 这是一个比使用 setTimeout 更好、更干净的解决方案。
    【解决方案3】:

    尝试调用 jQuery 的 .offset() 方法。

    当浏览器获得偏移量时,它会触发一个 reflow/repaint/layout 事件,允许转换工作。

    看到这个小提琴:http://jsfiddle.net/FYPpt/199/

    另见 -- http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html

    【讨论】:

    • 这与在接受的答案中使用div.width(); 时相同
    • 这更简洁,因为它不依赖于 CSS 过渡值,我认为这是在接受的答案中建议宽度的原因。
    • 谢谢,如果您更改大量属性或不想在 JS 代码中硬编码 CSS 属性,这将特别有用。
    【解决方案4】:

    正如@onetrickpony 所问,如果所有规则都在 CSS 文件中并且不应该添加到 JS 函数中怎么办。

    根据 Torin Finnemann 的回答,稍作改动:

    添加一个额外的类来定义规则:new-rules

    var div = $('<div class="trans" />');
    $('#container').append(div);
    
    var div = $('<div />').addClass('trans');
    $('#container').append(div);
    div.height();
    div.addClass('new-rules');
    

    在你的 CSS 中有预定义的类:

    .trans.new-rules {
        width: 200px;
        background: yellow;
    }
    

    现在在更改 CSS 时无需对 JS 感到刺痛。在 new-rules 的 CSS 文件中更改它:)

    http://jsfiddle.net/FYPpt/201/

    【讨论】:

      【解决方案5】:

      响应赏金:

      如果您不知道正在转换哪个属性,或者根本不认为强制setTimeout 触发动画是一个好习惯,您可以通过另一种方式强制回流。

      setTimeout 首先起作用的原因是因为在此期间您会​​导致整个文档重排,即使持续时间设置为0。这不是导致回流的唯一方法。


      Link to a fiddle

      JavaScript

      for (x = Math.ceil(Math.random() * 10), i=0;i<x;i++){
          $('<div />').appendTo($('#container')).addClass('trans');
      }
      
      var divs = $('#container div');
      var x = divs.eq(Math.ceil(Math.random() * divs.length));
      x[0].offsetHeight;
      x.addClass('wide');
      

      使用这个 JavaScript,我们随机添加 1 到 10 个 div 元素,然后随机选择其中一个并添加 wide 类。

      您会注意到其中有一行奇怪的 JavaScript,即 x[0].offsetHeight。这是整个操作的关键。调用 offsetHeight 会触发文档重排,而不使用 setTimeout 或查询 CSS 值。

      回流与 DOM 的关系:

      重排计算页面的布局。元素上的回流 重新计算元素的尺寸和位置,它还 触发该元素的子元素、祖先元素和 在 DOM 中出现在它之后的元素。然后它调用决赛 重绘。回流非常昂贵,但不幸的是它可以 很容易触发。

      所以请谨慎使用这些功能。对于大多数现代浏览器来说并不太担心(因为 jQuery 因触发多次重排而臭名昭著),但在您的网站上添加类似此解决方案的内容之前仍然需要考虑一些问题。


      重要提示:效率不亚于setTimeout调用。这不是一个灵丹妙药的解决方案,它在幕后做同样的事情。


      下面是对应的CSS,供参考:

      .trans {
          width: 20px;
          height: 20px;
          background-color: cyan;
          -webkit-transition: all 5s ease;
             -moz-transition: all 5s ease;
               -o-transition: all 5s ease;
                  transition: all 5s ease;
      }
      
      .trans.wide {
          width: 200px;
      }
      

      【讨论】:

      • 实际上调用width() 似乎可以完成这项工作,即使其他道具被过渡。我现在因为不测试而感到很傻:)
      【解决方案6】:
      var div = $('<div />');
      
      $('#container').append(div);
      
      div.css('width', '20px').addClass('trans', function() {
         div.css('width', '200px') 
      });
      

      创建一个新的 DIV 元素并将“trans”类添加到该元素以触发 CSS 过渡

      【讨论】:

      • 这是什么..?这是做什么的..?
      • 重新排序函数以便首先创建 div,然后是 addClass 和回调以在 addclasw 转换后设置宽度 - 它肯定会以这种方式触发......不确定确切代码的要求,但我知道这会工作
      • edit您的答案并在此处添加解释...此处不鼓励仅使用代码回答...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-10
      相关资源
      最近更新 更多