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

时间:2015-11-09 06:35:14

标签: javascript d3.js svg javascript-events

我正在使用交互式细粒度美国地图,在d3中有大约35K多边形。一旦我开始想要回应单个多边形的点击,我就遇到了这个问题。我使用SVG路径元素来渲染多边形。

问题是我无法让Chrome响应SVG上的点击事件,我称之为交互式费率(〜亚秒级响应时间),而Firefox处理方案没有问题。希望有一些伏都教我不知道或者可能是我忽略了一些简单的东西?

enter image description here

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

Working JS Fiddle

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

0 个答案:

没有答案