Javascript 许多SVG路径的简单点击处理在Firefox中运行良好,但在Chrome中却不行?

Javascript 许多SVG路径的简单点击处理在Firefox中运行良好,但在Chrome中却不行?,javascript,d3.js,svg,dom-events,Javascript,D3.js,Svg,Dom Events,我正在制作一张交互式细粒度美国地图,d3中有大约35K个多边形。当我开始想要对单个多边形上的点击做出响应时,我遇到了这个问题。我正在使用SVG路径元素渲染多边形 问题是,我无法让Chrome以我称之为交互速率(~次秒响应时间)的方式响应SVG上的点击事件,而Firefox则可以毫无问题地处理该场景。希望我遗漏了一些巫毒,或者我忽略了一些简单的东西? 我将下面的问题简化为纯JavaScript,只包含基本内容。我使用SVG路径元素(模拟我的地图)生成一组方形单元格,然后附加单击处理程序。尝试不同

我正在制作一张交互式细粒度美国地图,d3中有大约35K个多边形。当我开始想要对单个多边形上的点击做出响应时,我遇到了这个问题。我正在使用SVG路径元素渲染多边形

问题是,我无法让Chrome以我称之为交互速率(~次秒响应时间)的方式响应SVG上的点击事件,而Firefox则可以毫无问题地处理该场景。希望我遗漏了一些巫毒,或者我忽略了一些简单的东西?

我将下面的问题简化为纯JavaScript,只包含基本内容。我使用SVG路径元素(模拟我的地图)生成一组方形单元格,然后附加单击处理程序。尝试不同版本的numberOfPathCellsPerSide,然后用鼠标单击SVG地图,查看Chrome与Firefox中即时性能的对比

///////////////////////////////////////////////////////////////////////////////////////////
//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...");
}