transitionEnd事件与多个转变,检测最后过渡

问题描述 投票:5回答:3

transitionEnd事件上结束第一和好景不长,这是不期望的行为转变解雇。任何变通办法?

document.querySelector('a').addEventListener('transitionend', function(){
  var time = (new Date().getMinutes()) + ':' + (new Date().getSeconds());
  console.log('transitionEnd - ', time);
});
a{
  display:block;
  opacity:.5;
  width:100px;
  height:50px;
  background:lightblue;
}
a:hover{
  width:200px;
  height:100px;
  background:red;
  transition: 4s width,     /* <-- "transitionEnd" should fire after this */
              2s height,
              .5s background;  
}
<a>Hover me</a>

现在,我在Chrome检查(我不使用该浏览器),我看到该事件被调用3次,每次转变之一。无论如何,我需要它火是最后一个,在Firefox浏览器。 (我不知道有多少跃迁的元素无论如何,要知道这是最后一次)

javascript dom
3个回答
3
投票

transitionEnd返回一个事件对象调用propertyName属性。 Source

因此,你可以测试你想要的属性,并使用简单的逻辑来过滤回调:

document.querySelector('a').addEventListener('transitionend', function(event){
    if(event.propertyName !== 'width') return;
    console.log('transitionEnd - width!');
});

2
投票

哈克解决方案的一点可能是,试图找出其中的CSS属性具有最长总持续时间。您可以使用您的window.getComputedStyle元素<a>上添加了所有durationdelay性质这么做。

你可以在被触发三次在定期事件处理程序做到这一点(这是相当快),或做出预先计算你正在寻找的属性名称的功能。

主要问题这种方法:

  • CSS允许您使用mss在一个声明中,你可能需要做一些更多的计算。
  • 它可以是一种很难预测计算的风格是什么,当你改变悬停在transition风格或转换之后之前添加新的类时/。

var getValues = function(str) {
  return str
    .replace(/[A-Z]/gi, "")
    .split(", ")
    .map(parseFloat);
};

var getMaxTransitionProp = function(el) {
  var style = window.getComputedStyle(el);
  var props = style.transitionProperty.split(", ");

  var delays = getValues(style.transitionDelay);
  var durations = getValues(style.transitionDuration);
  var totals = durations.map(function(v, i) {
    return v + delays[i];
  });

  var maxIndex = totals.reduce(function(res, cur, i) {
    if (res.val > cur) {
      res.val = cur;
      res.i = i;
    }
    return res;
  }, {
    val: -Infinity,
    i: 0
  }).i;

  return props[maxIndex];
}

var lastEventListenerFor = function(el, cb) {
  var lastProp = getMaxTransitionProp(el);
  return function(e) {
    if (e.propertyName == lastProp) {
      cb(e);
    }
  };
}

var a = document.querySelector("a");
var cb = function(e) {
  console.log("End");
};

a.addEventListener("transitionend", lastEventListenerFor(a, cb));
a {
  display: block;
  opacity: .5;
  width: 100px;
  height: 50px;
  background: lightblue;
  transition: 3s width,
  /* <-- "transitionEnd" should fire after this */
  2s height, .5s background;
}
a:hover {
  width: 200px;
  height: 100px;
  background: red;
}
<a>Hover me</a>

1
投票

我现在是老也许问题,但遇到同样的麻烦。解决了这种方式:

document.querySelector('a').addEventListener('click', function(e){
  this.classList.toggle('animate');
  let style = window.getComputedStyle(this, null);
  Promise.all(style.transition.split(',').map((prop) => {
     prop = prop.trim().split(/\s+/);
     return Promise.race([
         new Promise((resolve) => {
              let h = (e) => {
                   if (e.propertyName == prop[0])
                        resolve('transitionEnd ' + prop[0]);
              };
              this.addEventListener('transitionend', h, {once:false});
         }),
         new Promise((resolve) => 
              setTimeout(
                  () => resolve('TIMEOUT ' + prop[0]),
                  prop[1].replace(/s/,'')*1000 + 100
              )
         )
     ])
  }))
  .then((res) => {
     console.log(res + 'DONE!!!!');
     /*  do your stuff */
  });
});

说明:

  • 首先我们确定是什么性质实际上应该改变,再拆/地图/转换它来执行操作。通常它有格式,如:“宽度4S缓解0,高度2S缓解0,..”
  • 接下来我们使用Promise.race,因为并不总是transitionEnd将triggerred(无论是道具的两种状态相同,或道具的名字将不会在规则和事件相匹配(背景可能是背景颜色),以及其他),我们需要TP退回到简单的超时
  • 我们终于等到每个属性都超时/事件监听器

免责声明:

  • 它的例子,我承认它使用了大量的魔法,错过了很多检查
  • “回调”将即使在情况下,如果动画被取消了被解雇(超时无论如何会闪光)
  • 需要ES6 :)

你可以用它在jsfiddle

© www.soinside.com 2019 - 2024. All rights reserved.