2013-09-23 86 views
2

我正在使用D3製作地圖。我在地圖上添加了點和圓圈。當我平移地球儀(這是一張立體地圖)時,點將更新到新位置,但圓圈確實會改變。我怎樣才能以類似的方式更新點數?使用D3,如何在平移後更新地圖上的圓圈?

我添加使用下面的方法點和圓:

// POINTS 
svg.append("g").attr("class","points") 
    .selectAll("text").data(places.features) 
    .enter().append("path") 
    .attr("class", "point")  
    .style("pointRadius", 2) 
    .style("fill", "red"); 

// CIRCLES 
svg.append("g").attr("class","circles") 
    .selectAll("path").data(places.features)  
    .enter().append("circle")   
    .attr('cx', function(d) { return proj(d.geometry.coordinates)[0]}) 
    .attr('cy', function(d) { return proj(d.geometry.coordinates)[1]})  
    .attr("r", 4) 
    .style('fill', 'green') 
    .attr("d", path); 

然後,當在地圖上搖擺,我稱之爲叫refresh函數來更新這些對象:

function refresh() { 

     // redraw land 
     svg.selectAll(".land").attr("d", path); 

     // redraw circles 
     svg.selectAll(".point").attr("d", path.projection(proj)); 

     // redraw circles 
     svg.selectAll(".circles").attr("d", path.projection(proj)); 

    } 

一個工作的例子是如下所示(需要連接world-110m.json才能正常工作)。我應該以不同的方式添加圈子,以便重繪它們嗎?

<!DOCTYPE html> 
<meta charset="utf-8"> 

<style> 
.land { 

    fill: rgb(117, 87, 57); 
    stroke-opacity: 1; 
    stroke: #fff; 
    stroke-width: 0.75; 
} 

</style> 
<head> 

    <!-- libraries --> 
    <script src="http://d3js.org/d3.v3.min.js"></script> 
    <script src="http://d3js.org/queue.v1.min.js"></script> 
    <script src="http://d3js.org/topojson.v0.min.js"></script> 

</head> 

<body> 
    <div class="map"></div> 
</body> 

<script> 

// Lots of code from: 
// http://bl.ocks.org/3757125 
// http://bl.ocks.org/3795040 

// data 
var places = {"type": "FeatureCollection","features": [ 
{ "type": "Feature", "properties": { "id": 34, "status": 1}, "geometry": { "type": "Point", "coordinates": [ 55.321249, 24.104000 ] }}, 
{ "type": "Feature", "properties": { "id": 34, "status": 1}, "geometry": { "type": "Point", "coordinates": [ 55.321249, 24.104000 ] }}, 
{ "type": "Feature", "properties": { "id": 272, "status": 1}, "geometry": { "type": "Point", "coordinates": [ 54.002962, 23.455742 ] }}, 
{ "type": "Feature", "properties": { "id": 272, "status": 1}, "geometry": { "type": "Point", "coordinates": [ 54.002962, 23.455742 ] }}, 
{ "type": "Feature", "properties": { "id": 350, "status": 1}, "geometry": { "type": "Point", "coordinates": [ 136.321249,-24.496000 ] }}, 
{ "type": "Feature", "properties": { "id": 427, "status": 0}, "geometry": { "type": "Point", "coordinates": [ 136.321249,-26.296000 ] }}, 
{ "type": "Feature", "properties": { "id": 427, "status": 0}, "geometry": { "type": "Point", "coordinates": [ 136.321249,-26.296000 ] }}, 
{ "type": "Feature", "properties": { "id": 96, "status": 0}, "geometry": { "type": "Point", "coordinates": [ 138.259022,-24.491771 ] }}]}; 


var width = 700, 
    height = 700; 

var proj = d3.geo.orthographic() 
    .translate([width/2, height/2]) 
    .clipAngle(90) 
    .scale(310); 

var sky = d3.geo.orthographic() 
    .translate([width/2, height/2]) 
    .clipAngle(90) 
    .scale(360); 

var path = d3.geo.path().projection(proj); 

d3.select(window) 
    .on("mousemove", mousemove) 
    .on("mouseup", mouseup); 


var svg = d3.select("body").select('.map').append("svg") 
      .attr("width", width) 
      .attr("height", height) 
      .on("mousedown", mousedown) 

queue() 
    .defer(d3.json, "data/world-110m.json") 
    .await(ready); 

var div = d3.select("body").append("div") 
    .attr("class", "tooltip")  
    .style("opacity", 0); 

function ready(error, world) { 
    var globe_highlight = svg.append("defs").append("radialGradient") 
     .attr("id", "globe_highlight") 
     .attr("cx", "75%") 
     .attr("cy", "25%"); 
     globe_highlight.append("stop") 
     .attr("offset", "5%").attr("stop-color", "#ffd") 
     .attr("stop-opacity","0.6"); 
     globe_highlight.append("stop") 
     .attr("offset", "100%").attr("stop-color", "#ba9") 
     .attr("stop-opacity","0.2"); 

    svg.append("circle") 
    .attr("cx", width/2).attr("cy", height/2) 
    .attr("r", proj.scale()) 
    .attr("class", "noclicks") 
    .style("fill", "url(#ocean_fill)"); 

    svg.append("path") 
    .datum(topojson.object(world, world.objects.land)) 
    .attr("class", "land noclicks") 
    .attr("d", path); 

    // POINTS 
    svg.append("g").attr("class","points") 
     .selectAll("text").data(places.features) 
     .enter().append("path") 
     .attr("class", "point")  
     .style("pointRadius", 2) 
     .style("fill", "red"); 

    // CIRCLES 
    svg.append("g").attr("class","circles") 
     .selectAll("path").data(places.features)  
     .enter().append("circle")   
     .attr('cx', function(d) { return proj(d.geometry.coordinates)[0]}) 
     .attr('cy', function(d) { return proj(d.geometry.coordinates)[1]})  
     .attr("r", 4) 
     .style('fill', 'green') 
     .attr("d", path); 

    refresh(); 
} 


function refresh() { 

    // redraw land 
    svg.selectAll(".land").attr("d", path); 

    // redraw circles 
    svg.selectAll(".point").attr("d", path.projection(proj)); 

    // redraw circles 
    svg.selectAll(".circles").attr("d", path.projection(proj)); 

} 


// modified from http://bl.ocks.org/1392560 
var m0, o0; 
function mousedown() { 
    m0 = [d3.event.pageX, d3.event.pageY]; 
    o0 = proj.rotate(); 
    d3.event.preventDefault(); 
} 

function mousemove() { 
    if (m0) { 
    var m1 = [d3.event.pageX, d3.event.pageY] 
     , o1 = [o0[0] + (m1[0] - m0[0])/6, o0[1] + (m0[1] - m1[1])/6]; 
    o1[1] = o1[1] > 30 ? 30 : 
      o1[1] < -30 ? -30 : 
      o1[1]; 
    proj.rotate(o1); 
    sky.rotate(o1); 
    refresh(); 
    } 
} 

function mouseup() { 
    if (m0) { 
    mousemove(); 
    m0 = null; 
    } 
} 
</script> 
</html> 

回答

2

circle元素沒有一個d屬性,只有path元素做。所以你可能想追加一個path而不是circle

此外,您正在將您的班級分配給家長g元素,因此您在refresh中的選擇實際上是指g的不是自己的形狀。您應該將這些類放在形狀上,或者將您的選擇更改爲如下形式:

svg.selectAll(".point") 
    .selectAll("path") 
     .attr("d", path.projection(proj)); 
+0

這是正確的,我是。我只是更新了我的'refresh()'函數,但沒有解決問題。 – djq

+1

更新了答案以反映您的更改。 –