始终触发且仅触发一次的“transitionend”事件

2024-02-24

我需要一个特别的transitionend-like 事件,在所有转换完成后触发一次,或者如果 CSS 中没有定义转换则立即触发。

这是我到目前为止所想到的:

(function($){

  $.event.special.transitionsComplete = {

    setup: function(data, namespaces, eventHandle){    
      var queue = [],
          style = window.getComputedStyle(this, null),
          computedProps = style.getPropertyValue('transition-property').split(', '),
          computedDurations = style.getPropertyValue('transition-duration').split(', '),
          $node = $(this);          

      // only count properties with duration higher than 0s
      for(var i = 0; i < computedDurations.length; i++)
        if(computedDurations[i] !== '0s')
          queue.push(computedProps[i]);           

      // there are transitions
      if(queue.length > 0){
        $node.on('webkitTransitionEnd.x transitionend.x', function(e){          
          queue.splice(queue.indexOf(e.originalEvent.propertyName));          
          if(queue.length < 1)
            $node.trigger('transitionsComplete');
        });

      // no transitions, fire (almost) immediately
      }else{
        setTimeout(function(){
          $node.trigger('transitionsComplete');
        }, 5);

      }

    },

    teardown: function(namespaces){
      $(this).off('.x');
    }

  };
})(jQuery);

我做了一个活生生的例子here http://jsfiddle.net/nf8gvbuo/.

唯一的问题是,它仅在元素本身具有转换属性时才有效,忽略子元素的转换。如果我切换transitionsComplete to transitionend父事件处理程序和子事件处理程序都在子转换完成后运行。有没有某种方法,或者更好的方法来确定一个元素或其子元素是否发生转换?如果可能的话,我想避免手动检查子项并检查它们的转换属性。 (无论如何,这都不可靠,因为即使有些孩子有过渡,也不意味着他们在那个时候会很活跃)


我用过树行者 API https://developer.mozilla.org/en/docs/Web/API/TreeWalker遍历原始节点(根)和所有子节点(仅限元素),过滤掉没有过渡的元素,并收集过渡属性queue (fiddle http://jsfiddle.net/7q8psw14/13/)。正如你所看到的,我已经解决了之间的时差complete-div and complete-p,他们现在(几乎 - 几毫秒)同时开火。

有两个警告,我没有解决方法:

  1. 如果存在通过不同方式触发的转换,对于 示例一是通过添加触发的.visible to the div,以及 其他通过添加.invisible,它们都会被添加到queue。该事件永远不会触发,因为queue永远不会空 - 我不知道如何解决这个问题。
  2. 如果存在快捷方式属性的转换(padding为了 示例),多个transitionend事件可能会被触发,transition-property, 例如padding-top, padding-right等等...这个 将导致数组很快变空splice(-1, 1)从数组末尾删除项目。我曾有一个解决方法 http://jsfiddle.net/7q8psw14/11/, 但 这可能会导致问题,因为它可能会删除queue。最好的解决方法是不要通过快捷方式进行转换 特性。

TreeWalker 的代码基于 Ban Nadel 的 -使用 TreeWalker 在 DOM 中查找 HTML 注释节点 http://www.bennadel.com/blog/2607-finding-html-comment-nodes-in-the-dom-using-treewalker.htm.

最后是代码:

(function ($) {

    $.event.special.transitionsComplete = {

        setup: function (data, namespaces, eventHandle) {
            var TRANSITION_PROPERTY = 'transition-property';
            var TRANSITION_DURATION = 'transition-duration';

            var root = this;
            var queue = [];
            var $node = $(this);

            function filter(node) { // filter for treeWalker
                /*** filters transitions which are a string with one '0s'. If more then '0s' is defined it will be catched when creating the queue ***/
                var computedDuration = window.getComputedStyle(node, null)
                    .getPropertyValue(TRANSITION_DURATION);

                return computedDuration === '0s' ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT;
            }

            filter.acceptNode = filter; // for webkit and firefox

            /** create the treeWalker to traverse only elements **/
            var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, filter, false);

            /** traverse all elements using treeWalker.nextNode(). First node is the root **/
            do {
                var style = window.getComputedStyle(treeWalker.currentNode, null);
                var computedProps = style.getPropertyValue(TRANSITION_PROPERTY).split(', ');
                var computedDurations = style.getPropertyValue(TRANSITION_DURATION).split(', ');

                /** push all props with duration which is not 0s **/
                computedDurations.forEach(function (duration, index) {
                    duration !== '0s' && queue.push(computedProps[index]);
                });
            } while (treeWalker.nextNode()); // iterate until no next node

            // no transitions, fire (almost) immediately
            if (queue.length === 0) {

                setTimeout(function () {
                    $node.trigger('transitionsComplete');
                }, 5);

                return; // return out of the function to skip the transitions block
            }

            // there are transitions
            $node.on('webkitTransitionEnd.x transitionend.x', function (e) {
                var propertyName = e.originalEvent.propertyName;
                var indexOfProp = queue.indexOf(propertyName);

                queue.splice(indexOfProp, 1);

                if (queue.length < 1) {
                    console.log('Transitions Complete');
                    $node.trigger('transitionsComplete');
                }
            });

        },

        teardown: function (namespaces) {
            $(this).off('.x');
        }

    };
})(jQuery);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

始终触发且仅触发一次的“transitionend”事件 的相关文章

随机推荐

  • 从 xcode 命令行生成 ipa

    从命令行生成 IPA 文件的最佳方法是什么 我使用的是 xcode 4 2 并使用以下命令生成存档 xcodebuild scheme AppStore clean archive 协同设计后 这会在构建输出目录中生成 dSYM 和 app
  • XAML 中的字符串格式

    我正在尝试格式化我的string每 3 个位置有一个逗号 如果不是整数则有一个小数 我检查了大约 20 个例子 这是我得到的最接近的例子
  • 如何在 iTunes 上获取我的应用程序统计信息?

    我最近发布了一款 iPhone 应用程序 但我没有看到任何方法可以像在 Google Play 中一样检查应用程序统计信息 您能告诉我该怎么做吗 你可以从iTunes连接 https itunesconnect apple com 登录您的
  • Java 贪吃蛇游戏避免使用 Thread.sleep

    我用 Java 制作了我的第一个游戏 贪吃蛇 它的主循环看起来像这样 while true long start System nanoTime model eUpdate if model hasElapsedCycle model up
  • 通过代码使卸载注册表项成为有条件的

    如何禁用 Inno SetupCreateUninstallRegKey http www jrsoftware org ishelp index php topic setup createuninstallregkey通过代码 My 安
  • 在每个“X”React 组件之后插入一个元素

    我有一个 React 组件 它使用 Bootstrap 将项目列表呈现为三列col col md 4风格 但是 我需要插入一个clearfix div http getbootstrap com css grid responsive re
  • git 无法执行任何任务

    我在 Windows 7 上使用 Git 我是从那里下载的http git scm com download http git scm com download 无论我重新安装 Git 并尝试执行某些操作 甚至克隆都不起作用 多少次 它都无
  • ant sql insert 语句在“--”字符串上失败。解决方法?

    Context 我们正在更改安装脚本以使用 ant 的 sql 任务和 jdbc 而不是专有的 sql 客户端 sqlplus oracle 和 osql msft 更新 添加了更多上下文 我们的 基础数据 种子数据 由一组 sql 文件组
  • 代码签名时是否/如何避免 SHA-1 签名时间戳?

    我们刚刚从 SHA 1 切换到 SHA 2 代码签名证书 作为背景信息 我们使用 COMODO 代码签名证书 使用signtool exe 在 Windows 上对 exe 和 xap 文件进行签名 我们使用经过认证的时间戳来执行此操作 以
  • UNIX时间是通用的吗

    我在互联网上做了一些研究 但仍然很困惑 UNIX 时间是像 GMT UTC 一样的通用时间还是像当地时间一样因地而异 我知道 UNIX 时间是从 1970 年 1 月 1 日 00 00 00 GMT 开始计算的 当我在 Java 中使用
  • 让 tkinter 使用 asdf 在 macos 上使用 python 3.x [重复]

    这个问题在这里已经有答案了 所以我很困惑 如何让 python 3 7 x 与 tkinter 和 asdf 一起使用 我做了以下事情 1 asdf local python 3 7 4 2 brew install tcl tk 3 br
  • 如何获取jquery锚点href值

    jQuery document ready function a change status click function var status id a val alert status id return false HTML a hr
  • 如何打开/关闭 iPhone 相机闪光灯?

    如何以编程方式打开 关闭 iPhone 的 LED 相机闪光灯 import
  • Python 中的 MATLAB ks密度等效项

    我在网上查看过 但尚未找到答案或方法来计算以下内容 我正在将一些 MATLAB 代码翻译为 Python 其中在 MATLAB 中我希望使用以下函数找到核密度估计 p x ksdensity data 其中 p 是分布中 x 点的概率 Sc
  • 模板类中的 C++ 静态常量数组初始化

    我有以下模板类 template
  • 哪些注册表项决定 Outlook 配置文件

    我需要编写 VBScript 代码来检查 Outlook 是否使用 MAPI 配置文件或 RPC over HTTP S 配置文件 哪个注册表项决定相同 这在 Outlook 2013 中发生了变化 Outlook 2013 开发人员的新增
  • 如何在 Blazor 中直接更改 css(不带变量)?

    我正在使用 Blazor 的服务器端 我想改变body的CSS 在 Jquery 中我可以轻松地编写这样的代码 body css overflow y hidden 但是 通过本教程 Blazor 更改验证默认 css 类名称 https
  • $http.jsonp() 是如何工作的

    这是一个例子 json file name Jon Skeets name Bill Joy 如果这个 json 文件的获取方式为 http jsonp pathToFile then 它返回 404 没有任何问题pathToFile我已经
  • Blade 中的嵌套部分

    我正在研究 Blade 如何实现 section 但它的工作方式与我习惯的 Twig 略有不同 看来你不能将 sections嵌套在一起 Example layout blade php 基本布局文件 favicons meta conte
  • 始终触发且仅触发一次的“transitionend”事件

    我需要一个特别的transitionend like 事件 在所有转换完成后触发一次 或者如果 CSS 中没有定义转换则立即触发 这是我到目前为止所想到的 function event special transitionsComplete