title: Using D3, how can I update circles on a map after panning?
body: <p>I am making a map using D3. I've added both points and circles to the map. When I pan the globe (it's a stereographic map) the points are updated to the new location, but the circles do change. How can I update the points in a similar way to the circles? </p>
  
  <p>I add points and circles using the following approach:</p>
  
  <pre><code>// 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); 
  </code></pre>
  
  <p>Then when the map is panned, I call a function called <code>refresh</code> to update these objects:</p>
  
  <pre><code>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));  
  
      }
  </code></pre>
  
  <p>A working example is shown here (the <code>world-110m.json</code> needs to be linked to for this to work). Should I be adding the circles in a different way such that they can be redrawn?</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;meta charset="utf-8"&gt;
  
  &lt;style&gt;
  .land {
  
    fill: rgb(117, 87, 57);
    stroke-opacity: 1;
    stroke: #fff;
    stroke-width: 0.75;
  }
  
  &lt;/style&gt;
  &lt;head&gt;
  
    &lt;!-- libraries --&gt;
    &lt;script src="http://d3js.org/d3.v3.min.js"&gt;&lt;/script&gt;
    &lt;script src="http://d3js.org/queue.v1.min.js"&gt;&lt;/script&gt;
    &lt;script src="http://d3js.org/topojson.v0.min.js"&gt;&lt;/script&gt;
  
  &lt;/head&gt;
  
  &lt;body&gt;
    &lt;div class="map"&gt;&lt;/div&gt;
  &lt;/body&gt;
  
  &lt;script&gt;
  
  // 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] &gt; 30  ? 30  :
              o1[1] &lt; -30 ? -30 :
              o1[1];
      proj.rotate(o1);
      sky.rotate(o1);
      refresh();
    }
  }
  
  function mouseup() {
    if (m0) {
      mousemove();
      m0 = null;
    }
  }
  &lt;/script&gt;
  &lt;/html&gt;
  </code></pre>