Javascript 许多SVG路径的简单点击处理在Firefox中运行良好,但在Chrome中却不行?
我正在制作一张交互式细粒度美国地图,d3中有大约35K个多边形。当我开始想要对单个多边形上的点击做出响应时,我遇到了这个问题。我正在使用SVG路径元素渲染多边形 问题是,我无法让Chrome以我称之为交互速率(~次秒响应时间)的方式响应SVG上的点击事件,而Firefox则可以毫无问题地处理该场景。希望我遗漏了一些巫毒,或者我忽略了一些简单的东西? 我将下面的问题简化为纯JavaScript,只包含基本内容。我使用SVG路径元素(模拟我的地图)生成一组方形单元格,然后附加单击处理程序。尝试不同版本的numberOfPathCellsPerSide,然后用鼠标单击SVG地图,查看Chrome与Firefox中即时性能的对比Javascript 许多SVG路径的简单点击处理在Firefox中运行良好,但在Chrome中却不行?,javascript,d3.js,svg,dom-events,Javascript,D3.js,Svg,Dom Events,我正在制作一张交互式细粒度美国地图,d3中有大约35K个多边形。当我开始想要对单个多边形上的点击做出响应时,我遇到了这个问题。我正在使用SVG路径元素渲染多边形 问题是,我无法让Chrome以我称之为交互速率(~次秒响应时间)的方式响应SVG上的点击事件,而Firefox则可以毫无问题地处理该场景。希望我遗漏了一些巫毒,或者我忽略了一些简单的东西? 我将下面的问题简化为纯JavaScript,只包含基本内容。我使用SVG路径元素(模拟我的地图)生成一组方形单元格,然后附加单击处理程序。尝试不同
///////////////////////////////////////////////////////////////////////////////////////////
//numberOfPathCellsPerSide*numberOfPathCellsPerSide=SVG路径“多边形”的总数。
//单击处理程序响应时间似乎与路径的总数有关,而不是与
//每个路径的大小。此外,正如您将在下面看到的,有几种不同的变体
//尝试侦听的单击事件无效。
//尝试依次取消注释以体验性能变化
//在Chrome和Firefox之间:
///////////////////////////////////////////////////////////////////////////////////////////
var numberOfPathCellsPerSide=100;//100 x 100=10000个总路径=>~instant在Chrome中,~instant在Firefox中
//var numberOfPathCellsPerSide=200;//200 x 200=40000总路径=>~7秒在Chrome中,即时在Firefox中
//var numberOfPathCellsPerSide=300;//300 x 300=90000条总路径=>在Chrome中约48秒,在Firefox中约瞬间
var lengthOfPathCell=5;
var xmlns=”http://www.w3.org/2000/svg";
var description=document.createElement(“div”);
description.innerHTML=
svg路径总数:“+numberOfPathCellsPerSide*numberOfPathCellsPerSide+”
”;
文件.正文.附件(说明);
var lengthOfSVGContainer=路径单元的数量rside*lengthOfPathCell;
var svg=document.createElements(xmlns,“svg”);
document.body.appendChild(svg);
svg.setAttributeNS(null,“宽度”,lengthOfSVGContainer);
setAttributeNS(null,“高度”,lengthOfSVGContainer);
var g=document.createElements(xmlns,“g”);
svg.appendChild(g);
对于(var i=0;iI不知道问题是什么,但分析一次单击显示99.99%的时间花在“(程序)”上这表明这可能是Chrome本身的问题,与JavaScript无关。是的,我怀疑Chrome已经实施了某种蛮力命中测试来确定点击的目标,也许Firefox使用了更智能的东西,比如R-tree。更新:从51.0.2704.103 m版开始,Chrome似乎已经修复了
///////////////////////////////////////////////////////////////////////////////////////////
// numberOfPathCellsPerSide * numberOfPathCellsPerSide = total number of SVG path "polygons".
// Click handler response time seems to be tied to total number of paths rather than the
// size of each path. Also, as you will see down below, several different variations
// of click event listening were tried to no avail.
// Try uncommenting each in succession to experience the performance variations
// between Chrome and Firefox:
///////////////////////////////////////////////////////////////////////////////////////////
var numberOfPathCellsPerSide = 100; // 100 x 100 = 10,000 total paths => ~instant in Chrome, ~instant in Firefox
//var numberOfPathCellsPerSide = 200; // 200 x 200 = 40,000 total paths => ~7 sec in Chrome, ~instant in Firefox
//var numberOfPathCellsPerSide = 300; // 300 x 300 = 90,000 total paths => ~48 sec in Chrome, ~instant in Firefox
var lengthOfPathCell = 5;
var xmlns = "http://www.w3.org/2000/svg";
var description = document.createElement("div");
description.innerHTML =
"Total number of svg paths: " + numberOfPathCellsPerSide * numberOfPathCellsPerSide + "<br><br>";
document.body.appendChild(description);
var lengthOfSVGContainer = numberOfPathCellsPerSide * lengthOfPathCell;
var svg = document.createElementNS (xmlns, "svg");
document.body.appendChild(svg);
svg.setAttributeNS (null, "width", lengthOfSVGContainer);
svg.setAttributeNS(null, "height", lengthOfSVGContainer);
var g = document.createElementNS(xmlns, "g");
svg.appendChild(g);
for(var i=0; i<(numberOfPathCellsPerSide * numberOfPathCellsPerSide); i++)
{
var path = document.createElementNS (xmlns, "path");
var x = (i % numberOfPathCellsPerSide) * lengthOfPathCell
var y = Math.floor(i / numberOfPathCellsPerSide) * lengthOfPathCell;
var drawCellCommands =
"M " + x + " " + y + " " +
"L " + (x + lengthOfPathCell) + " " + y + " " +
"L " + (x + lengthOfPathCell) + " " + (y + lengthOfPathCell) + " " +
"L " + x + " " + (y + lengthOfPathCell) + " " +
"L " + x + " " + y + " ";
path.setAttributeNS(null, "d", drawCellCommands);
path.style.fill = "hsl(" + Math.random() * 360 + ",100%,50%)";
///////////////////////////////////////////////////////////////////////////////////////////
// Several different variants of listening for click events.
// Leave one of them uncommented to see it doesn't seem to matter!
///////////////////////////////////////////////////////////////////////////////////////////
// listener attempt 1: create an anonymous handler function for each path cell
path.addEventListener("click", function(e)
{
console.log("finally handled the click...");
alert("finally handled the click...");
});
// listener attempt 2: use the same named handler function for each path cell
//path.addEventListener("click", namedClickHandler);
g.appendChild(path);
}
// listener attempt 3: leverage delegation by using a single named handler once on enclosing SVG parent element
// Should be the most responsive yet still seems to make no difference in Chrome
//svg.addEventListener("click", namedClickHandler);
function namedClickHandler(e)
{
console.log("finally handled the click...");
alert("finally handled the click...");
}