是否可以消除渲染 d3 鼠标位置的延迟?

sha*_*roz 5 svg d3.js

我有一些代码在光标位置上方显示一个 SVG 项目。我注意到如果对象只是落后一帧,那么它比我预期的要落后于光标。

var width = 600,
    height = 200;
var mouseLocation = [0,0];

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var cursor = svg.append('circle')
    .attr("r", 2)
    .attr("fill", 'darkblue');

// update mouse location
d3.select(window).on("mousemove", () => { 
  mouseLocation = d3.mouse(svg.node()); 
});

// show mouse
d3.timer(function() {
  cursor.attr("transform", 'translate(' + mouseLocation + ')');
});
Run Code Online (Sandbox Code Playgroud)
<script src="http://d3js.org/d3.v4.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

您可以通过将鼠标从一侧平滑地滑动到另一侧来查看延迟。蓝色圆圈稍微落后于光标。(至少在 Windows 上的 Chrome 57 上)

我尝试了几种变体,包括在 mousemove 回调函数中调用 circle.attr 。但总有一点延迟。

编辑我尝试失败的事情:

  • mousemove事件中设置光标变换
  • 检查自上次mousemove调用以来经过的时间,仅每 16 毫秒更新一次。
  • svg.style("shape-rendering", "optimizeSpeed");
  • mousemove事件用于 svg 而不是窗口
  • 使用d3.event.pageXandd3.event.pageY而不是d3.mouse(svg.node())
  • 我使用演示遇到了同样的问题<canvas>

Ger*_*ado 0

在这个答案的第一个版本中(查看编辑历史记录)我尝试了d3.intervalsetInterval,没有区别。

然而,我相信,也许这个问题没有答案(从OP想要的意义上来说),因为延迟取决于D3处理事件mousemove。这里的问题也可能与 D3 无关,而是取决于用户代理(浏览器)如何控制事件mousemove频率。

如果我们将移动圆的代码放在该mousemove函数中,就可以看出这一点:

d3.select(window).on("mousemove", () => { 
    mouseLocation = d3.mouse(svg.node()); 
    cursor.attr("transform", 'translate(' + mouseLocation + ')');
});
Run Code Online (Sandbox Code Playgroud)

并且滞后仍然是相同的:

d3.select(window).on("mousemove", () => { 
    mouseLocation = d3.mouse(svg.node()); 
    cursor.attr("transform", 'translate(' + mouseLocation + ')');
});
Run Code Online (Sandbox Code Playgroud)
var width = 600,
    height = 200;
var mouseLocation = [0,0];

var svg = d3.select("div").append("svg")
    .attr("width", width)
    .attr("height", height);

var cursor = svg.append('circle')
    .attr("r", 2)
    .attr("fill", 'darkblue');

// update mouse location
d3.select("div").on("mousemove", () => { 
  cursor.attr("transform", 'translate(' + (d3.event.pageX - 16) + "," + (d3.event.pageY - 16) + ')');
});
Run Code Online (Sandbox Code Playgroud)