【问题标题】:CSS transition with pure JS without delay无延迟的纯 JS 的 CSS 过渡
【发布时间】:2016-11-11 22:16:56
【问题描述】:

我想要实现的是从 js 更改某些属性(上面代码中的background-color)两次,以便在它们之间运行转换,但不会从前一个状态到第一个状态。上面的代码几乎从不工作,因为超时设置为零,它几乎总是在它设置为至少 10 时工作,当我将它设置为 100 时它总是在我的机器上工作。我还想要的是完全避免超时和以太线性或基于适当的事件回调运行代码(到目前为止我没有发现任何有用的)。

这是一个示例 (also on jsFiddle):

var outter = document.getElementById('outter');
var test = document.getElementById('test');

test.onclick = function() {
  outter.removeChild(test);
    test.style.backgroundColor = 'green'
  outter.appendChild(test);
  setTimeout(function() {
    test.style.backgroundColor = 'red'
  }, 0);
}
#test {
  position: fixed;
  left: 2em;
  right: 2em;
  top: 2em;
  bottom: 2em;
  background-color:red;

  transition-duration: 2s
}
<div id=outter>
  <div id=test></div>
</div>

【问题讨论】:

  • 所以在点击时,您希望背景立即变为绿色,然后花两秒钟时间从绿色变为红色?
  • @T.J.Crowder 没错!这里最重要的是“立即”这个词
  • 我不明白,想立即从 A 过渡到 B,然后从 A 过渡到 B,但有延迟。你已经在 B 了。
  • 为什么要从 DOM 中删除 test,然后在将其添加回 DOM 之前更改其颜色?
  • @Crowes 从任何地方到 A 没有延迟,然后从 A 到 B 有动画

标签: javascript css css-transforms


【解决方案1】:

没有超时:

var outter = document.getElementById('outter');
var test = document.getElementById('test');

test.onmousedown= function() {
    test.style.transitionDuration = "0s";
    test.style.backgroundColor = 'green';
};

test.onmouseup= function() {
    test.style.transitionDuration = "2s";
    test.style.backgroundColor = 'red';
};
#test {
  position: fixed;
  left: 2em;
  right: 2em;
  top: 2em;
  bottom: 2em;
  background-color:red;
}
<div id=outter>
  <div id=test></div>
</div>

【讨论】:

  • 我真的很喜欢您的解决方案,因为它是最狡猾的解决方案,并且在与我描述的完全相同的条件下工作得很好,但是我不仅需要通过点击来触发该动画而且我不能依赖不幸的是,这里的用户输入(mousedown/mouseup 对)。
【解决方案2】:

我设法在变绿时使用了一个非常短的过渡并使用transitionend 处理程序(遗憾的是,它仍然需要供应商前缀——是的)。

以下内容适用于 Firefox、Chrome 和 IE11。 (我应该注意,您不必使用类,我只是更喜欢在 CSS 中保留样式;您可以使用 outter.style.transitionDuration = "2s"; 等。)

var outter = document.getElementById('outter');
var test = document.getElementById('test');

function onTransition(element, handler, add) {
  var method = (add ? "add" : "remove") + "EventListener";
  element[method]("transitionend", handler, false);
  element[method]("mozTransitionEnd", handler, false);
  element[method]("webkitTransitionEnd", handler, false);
}

test.onclick = function() {
  // If we're running...
  if (outter.classList.contains("green")) {
    // ...reset
    onTransition(outter, greenToRed, false);
    onTransition(outter, redDone, false);
    outter.classList.remove("green", "red");
  }
  onTransition(outter, greenToRed, true);
  outter.classList.add("green");
};

function greenToRed() {
  onTransition(outter, greenToRed, false);
  onTransition(outter, redDone, true);
  outter.classList.add("red");
}
function redDone() {
  onTransition(outter, redDone, false);
  outter.classList.remove("green", "red");
}
#test {
  position: fixed;
  left: 2em;
  right: 2em;
  top: 2em;
  bottom: 2em;
  background-color: red;
}

.green #test {
  background-color: green;
  transition-duration: 0.0001s;
}
.red #test {
  transition-duration: 2s;
  background-color: red;
}
<div id=outter>
  <div id=test></div>
</div>

当然,以上只是概念验证;它可以被提炼和清理。

【讨论】:

  • 这看起来不错,只是它不像原来的例子那样工作 - 在动画的时刻点击会完全破坏它,到目前为止我看不到任何方法可以在你的代码中避免这种情况。
  • @Grief:你的意思是点击它,然后在绿色到红色的两秒内再次点击它?如果是这样,你想发生什么?忽略第二次点击?重新开始?
  • 我想像原来的 sn-p 一样重新开始动画。忽略就像删除 onclick 处理程序一样简单,直到 transitionend。
  • @Grief:我已更新以处理该问题,请参阅对 onload 的更改。
  • 现在可以使用了,非常感谢。现在我必须了解这种方法并将其应用于我的项目:)
猜你喜欢
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-07-17
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 2014-03-17
相关资源
最近更新 更多