D3 onclick,onmouseover和mouseout行为覆盖

时间:2016-03-07 19:49:12

标签: javascript d3.js

我有一个D3多线图,它使用onclick mouseovermouseout事件的图例。单击图例将隐藏该行。将鼠标悬停在图例上将使该行变为粗体并将鼠标移除将使该线恢复正常。

问题是如果我点击图例然后在D3转换完成之前移除鼠标,则转换将无法完成。如果我将鼠标放在图例上足够长的过渡时间,一切正常。

要测试单击图例矩形并快速移出鼠标,该线条不会消失。

在这里小提琴:https://jsfiddle.net/goodspeedj/5ewLxpre/

鼠标事件的代码如下:

.on("click", function(d) {

    var selectedPath = svg.select("path." + d.key);
    //var totalLength = selectedPath.node().getTotalLength();

    if (d.visible === 1) {
        d.visible = 0;
    } else {
        d.visible = 1;
    }

    rescaleY();
    updateLines();
    updateCircles();

    svg.select("rect." + d.key).transition().duration(500)
        .attr("fill", function(d) {
            if (d.visible === 1) {
                return color(d.key);
            } else {
                return "white";
            }
        })

    svg.select("path." + d.key).transition().duration(500)
        .delay(150)
        .style("display", function(d) {
            if(d.visible === 1) {
                return "inline";
            }
            else return "none";
        })
        .attr("d", function(d) {
            return line(d.values);
        });

    svg.selectAll("circle." + d.key).transition().duration(500)
        //.delay(function(d, i) { return i * 10; })
        .style("display", function(a) {
            if(d.visible === 1) {
                return "inline";
            }
            else return "none";
        });


})
.on("mouseover", function(d) {
    d3.select(this)
        .attr("height", 12)
        .attr("width", 27)

    d3.select("path." + d.key).transition().duration(200)
        .style("stroke-width", "4px");

    d3.selectAll("circle." + d.key).transition().duration(200)
        .attr("r", function(d, i) { return 4 })

    // Fade out the other lines
    var otherlines = $(".line").not("path." + d.key);
    d3.selectAll(otherlines).transition().duration(200)
        .style("opacity", 0.3)
        .style("stroke-width", 1.5)
        .style("stroke", "gray");

    var othercircles = $("circle").not("circle." + d.key);
    d3.selectAll(othercircles).transition().duration(200)
       .style("opacity", 0.3)
       .style("stroke", "gray");
})
.on("mouseout", function(d) {
    d3.select(this)
        .attr("height", 10)
        .attr("width", 25)

    d3.select("path." + d.key).transition().duration(200)
        .style("stroke-width", "1.5px");

    d3.selectAll("circle." + d.key).transition().duration(200)
        .attr("r", function(d, i) { return 2 })

    // Make the other lines normal again
    var otherlines = $('.line').not("path." + d.key);
    d3.selectAll(otherlines).transition().duration(100)
        .style("opacity", 1)
        .style("stroke-width", 1.5)
        .style("stroke", function(d) { return color(d.key); });

    var othercircles = $("circle").not("circle." + d.key);
    d3.selectAll(othercircles).transition().duration(200)
        .style("opacity", 1)
        .style("stroke", function(d) { return color(dimKey(d)); });
});

提前致谢。

2 个答案:

答案 0 :(得分:1)

当你有多个转换时,可以中断另一个转换。您的代码发生的事情是onclick转换被mouseout转换中断。这导致线条不显示出现。要解决此问题,只需在mouseout事件中添加延迟,以便在onclick事件完成后发生。例如,我做了以下更改:

在第295行添加了延迟:   1 + 2

并且在第244行将您的onclick延迟从500减少到200,仅用于此测试, d3.select("path." + d.key).transition().delay(300).duration(200) .style("stroke-width", "1.5px");

答案 1 :(得分:1)

您可以在图例单击(.clicked)时为其指定一个类,然后在转换完成后以适当的延迟调用setTimeout以删除该类。

当鼠标悬停或鼠标移开时,首先检查图例是否具有.clicked类。如果是这样,请按照另一个答案中的建议设置一些延迟值,否则,不要拖延。与其他答案相比,这样做的好处是,如果需要,只会有延迟。

修改

如果您的图例有类" .legend",请修改您的代码,如下所示:

.on("click", function(d) {

    // Add .clicked class to the legend
    $('.legend').addClass('clicked');

    // remove clicked class after 750ms. Your duration is 500ms,
    // so I'm padding it a bit although you can adjust this as needed
    setTimeout(function () { $('.legend').removeClass('clicked') }, 750);

    ... rest of your function
})
.on("mouseover", function(d) {

    // check if legend has been clicked recently and change delay if so
    var transitionDelay = 0;
    if($('.legend').hasClass('clicked')) transitionDelay = 750;

    // your function

    d3.select(this)
        .attr("height", 12)
        .attr("width", 27)

    d3.select("path." + d.key).transition().delay(transitionDelay).duration(200)
        .style("stroke-width", "1.5px");

    ... rest of your function
});