即使在状态改变后激活,也会应用CSS转换?

时间:2012-03-19 16:51:56

标签: jquery html5 css-transitions

我有一个jQuery插件可以在屏幕上移动一个元素,但是有一个“动画”切换来显示幻灯片过渡与否。在尝试使用CSS Transitions而不是Javascript转换进行更改时,我遇到了这个问题,我不确定它是否是一个bug /怪癖,或者我只是做错了:

var $item = $('#myItem');
if (!animate) {
  $item.removeClass('csstransitions'); // Class that has "transition:left 0.25s ease-out" 
  $('#myItem').css('left', '300px'); // Move the element
  $('#myItem').addClass('csstransitions'); // Re-apply transitions class
}

当这样做时,如果在转换类未应用于元素时发生css更改,但在之后立即应用,则某些浏览器(Chrome和Safari,在我的测试中) 仍然应用CSS转换 ,根据我的逻辑,它应该只是捕捉到新位置。

this jsFiddle中查看此操作;在Chrome或Safari中,单击“无延迟”按钮,看到它仍然为框的位置设置动画,而“延迟”按钮(使用超时设置一毫秒后)不会动画CSS更改

如jsFiddle所示,我必须使用setTimeout调用(setTimeout(function() { $el.addClass('csstransition'); }, 1);)才能在Chrome和Safari中获得正确的行为。这只是因为CSS过渡是最前沿的,或者我做错了什么,并且有一种更简单的方法可以暂时“转变”过渡?

编辑注意到this question是类似的,虽然答案只是将两个电话分开,但问题仍然是“为什么我们(网络开发人员)需要将这两个电话分开?“这是我们应该用来切换CSS过渡的方法吗?

1 个答案:

答案 0 :(得分:2)

我会投票支持怪癖或实施差异。

在转换之前,应用哪种订单样式并不重要,因为在实际应用中,顺序无关紧要,只是特异性。但是对于过渡,时间延迟的元素被添加到样式中,这是问题的关键。

不知道任何浏览器如何应用样式,我猜测Safari和Chrome会做一些优化,不必在每次样式更新后重新流动页面。相反,它们可能会等待特定的时间间隔或事件来进行更新,例如在代码块的末尾。

这里详细说明了一些差异:
http://taligarsiel.com/Projects/howbrowserswork1.htm

虽然,我不知道是否涵盖了这个具体问题。

作为演示,另一种处理方法是拥有2个点击处理程序:

$('button#nodelay').on('click', function() {
    var $el = $('#square');
    $el.removeClass('csstransition');
    $el.css('left', '100px');
}).on('click', function() {
    $el.addClass('csstransition');
});

这基本上将两个更新划分为单独的代码块,非常类似于setTimeout方法。

此外,由于转换仍然是草案标准,我不会依赖任何这种行为来保持一致,并且有些怪癖。 (我遇到了一个问题,即同时转换lefttop并不适用于所有浏览器。)

修改

为了进一步说明,如果浏览器在添加到DOM后立即呈现所有CSS,则会得到以下流程:

  1. 将CSS left: 300px添加到DOM元素
  2. 呈现样式:浏览器检查元素是否存在转换。如果是,则动画,如果不是,立即应用。在这种情况下,不是转换(尚未),因此不会发生动画。
  3. 将CSS transition: left 2s ease-out添加到DOM元素
  4. 呈现样式:无渲染更改,转换适用于将来的left更改。
  5. 但是,如果浏览器优化了CSS的呈现,通过在代码块的末尾(或类似的东西)进行分组,你得到这个:

    1. 将CSS left: 300px添加到DOM元素
    2. 将CSS transition: left 2s ease-out添加到DOM元素
    3. 到达渲染点(代码块结束等),渲染所有样式:
    4. 当应用left时,浏览器会检查元素是否有转换。如果是,则动画,如果不是,立即应用。在这种情况下,转换,因此动画会发生。
    5. 因此,动画的长度和等待的时间无关紧要。重要的是{<1}}在应用转换之前呈现。目前,在WebKit中,这意味着将left: 300px样式应用于与transition样式不同的单独的代码块中。这是通过建议的所有答案left(具有0延迟的事件),单独的单击处理程序(如果应用第二个)或函数回调来完成的。

      这是另一种有效的方式:

      setTimeout

      这样可行,因为您强制浏览器停止并评估CSS,以便您可以获得$('button#nodelay').on('click', function() { var $el = $('#square'); $el.removeClass('csstransition'); $el.css('left', '100px').css('left'); // <-- This (or .show() even) $el.addClass('csstransition'); }); 的值(尽管您可以在第二个left调用中放置任何有效的css属性) 。在这种情况下,它应用所有CSS并强制元素重新渲染。