有没有办法减少鼠标指针后面的指南滞后?

时间:2012-10-10 20:42:07

标签: svg d3.js

我的svg上有一个垂直指针跟在鼠标指针之后,但是现在它更新它的位置很慢,这对于快速鼠标移动尤其明显。有没有办法减少这种滞后?

当前代码:

svg.on("mousemove", function(d) {
    svg.select(".guideline")
        .attr("x1", d3.mouse(this)[0]-1)
        .attr("x2", d3.mouse(this)[0]-1);

});

svg.on("mouseover", function(d) {
    svg.append("line")
        .attr("class", "guideline")
        .attr("y1", margin[0])
        .attr("y2", height+margin[0])
        .attr("opacity", originOpacity)
        .attr("stroke", "#333")
        .attr("pointer-events", "none");

});

svg.on("mouseout", function(d) {
    svg.select(".guideline").remove();
});

4 个答案:

答案 0 :(得分:3)

我遇到了同样的问题,但我发现了两件事:

  1. 如果你看一下High Charts,他们已经(在他们的JS库中)实现了一个类似的垂直指南,它并没有落后太多。所以有可能做到这一点。例如,请参阅:here

  2. 我使用了一个容器元素,我在其中添加了一个SVG元素,我在其中添加了一个带有坐标转换/转换的group(g)元素,如下所示:

  3. HTML:

    <div id="d3-container"></div>
    

    JS:

    var svg = d3.select("#d3-container")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .attr("id","d3-svg")
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .attr("id","d3-canvas");
    

    有趣的是,当我将鼠标事件(使用第一个答案中的上述代码)绑定到各种元素时,我会得到非常不同的性能:当我将它绑定到“d3-canvas”组时,我的引导线是非常慢并且滞后,当我将它绑定到它的父svg元素(“d3-svg”)时它已经更快了,如果我将它绑定到div(“d3-container”),我获得最快的性能(尽管它仍然没有高股票那么快。所以我认为坐标转换会给鼠标事件增加很多开销,但不管怎样,D3或SVG也没有针对鼠标事件进行优化。

答案 1 :(得分:2)

您正在选择每个鼠标移动的线条,而是将该线条保留在变量中:

var line = svg.append("line")
        .attr("class", "guideline")
        .attr("y1", margin[0])
        .attr("y2", height+margin[0])
        .attr("opacity", 0)
        .attr("stroke", "#333")
        .attr("pointer-events", "none");

svg.on("mousemove", function(d) {

    line
        .attr("x1", d3.event.pageX-1)
        .attr("x2", d3.event.pageY-1);

});

svg.on("mouseover", function(d) {
  line.attr("opacity", originOpacity);
});

svg.on("mouseout", function(d) {
    line.attr("opacity", 0);
});

答案 2 :(得分:2)

您可以添加几毫秒的延迟,而不是更新每个mousemove上的属性:

var lastMove, elapsed;
svg.on("mousemove", function(d) {

    elapsed = Date.now() - lastMove;
    if ( elapsed < 40 ) return;

    svg.select(".guideline")
        .attr("x1", d3.mouse(this)[0]-1)
        .attr("x2", d3.mouse(this)[0]-1);

    lastMove = Date.now();
});

这肯定会提高性能,但代价是让动作更加不稳定。玩你检查的毫秒数。 40可能太长了。

答案 3 :(得分:1)

有一个名为shape-rendering的CSS属性,用于设置应如何呈现SVG的优先级。您可以指定autooptimizeSpeedcrispEdgesgeometricPrecision,其中auto会尝试在不牺牲精度的情况下适应速度和清晰度。

我发现设置shape-renderingauto会提高我的十字准线的性能。 crispEdges和optimizeSpeed似乎让光标间歇性地消失。我无法在小提琴中重现光滑的十字准线,但在我的解决方案中,它现在实际上非常平滑。