javascript - 为什么在 Raphaël 中拖动会因在气泡阶段的封闭元素中停止 mousemove 的传播而中断?

标签 javascript dom-events raphael event-bubbling

我正在尝试调试复杂 Web 应用程序中的事件处理错误,但我已将问题简化为一个简单示例,该示例演示了令我感到困惑的行为。

我的示例页面基于 Raphaël 示例之一,如下所示:

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Raphaël · Drag-n-drop Example</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script src="http://github.com/DmitryBaranovskiy/raphael/raw/master/raphael-min.js"></script>
        <script>
            window.onload = function () {
                $('body').mousemove(function(e) {
                    // console.log("in body's mousemove");
                    // Uncommenting the next line stops the move
                    // function below from being called:
                    // e.stopPropagation();
                });
                var R = Raphael(0, 0, "100%", "100%");
                var r = R.circle(100, 100, 50).attr({fill: "hsb(0, 1, 1)", stroke: "none", opacity: .5});
                var start = function () {
                    this.ox = this.attr("cx");
                    this.oy = this.attr("cy");
                    this.animate({r: 70, opacity: .25}, 500, ">");
                },
                move = function (dx, dy) {
                    // console.log("in move function for the circle", this);
                    this.attr({cx: this.ox + dx, cy: this.oy + dy});
                },
                up = function () {
                    this.animate({r: 50, opacity: .5}, 500, ">");
                };
                r.drag(move, start, up);
            };
        </script>
    </head>
    <body>
        <div id="holder"></div>
    </body>
</html>

该版本按预期工作——您可以拖动红色圆圈——但取消注释 e.stopPropagation() 行中断拖动。如果您有 Firebug 或 Chrome 并取消注释 console.log 行,您会看到 move 函数从未被调用 - 不知何故 mousemove 处理程序因为 body 元素在事件到达圆的处理程序之前被调用。

我不明白这是怎么回事,因为 body 元素上的 mousemove 处理程序是在事件处理的冒泡阶段设置的。如果我明白the order in which events are processed正确地,此处调用 mousemove 处理程序的顺序大约是:

  1. 捕获阶段:body元素的mousemove(null)
  2. 捕获阶段:svg 元素的 mousemove (null)
  3. 捕获阶段:圆圈的鼠标移动(null)
  4. 气泡阶段:圆的 mousemove(在拖动开始时由 Raphaël 设置,并调用 move 函数)
  5. 气泡阶段:svg 元素的 mousemove (null)
  6. 气泡阶段:body 元素的 mousemove(如上设置,停止传播)

如果那是对的,我不明白在冒泡阶段停止在 body 的 mousemove 处理程序中传播事件会如何中断拖动,因为它应该发生在圆圈处理完事件。

如果有人能解释一下这个例子中发生了什么,特别是我是否误解了事件处理的工作原理,或者 Raphaël 实现拖动的方式有什么特别之处,那就太好了。

最佳答案

我试着在 Raphaël 邮件列表上询问这个问题,那里的回复解释说 Raphaël mousemove 处理程序实际上附加到 document,这解释了我所看到的行为。其中一个回复还解释了为什么拖拽需要这样实现:

关于javascript - 为什么在 Raphaël 中拖动会因在气泡阶段的封闭元素中停止 mousemove 的传播而中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6617548/

相关文章:

javascript - 目标高度未知(不固定)时如何实现元素高度过渡

javascript - 如何传递 css :active pseudo class to javascript?

javascript - 如何在 getElementsByClassName 中获取当前元素

javascript - 如何修复 javascript 和 raphaeljs 内存泄漏?

javascript - Raphael 2 - 鼠标按下时画线

javascript - 缩放后如何在 Raphael 中应用(或维护)线条样式?

javascript - 如何使用 lodash 按嵌套属性分组?

javascript - Window.onload 和排序

javascript - 如何获取文本区域的旧值

javascript - 为什么 Internet Explorer 9 不会对此单击事件使用react? [里面有简短的 jsFiddle 代码]