【问题标题】:CSS Transitions applied even if activated after state change?即使在状态更改后激活 CSS 转换也适用?
【发布时间】:2012-04-04 04:24:46
【问题描述】:

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

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 过渡的方法吗?

【问题讨论】:

  • 回调函数在我的示例中不再起作用。它没有重新添加课程。
  • 查看我的答案中的最后一个编辑以获得不显眼的解决方法。

标签: jquery html css-transitions


【解决方案1】:

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

在过渡之前,应用哪种顺序样式实际上并不重要,因为实际上,顺序并不重要,只是具体性。但是随着过渡,样式中添加了时间延迟的元素,这是问题的症结所在。

不知道任何浏览器如何应用样式,我猜 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)。

编辑

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

  1. CSS left: 300px 添加到 DOM 元素
  2. 样式渲染:浏览器检查元素上是否有过渡。如果是,请制作动画,如果不是,请立即申请。在这种情况下,还没有过渡(还),因此不会出现动画。
  3. CSS transition: left 2s ease-out 添加到 DOM 元素
  4. 呈现的样式:没有呈现变化,过渡适用于未来的left 变化。

但是,如果浏览器优化 CSS 的呈现,通过在代码块的末尾进行分组(或类似的东西),你会得到:

  1. CSS left: 300px 添加到 DOM 元素
  2. CSS transition: left 2s ease-out 添加到 DOM 元素中
  3. 已达到渲染点(代码块结束等),所有样式均已渲染:
  4. 当应用left 时,浏览器会检查元素上是否有过渡。如果是,请制作动画,如果不是,请立即申请。在这种情况下,存在一个过渡,因此会出现动画。

因此,动画的长度和您等待的时间无关紧要。重要的是 left: 300px 在应用过渡之前被渲染。目前,在 WebKit 中,这意味着将 transition 样式应用到一个单独的、晚于 left 样式的代码块中。这是通过所有建议的答案setTimeout(延迟为 0 的事件)、单独的单击处理程序(如果应用第二个)或函数回调来完成的。

这是另一种可行的方法:

$('button#nodelay').on('click', function() {
    var $el = $('#square');
    $el.removeClass('csstransition');
    $el.css('left', '100px').css('left'); // <-- This (or .show() even)
    $el.addClass('csstransition');
});

这是可行的,因为您正在强制浏览器停止并评估 CSS,以便您可以获得 left 的值(尽管您可以在第二个 .css() 调用中放置任何有效的 css 属性)。在这种情况下,它会应用所有 CSS 并强制元素重新渲染。

【讨论】:

  • 为什么不用回调函数呢?两个点击处理程序似乎非常多余。
  • 当然。我证明了关键是两个代码块。他已经有了解决setTimeout 问题的有效解决方案。选择最有效且最不易混淆的一种。
  • 设置超时似乎不是一个有效的解决方案,因为它依赖于动画只需要一定的时间。如果您将超时设置为低,则您将回到第一格。回调适用于这种情况。此外,为了回答您的问题,Chrome 和 Safari(特别是 webkit 浏览器)使用所谓的动画帧,可以设置或依赖于硬件。老源:blog.chromium.org/2011/03/…
  • 不正确,setTimeout 可以为 0。重要的是代码块不同。如果在left css 更改之后 应用过渡,则不会出现动画。动画的时间无关紧要。
  • 好的,我明白你的意思了。我的解释非常简单,但是,回调仍然是最优雅/最直观的方法。问题与执行调用的顺序有关,使用回调可确保在动画完成之前不会调用 addClass。
猜你喜欢
  • 1970-01-01
  • 2021-07-26
  • 2016-05-19
  • 2022-11-04
  • 1970-01-01
  • 2017-11-06
  • 2021-09-29
  • 1970-01-01
  • 2021-01-23
相关资源
最近更新 更多