d3 got slow all of a sudden

本小妞迷上赌 提交于 2019-12-11 00:47:32

问题


Unfortunately, by 'all of a sudden', I mean between versions 3.1.1.10 and 3.2.0. I have a scatterplot with about 3000 points in it, and we are trying to make a mouse click based tooltip work since tooltips based on mouseover events don't really work for us.

So, while testing our initial attempt, we saw that it took a full 2 or 3 seconds before anything happened. I thought that was a little odd. I mean sure, we're doing a nearest-neighbor calculation, but it's only 3000 points, so what gives? I profiled it and found that once we got the event trigger, our calculations were only taking about 22 msec, so that's good. So what is causing d3 to take so much time in getting us active on mouse clicks? I started dropping in different versions of d3 to see if it was the culprit and sure enough, things were slow until I got back to version 3.1.0. That one have us the mouse event pretty much immediately and our tooltip popups were now working well.

Only problem is I can't use 3.1.10 because I need the zoom().center() functionality that was added more recently.

So any ideas? Anybody know why the slowdown occurred there? Can it be patched? Can someone suggest a clever workaround? I can't be the only one who has seen this problem. I brought it up in the d3 forum, topic number qfz11UYgMC8

I understand why I cannot post codepen demos here without code, but the 2 demos I have demonstrate my point above by differing only in what version of d3 is included in them. I will include the code here if people really want to see it, but it's pretty much standard d3.js where I create my scatterplot from a json object, and it's thousands of lines of code.

And the problem is definitely based on the size of the scatterplot. A small plot of a dozen or so points pops up the tooltip right away, and the one with 3000 points is slow (on all d3.js libraries 3.2 and later).

Edit: adding code snippets, and codepen links The code itself is thousands of lines long because the data itself gets embedded in the html. Here is what I hope is the relevant code...

<html>
<head>
    <title>Rolling D3 speed test</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.2.0/d3.min.js"></script>
    <!-- <script src="file://C:/d3.v3.5.16.min.js"></script> -->
    <script type="text/javascript" charset="utf8" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script type="text/javascript" language="javascript" class="init">

// variable init left out for brevity
...
var svg = d3.select("body").append("svg")
            .attr("width",viewportWidth)
            .attr("height",viewportHeight)
            .call(zoom)
            .append("g")
    .attr("class", "main")
            .attr("transform","translate("+(left_shift)+","+(top_shift)+")");
...
//mouse click on svg (to display tooltip on nearest point)
d3.select('svg').on("click",  function() {
  var startTime = new Date();
  var coords = [0, 0];
  coords = d3.mouse(this);
  var isClicked = isPointClicked(point_clicked);
  if(!isClicked) clicked(coords[0], coords[1]);
  point_clicked = false;

  var finalEndTime = new Date();
  var finalTimeDiff = finalEndTime - startTime;
  console.log('all click actions completed in '+finalTimeDiff+' milliseconds.');
});
 //mouse-right click event to remove tooltip
  d3.select('body').on("contextmenu", function() {
  d3.event.preventDefault();
  var ele = d3.select('div.tooltip');
  //if(ele!=="undefined" && ele!==null)
ele.style("opacity",0);
});

...
// x and y axis rendering removed for brevity
...

//draw all data
//var radius = 2.5; // 2.5 normally, 8 is good for testing small sets
var side = 2;     // takes place of radius
// shiftrect needs to be half the square size to center square on data point
var shiftrect = 1;
for(var k=0;k<plot_data.series.length;++k) {
    if(plot_data.series[k].visible === true) {
        var y_list = plot_data.series[k].ydata;
        var x_list = plot_data.series[k].xdata;
        svg.selectAll("dot")
           .data(x_list)
           .enter().append("rect")
       .attr("id", function(d, i) { return "rect"+k+i;})
           .attr("x", function(d) {return x(parseFloat(d))-shiftrect;})
           .attr("y", function(d,i) {return y(parseFloat(y_list[i]))-shiftrect;})
           .attr("height", side)
           .attr("width", side)
           .attr("fill",function() { return color(k);})
           .attr("clip-path", "url(#plot-clip)");
    }
}

Codepen that is slow http://codepen.io/pkrouse/details/ONwQmz/

Codepen that is fast. Only diff is version of D3 used http://codepen.io/pkrouse/details/JXBpKo/

来源:https://stackoverflow.com/questions/36946523/d3-got-slow-all-of-a-sudden

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!