2013-06-13 5 views
3

작년에 Mapnik library (서버 측, 비트 맵/타일링)을 사용하여 웹 맵에서 몇 가지 실험을했습니다. 이제 d3.js를 사용한 클라이언트 측 접근 방식 인 벡터를 사용하여 동일한 실험을 반복하려고합니다.팬/줌의 D3.Geo 성능

zoom이 느리고 pan이 부진한지도 (~ 680 도형)가 있습니다 (this example by Mike Bostock). 문제가 zoommove 콜백에있는 것으로 의심됩니다. selectAll("path").attr("d", path)은 시간이 오래 걸립니다.

function zoommove() { 
    projection.translate(d3.event.translate).scale(d3.event.scale); 
    mapa.selectAll("path").attr("d", path); 
    console.log('zoommove fired...'); 
} 

질문 :

  1. 는 여기 뭔가 잘못하고 있습니까

    ?
  2. 성능을 최적화하려면 어떻게해야합니까?

지도이 (jsfiddle here)입니다 :

Municipalities from São Paulo State, Brazil

데이터 소스는 topojson 형식입니다. 어떤 모양이 폐쇄되지 않기 때문에 그것은 간단하고, 이미 너무 많은 수 있습니다 : 단순화 플래그없이 topojson을 실행할 때

enter image description here

[업데이트]

가 열려 형상의 문제 같은데

도 발생, 나는 아직도 조사 중이 야. 나는 여기에 어떤 단서를 주셔서 감사하겠습니다, 문서는 매우 자세하지 않습니다.

답변

11

(나는 두포 밑에서 무슨 일이 일어나고 있는지 잘 모르겠다. 이것은 완전히 틀릴 수도있다.)

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

지도를 처음부터 다시 그립니다. 50 개 주에서는 잘 작동하지만 600+ 모양으로는 꽤 느려지 기 시작합니다.

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

내가 부드럽게 확대와 팬 미국 (~ 500 개 형상)의 county level map 만드는 데 사용했습니다 당신이 장소에 경로를 떠나 단지 전체 SVG를 전환하는 경우 당신은 더 나은 운이있을 수 있습니다.

+0

당신이 바로 그 트랙에 저를 얻었다. 이동중인 동일한 요소에 대해 변환이 계산되기 때문에 팬은 약간 울퉁불퉁합니다. 그러나 문제를 해결할 수는 있습니다. ('d3.event.translate'는 배열입니다.) 당신의 대답을 약간 편집 했으니 까, 괜찮 으면 좋겠다. –

+0

더 짧은 "translate ("+ d3.event.translate + ")"는 자바 스크립트가 배열과 문자열의 추가를 처리하기 때문에 작동하지만 길이가 너무 짧거나 불분명 할 수 있습니다. 행운을 빕니다! –

+0

당신 말이 맞아요. 수정 된 내용을 취소하고 다른 답변에서 나를 위해 잘 된 것을 게시하십시오. 고맙습니다! 매우 도움이됩니다. –

2

여기 내 자신의 질문에 대답하면, 도움이된다면, 대신에 아담의 답변을 upvote, 그는 신용을받을 자격이.

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

몇 가지 팁 : 나를 위해 일한 무엇

  • projection.translate()가없는 경우는 [0, 0], 그렇지 않으면 큰 범프가 발생, 계정에 걸릴해야 처음으로 팬/확대/축소를 시도 할 때 (처음에만).
  • projection.scale()이 1이 아닌 경우이를 고려해야합니다.
  • .call(zoom)은지도 요소에 있어야하며, 그렇지 않으면 패닝/확대/축소가 울퉁불퉁합니다.
0

나는 svg 요소 자체가 크기 조정되기를 원하지 않기 때문에 rescaling이 내 솔루션에 적합하지 않았습니다. 내가 대신 한 것은 눈에 보이는 영역의 요소가 다시 계산되지 않도록 최적화하는 작업이었습니다. 즉, 모든 요소가 뷰 성능에있을 때 여전히 성능이 좋지 않지만 확대 할 때 훨씬 더 좋습니다.

송시 샘플 :

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

JSFiddle