在 JavaScript 中更改 HTML 元素的样式并暂时禁用其 CSS 转换并不能可靠地运行 [英] Changing an HTML element's style in JavaScript with its CSS transition temporarily disabled isn't reliably functioning

查看:23
本文介绍了在 JavaScript 中更改 HTML 元素的样式并暂时禁用其 CSS 转换并不能可靠地运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在为一个网站制作动画,其中涉及两个元素的位置在一段时间内发生变化,并且通常会重置为它们的初始位置.一次只能看到一个元素,一切都应该尽可能顺利.

Currently I am working on an animation for a website which involves two elements having their position changed over a period of time and usually reset to their initial position. Only one element will be visible at a time and everything ought to run as smoothly as possible.

在您询问之前,仅使用 CSS 的解决方案是不可能的,因为它是动态生成的并且必须同步.对于这个问题,我将使用一个非常简化的版本,它只包含一个向右移动的框.除非在此问题的其余部分明确说明以保持简单,否则我将仅提及后一个示例.

Before you ask, a CSS-only solution is not possible as it is dynamically generated and must be synchronised. For the sake of this question, I will be using a very simplified version which simply consists of a box moving to the right. I shall be referring only to this latter example unless explicitly stated for the remainder of this question to keep things simple.

无论如何,移动是由设置的 CSS transition 属性处理的,这样浏览器就可以完成繁重的工作.然后必须取消此转换,以便立即重置元素的位置.这样做的明显方法是这样做,然后在需要再次移动时重新应用transition,这也是立即的.但是,这不起作用.不完全的.我来解释一下.

Anyway, the movement is handled by the CSS transition property being set so that the browser can do the heavy lifting for that. This transition must then be done away with in order to reset the element's position in an instant. The obvious way of doing so would be to do just that then reapply transition when it needs to get moving again, which is also right away. However, this isn't working. Not quite. I'll explain.

查看此问题末尾或链接的 JSFiddle 中的 JavaScript,您可以看到这就是我正在做的事情,但 setTimeout 在两者之间增加了 25 毫秒的延迟.这样做的原因是(最好你自己尝试一下)如果没有延迟(这是我想要的)或非常短的延迟,元素将间歇性或持续地保持在原位,这不是想要的效果.延迟越高,它就越有可能起作用,尽管在我的实际动画中这会导致轻微的抖动,因为动画分为两个部分并且没有设计延迟.

Take a look at the JavaScript at the end of this question or in the linked JSFiddle and you can see that is what I'm doing, but setTimeout is adding a delay of 25ms in between. The reason for this is (and it's probably best you try this yourself) if there is either no delay (which is what I want) or a very short delay, the element will either intermittently or continually stay in place, which isn't the desired effect. The higher the delay, the more likely it is to work, although in my actual animation this causes a minor jitter because the animation works in two parts and is not designed to have a delay.

这似乎是一种可能是浏览器错误的事情,但我已经在 Chrome、Firefox 52 和当前版本的 Firefox 上对此进行了测试,结果都相似.我不确定从哪里开始,因为我无法在任何地方或任何解决方案/解决方法中找到报告的此问题.如果有人能找到一种方法使它按预期可靠地工作,将不胜感激.:)

This does seem like the sort of thing that could be a browser bug but I've tested this on Chrome, Firefox 52 and the current version of Firefox, all with similar results. I'm not sure where to go from here as I have been unable to find this issue reported anywhere or any solutions/workarounds. It would be much appreciated if someone could find a way to get this reliably working as intended. :)


这是 JSFiddle 页面,其中包含我的意思的示例.

标记和代码也粘贴在这里:

The markup and code is also pasted here:

var box = document.getElementById("box");
//Reduce this value or set it to 0 (I
//want rid of the timeout altogether)
//and it will only function correctly
//intermittently.
var delay = 25;

setInterval(function() {
  box.style.transition = "none";
  box.style.left = "1em";

  setTimeout(function() {
    box.style.transition = "1s linear";
    box.style.left = "11em";
  }, delay);
}, 1000);

#box {
  width: 5em;
  height: 5em;
  background-color: cyan;
  position: absolute;
  top: 1em;
  left: 1em;
}

<div id="box"></div>

推荐答案

在重置后设置新过渡之前强制 DOM 重新计算自身.例如,这可以通过读取框的偏移量来实现,如下所示:

Force the DOM to recalculate itself before setting a new transition after reset. This can be achieved for example by reading the offset of the box, something like this:

var box = document.getElementById("box");

setInterval(function(){
      box.style.transition = "none";
      box.style.left = "1em";
      let x = box.offsetLeft; // Reading a positioning value forces DOM to recalculate all the positions after changes
      box.style.transition = "1s linear";
      box.style.left = "11em";  
    }, 1000);

body {
  background-color: rgba(0,0,0,0);
}

#box {
  width: 5em;
  height: 5em;
  background-color: cyan;
  position: absolute;
  top: 1em;
  left: 1em;
}

<div id="box"></div>

另见 jsFiddle 的工作演示.

通常,当您设置其属性时,DOM 不会更新,直到脚本完成.然后重新计算和渲染 DOM.但是,如果您在更改 DOM 属性后读取它,它会立即强制重新计算.

Normally the DOM is not updated when you set its properties until the script will be finished. Then the DOM is recalculated and rendered. However, if you read a DOM property after changing it, it forces a recalculation immediately.

没有超时(和属性读取)的情况是,style.left 值首先更改为 1em,然后立即更改为 11em.转换发生在脚本完成后,并看到最后设置的值 (11em).但是,如果您读取更改之间的位置值,则过渡具有新的值.

What happens without the timeout (and property reading) is, that the style.left value is first changed to 1em, and then immediately to 11em. Transition takes place after the script will be fihished, and sees the last set value (11em). But if you read a position value between the changes, transition has a fresh value to go with.

这篇关于在 JavaScript 中更改 HTML 元素的样式并暂时禁用其 CSS 转换并不能可靠地运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆