D3.Geo performance on Pan/Zoom

时光怂恿深爱的人放手 提交于 2019-12-04 14:26:36
Adam Pearce

(I'm not super sure what's going on under the hood here, this might be totally wrong).

mapa.selectAll("path").attr("d", path);

Redraws the map from scratch. That works fine for 50 states but starts to get pretty slow with 600+ shapes. You might have better luck if you left the paths in place and just transformed the entire svg:

function zoommove() {
  svg.attr("transform",
      "translate("+d3.event.translate+")"
      + " scale("+d3.event.scale+")");
}

Which I've used to create a county level map of the US (~500 shapes) that zooms and pans smoothly.

Answering my own question here, If you find this helpful, please upvote Adam's answer instead, he deserves the credit.

What worked for me:

var bg = svg.append('g')
    .call(zoom);

var map = bg.append("g")
    .attr("transform", "translate(0,0) scale(1)");

...

function zoommove() {
    var t1 = projection.translate(),
        t2 = d3.event.translate,
        t = [t2[0]-t1[0], t2[1]-t1[1]];

    map.attr("transform", 
        "translate("+t+") " +
        "scale("+(d3.event.scale/s)+")"
    );
    console.log(map.attr("transform"));
}

Some tips:

  • if projection.translate() is not [0, 0], you have to take it in account, otherwise a big bump will occur on the first time you try to pan/zoom (only the first time).
  • if projection.scale() is not 1, you have to take it in account.
  • the .call(zoom) must be in the maps parent element, otherwise panning/zooming becomes bumpy.

I've come across similar issues, and a rescaling was not suitable for my solution as i did not want the svg elements themselves to be scaled. What I did instead was optimize it such that elements out of the visible area were not recalculated. This means that when all the elements are in the view performance is still bad, but when you zoom in it's much better.

ode sample:

clippedArea.selectAll("circle")
    .style("visibility", d => pointInDomain(d, domain) ? "visible" : "hidden")
    .filter(d => pointInDomain(d, domain))
  .attr("cx", d => xz(d.x));

JSFiddle

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