【问题标题】:How to stop d3.drag triggering mouseover/mouseout events in chrome如何停止 d3.drag 在 chrome 中触发 mouseover/mouseout 事件
【发布时间】:2014-10-16 14:17:41
【问题描述】:

我有以下 d3 可视化。顶部较深的颜色表示已选择一个节点。当我将鼠标悬停在未选择的节点上时,它会更改不透明度,因此用户可以看到如果我单击将选择哪个节点。

这是通过 CSS 样式表和以下 js/d3 实现的:

nodeSelection.select("circle").on('mouseover', function(e) {
             d3.select(this).classed("hover", true);
            _this.fireDataEvent("mouseOverNode", this);
        });

        nodeSelection.select("circle").on('mouseout', function(e) {
            d3.select(this).classed("hover", false);
            _this.fireDataEvent("mouseOutNode", this);
        });

到目前为止,一切都很好。但是,当我拖动时,拖动功能似乎会在我没有拖动的节点上随机触发鼠标悬停和鼠标移出事件。这会导致节点不透明度闪烁。如果我查看 chrome 中的开发工具,我可以看到这是因为它导致节点获得类“悬停”。上面添加这个 CSS 类的代码没有出现在其他地方,并且通过使用控制台日志记录,我已经确认 mouseover 和 mouseout 事件正在被触发。这些节点通常离光标很远。

在 Firefox 中不会出现此问题。

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    更新:我实际上在发布后几乎立即解决了这个问题。我只是在拖动开始时明确取消注册监听器,然后在拖动结束时重新注册。如果他们有类似的问题,对某些人来说可能仍然很有趣。

    我的拖动功能现在看起来像:

    var drag = d3.behavior.drag()
                .on("dragstart", function(d) {
                    console.log("dragstart");
                    d.dragstart = d3.mouse(this); // store this
                    d.fixedbeforedrag = d.fixed;
                    d.fixed=true;
    
                    // deregister listeners
                    nodeSelection.select("circle").on("mouseover", null).on("mouseout", null); 
                })
                .on("drag", function(d) {
                    d.px = d.x; // previous x
                    d.py = d.y;
                    var m = d3.mouse(this);
                    d.x += m[0] - d.dragstart[0];
                    d.y += m[1] - d.dragstart[1];
                    nodeSelection.attr("transform", "translate(" + [d.x, d.y] + ")");
                    _this.getForce().start();
                })
                .on("dragend", function(d) {
                    console.log("dragend");
                    delete d.dragstart;
                    d.fixed = d.fixedbeforedrag;
                    //reregisters listeners
                    _this.updateSVG(); 
                });
    

    【讨论】:

    • 我不确定这是否是正确的方法。我搜索了相同的主题并出现了 if (d3.event.defaultPrevented) return;和 d3.event.sourceEvent.stopPropagation();表达式,但我仍然不确定如何正确放置它们以防止拖动时鼠标悬停。
    • d3.event.defaultPrevented 将阻止默认浏览器行为。停止传播可防止将事件向上发送到 DOM 层次结构。这些都不会阻止调用同一对象的显式侦听器。造成这种情况的根本原因是/是 chrome 中的一个错误,这意味着它没有很好地保持 svg 元素的位置和鼠标指针的集成度,所以它触发 mouseout 只是因为它没有足够快地更新元素位置。然后当它赶上时鼠标悬停。这类问题不断得到修复/再次发生。
    • jQuery 在鼠标悬停的拖动交互中表现出类似的问题。我怀疑这是由于您引用的 Chrome 错误。删除 mouseover 事件处理程序(使用 .off())似乎是唯一的解决方案。感谢您发布此内容,因为它解决了我的问题。不同的软件相同的表现。
    • 我很高兴它有帮助。我的猜测是因为 chrome 在多个线程中执行 JavaScript,所以它可以异步更新鼠标指针与 svg 元素。
    猜你喜欢
    • 2015-02-25
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    相关资源
    最近更新 更多