Javascript 是否可以在不使用事件的情况下检查CSS转换是否完成?

Javascript 是否可以在不使用事件的情况下检查CSS转换是否完成?,javascript,css-transitions,Javascript,Css Transitions,是否可以通过JavaScript验证CSS转换是否已完成,而无需预先注册转换事件 问题是: 我有一个Web应用程序,它使用CSS转换在页面加载时淡入某些元素 我无法修改此Web应用程序JavaScript代码 当我访问此页面时,我可以在浏览器控制台中执行JavaScript 在继续使用自定义java脚本代码之前,我想确保CSS转换100%完成 在浏览器控制台中,我可以钩住转换事件,但在很多情况下,这会失败,因为: 转换元素还不存在 设置挂钩时,动画已经完成 是否有可能通过JavaScri

是否可以通过JavaScript验证CSS转换是否已完成,而无需预先注册转换事件

问题是:

  • 我有一个Web应用程序,它使用CSS转换在页面加载时淡入某些元素
  • 我无法修改此Web应用程序JavaScript代码
  • 当我访问此页面时,我可以在浏览器控制台中执行JavaScript
  • 在继续使用自定义java脚本代码之前,我想确保CSS转换100%完成
  • 在浏览器控制台中,我可以钩住转换事件,但在很多情况下,这会失败,因为:
    • 转换元素还不存在
    • 设置挂钩时,动画已经完成
是否有可能通过JavaScript检查元素的CSS转换是否完成?在任何时候

我不能使用javascript事件(例如:)

No。
您所能做的最好的事情就是查看CSS以查看过渡持续时间。

这不是一个答案,而是一个快速构建的POC:

element.onclick=function(){
const color=0x1000 |(Math.random()*0x1000);
const prop=Math.random()<.5?“背景色”:“颜色”;
element.style[prop]=“#”+color.toString(16.slice(-3);
}
设curr={};
requestAnimationFrame(函数检查(){
const prev=当前值;
curr=Object.assign({},getComputedStyle(元素));
const changed=Object.keys(curr.filter)(key=>curr[key]!==prev[key]);
out.innerHTML=changed.map(key=>`
  • ${key}
  • `).join(“\n”); requestAnimationFrame(检查); });
    html,
    身体{
    宽度:100%;
    身高:100%;
    保证金:0;
    填充:0;
    }
    #元素{
    光标:指针;
    宽度:100%;
    身高:100%;
    填充:20px;
    过渡:所有1;
    }
    
    点击某处

    目前正在过渡:
      ; 抱歉耽搁了,我正在开会。搜索了我的一个旧项目,但找不到。我将在这里概述这个想法,我最初认为也许我们可以选择突变观察者,但是我们也必须在那里进行定期检查。所以我想这个就行了。首先,你应该避免一些事情:

      • 在每一帧调用getComputedStyle是一个坏主意,因为调用和触发layout是一个非常昂贵的func,所以您应该改为节流
      • 硬拷贝样式对象,这是一个要复制的大对象,因此您应该传递一个特定属性的参数
      • 使用节点引用时,如果节点不在那里,如您所说,这将抛出引用错误,而使用函数返回节点
      第一件事是编写一个helper函数,该函数将定期运行一些测试函数,并在成功时返回:

       function watchman(obj,test,action,options){
          var currentFrame = {value:undefined};
          function watch(){
            if(test.call(obj,options)){
              action.call(obj,options);
              return;
            } else {
              currentFrame.value = window.requestAnimationFrame(watch);
            }
          };
          currentFrame.value = window.requestAnimationFrame(watch);
          return currentFrame;
        };
      
      接下来是实际的函数,我认为不需要创建新对象,我们可以创建一个包含3(2个可选)参数的函数,节点“functor”,要检查的样式属性,最后是要调用的函数

       function onTransitionEnd(fNode,prop,f,precision,timeout){
          precision = precision || 5;
          timeout = timeout || Infinity;
          return new Promise(function(res){
            var node = fNode(),
                oValue = node && getComputedStyle(node)[prop],
                currentFrame = watchman(
                  fNode,
                  function(counter){ 
                    if(counter.counter * 17 >= timeout){
                      window.cancelAnimationFrame(currentFrame.value);
                    }
                    if(++counter.counter % precision === 0) {
                      if(!this()){return}
                      var nValue = getComputedStyle(this())[prop];
                      if(nValue === oValue) {
                        return true;
                      }
                      oValue = nValue;
                    }
                  },
                  function(counter){
                    res(f.call(fNode(),prop));
                  },
                  {counter:0}
                );
          });
        };
      
      默认精度为5意味着函数将每5个刻度,5*17毫秒检查一次值,以确定转换是否结束。超时也是可选的,它将在一段时间后取消运行

      如果节点不在那里,这不是问题,因为我们正在传递一个返回节点或null的函数,如果节点不在那里,它将不会执行

      上面是一个承诺,它将返回一个“thenable”对象,您可以根据自己的喜好来链接它

      简单用例,例如,在更改样式或类之后:

      document.getElementById("someDiv").className = "def c1";
      onTransitionEnd(
        function(){return document.getElementById("someDiv");},
        "transform",
        function(){alert("heyy!!");}
      );
      
      它现在会提醒你“嘿”。要将此链接:

      document.getElementById("someDiv").className = "def c1";
      onTransitionEnd(
        function(){return document.getElementById("someDiv");},
        "transform",
        function(prop){alert("heyy!!"); return this;}
      ).then(function(node){
          node.className  = "def";
          return onTransitionEnd(
          function(){return document.getElementById("someDiv");},
          "transform",
          function(){alert("heyy-2!!"); return this;}
        );
      }).then(function(node){
          alert("id is " + node.id);
      });
      
      以下是一些例子:

      • )
      • )
      • )
      对于最后一个要工作的,打开开发者控制台,选择蓝色div并将其id更改为“someDiv”,函数将执行

      您可能想知道是否在每次更改样式时调用onTransitionEnd,在这种情况下,您可以编写一个包装器。如果你没有主意,告诉我我也会写的

      显然,您没有使用包装器,因此这里有一个帮助器包装器:

      function Select(node){
        this.node = node;
      };
        Select.prototype.style = function(prop,value,f){
          var node = this.node;
          this.node.style[prop] = value;
          f && onTransitionEnd(
            function(){return node;},
            prop,
            f
          );
          return this;
        };
      
      以下是您将如何使用它:

      var selection  = new Select(document.getElementById("someDiv"));
      selection
      .style("width","100px",function(propName){alert(propName + " changed!");})
      .style("height","100px",function(propName){alert(propName + " changed!");})
      .style("transform","scale(0.5,0.5)",function(propName){alert(propName + " changed!");});
      
      这是一个例子


      )

      事件意味着有人通知你。不使用事件意味着没有人通知您。这意味着你必须投票。GUI轮询最后一次是在DOS 16位模式下使用的。如果我发现我将发布,我可能正在寻找我的旧项目搜索示例@此外,只要GUI轮询做得好,它就没有问题。“GUI轮询上次是在DOS 16位模式下使用的”。它用于automation@ibrahimtanyalcinGUI轮询不能做得很好,因为这是一个愚蠢的想法。@ceving,“愚蠢”的想法在无法使用更好的想法的情况下是必要的。这不是一个最优解决方案的问题,正如OP所描述的那样,这是不必要的。第二,我建议你在与他人交谈时使用更好的语言,否则至少通过放置真实的个人资料照片来展示“游戏中的皮肤”。thx用于此解决方法!也许我可以用某种方式使用这种hackok-thx。我担心这是真的,但不确定:-/嗨,易卜拉欣!谢谢你的时间!你的解决方案帮助我理解了整个问题。似乎除了反复检查属性是否更改等之外没有其他可能性。例如,如果我稍微修改您的第一个示例,它将失败。“onTransitionEnd”已发出警报,即使动画尚未启动<代码>onTransitionEnd(function(){return document.getElementById(“someDiv”);},“transform”,function(){alert(“heyy!!”);});setTimeout(函数(){document.getElementById(“someDiv”).className=“def c1”;},10000)thx以获取答案。这对我帮助很大!不需要进一步回答:-)那是因为你还缺少1个元素,这就是“包装器”的概念,我问你是否知道