block by mpmckenna8 12bfcf6cd85b7f205475

zooming with d3 geo

Full Screen

So In my previous examples I was trying to zoom using a handy little script made by Jason Davies. But I don’t think I was using it correctly and things were a little jenky so I tried to look for some other examples. Of course right in the docs there’s a link to https://github.com/mbostock/d3/wiki/Zoom-Behavior zoom behaviors of a bunch of different kinds.

Also there’s a little animation on the location dot using css. I hope this zoom method is a little less jenky especially in mobile browsers.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<head>
  <link rel="stylesheet" href="./map.css">


</head>

<body>



      <h2 class="bigtitle">California State <span class="chatit">Assembly</span> Districts</h2>
      <div class="houseseler">
        <select class="houseslect" onchange="housech(value)">
          <option value="lower"> State Assembly </option>
          <option value="upper" selected> Senate </options>
        </select>
      </div>



    <script src="//d3js.org/d3.v3.js"></script>
    <script src="//d3js.org/topojson.v1.min.js"></script>
        <script src="./zoomed.js"></script>

        <script src="./twomap.js"></script>

    </body>

map.css

/* CSS goes here. */
.casubun {
  //  fill: #003831;
}

.bords{
  fill:none;
  stroke-width:2px;
  stroke:white;
}

.bigtitle{
  margin-right:auto;
  margin-left:auto;
  vertical-align:middle;
  text-align:center;
  color:grey;

}

.maphold{
  margin-right:auto;
  margin-left:auto;
}

.houseseler{
  margin: 0 auto;
  white-space:nowrap;
  width: 120px;


}

.houseselect{
  text-align:center;
}

.maphold{
  //position:absolute;

}

svg{
  z-index:1;
}

.distinfo{
  position:absolute;
  z-index:3;
  width:175px;
  padding:15px;
  text-align:center;
  margin-top: 10px;

}

svg path .hoved{
  stroke-width:6;
  fill:fushia;
  stroke:orange;
}

.myloc { fill: hsl(6, 63%, 46%);
  stroke:pink; }

circle.myloc {
  -webkit-animation-name: dot-glow;
  -webkit-animation-duration: 2s;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: ease-in-out;
  -webkit-animation-direction: alternate;

  animation-name: dot-glow;
  animation-duration: 6s;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
  animation-direction: alternate;

}
@-webkit-keyframes dot-glow {
  0% { fill: hsl(85, 93%, 16%); }
  50% { fill: hsl(85, 93%, 56%); }
  100% { fill: hsl(85, 93%, 56%); }
}

@keyframes dot-glow {
  0% { fill: hsl(6, 93%, 16%); }
  50% { fill: hsl(6, 93%, 56%); }
  100% { fill: green ;//hsl(6, 93%, 56%);
  }
}

.overlay {
  fill: none;
  pointer-events: all;
}

twomap.js

var width = 960,
height = 600;

var lat;
var lon;

//Choosing mercator because that's what I made the data in and also scale and center setting
var projection = d3.geo.mercator()
  .scale(2000)
  .translate([width / 2, height / 2])
  .center([-120,36]);

// So now when I call path on jam it will use this projection and stuff
var path = d3.geo.path()
  .projection(projection);

  var zoom = d3.behavior.zoom()
  .translate([0, 0])
  .scale(1)
  .scaleExtent([1, 18])
  .on("zoom", zoomed);


d3.select("body").append("h4")
  .html('Total number of Democrats: <span class="numDems">52</span> </br> Total number of Republicans: <span class="numRepu">28</span>')
  .style('color', 'white')
  .attr('class', 'bigtitle');

// Appending the actual SVG to the body of the page w/ height width
var holder = d3.select("body").append("div")
.attr("class", "maphold").style("width", width + "px").style("height", height+"px")

holder.append('div')
.attr('class','distinfo')
.style('background-color', "white")
.style('width', "200px")
.html('Click on a district to see details')



var svg = holder.append("svg")
.attr("width", width)
.attr("height", height);




svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.call(zoom);

var features = svg.append('g')//.call(zoom)

// things seem to work best if I just call zoom on svg though calling it on the
// .overlay above as well doesn't break stuff like calling zoom on the features.
svg.call(zoom)
//d3.select('.maphold')

function makemap(house){

  d3.selectAll('path')
    .remove();

  //Make the house the in title the right one
  d3.select('.chatit')
    .text(function(){
      if(house =='lower'){
        return 'Assembly'
      }
      return 'Senate'
    })

  d3.json("http://secure-sands-4200.herokuapp.com/ca" + house +".json" // "/calAss1.json"
  , function(cali) {
    console.log(cali.objects);

    // if statement to deal with different object names in topojson
  if(house ==="upper"){
    var neighbors = topojson.neighbors(cali.objects.caSenDist.geometries);
    var districts = topojson.feature(cali, cali.objects.caSenDist).features;
  }
  else{
    var neighbors = topojson.neighbors(cali.objects.assemD2011.geometries);
    var districts = topojson.feature(cali, cali.objects.assemD2011).features;
  }
    console.log(neighbors);

    features.selectAll(".casubun")
    .data(districts)
    .enter().append("path")
    .attr("class", function(d) { return "casubun"; })
    .attr("d", path)
    .style("fill",function(d,i){
      //console.log(d)
      return "green";
      });

    if(house ==="upper"){

      features.append("path")
      .datum(topojson.mesh(cali,cali.objects.caSenDist, function(a,b){
        return a;
      }))
      .attr("d",path)
      .attr("class", "bords")
    }
    else{
      features.append("path")
      .datum(topojson.mesh(cali,cali.objects.assemD2011, function(a,b){
        return a;
      }))
      .attr("d",path)
      .attr("class", "bords")
    }

//.attr();

d3.json('http://secure-sands-4200.herokuapp.com/db/?state=ca&house='+house, function(datur){
  //console.log(d)
  var dable = datur;
  var numRepubs = 0;
  var numDems = 0;


  var distos = d3.selectAll('.casubun')
  .style('fill', function(d, i){
    var tofi = 'yellow';
    var dnum = +d.properties.DISTRICT;
  //  console.log(d)
    datur.forEach(function(w, e){
      //  Matching the distcts with the console.log(w)
      if(w.district == dnum ){
        console.log('a match!');
        if(w.party === "Republican"){
          d.properties.party = "Republican";
          d.properties.name = w.full_name;
          numRepubs++;

          return  tofi = 'red'
        }
        d.properties.party = "Democrat";
        d.properties.name = w.full_name
        numDems++;

        tofi = 'blue';
      }
    })
  //  console.log(d);
    putTots();

    return tofi;
  })


  function putTots(){
    d3.select('.numDems')
    .text(numDems);

    d3.select('.numRepu')
    .text(numRepubs);


  }

  navigator.geolocation.getCurrentPosition(function(pos){
    console.log('geoloc', pos);
    lat = pos.coords.latitude;
    lon = pos.coords.longitude;
    var projcoor = projection([lon,lat]);

  features.append('circle')
    .attr('cx',function(){

      console.log(projection([lon,lat]));
      return projcoor[0]
    })
    .attr('cy',function(){
      return projcoor[1]
    })
    .attr('r','10')
    .attr('fill','green')
    .attr('class', 'myloc')

  })
  console.log(distos[0])



  d3.selectAll(".casubun").on('click', function(d){
    console.log(this);
    d3.selectAll('.casubun')
    .style('fill', makePcol)
    .attr('class', 'casubun')
    .attr('stroke','null')

    var blah = d3.select(this);
    blah
    .style('fill', 'fuchsia')
    .attr('stroke', 'orange')
    .attr('class', 'casubun hoved')


    console.log(d);
    d3.select('.distinfo')
    .html(function(){
      console.log((d.properties.name))

      if(d.properties.name != undefined ){
      return 'District ' +  d.properties.DISTRICT +' '+ d.properties.name}
      else{
        return 'No one'
      }
      })
  })
  .on('mouseout', function(d){
    console.log('outter there')

  });


})

});

}

function makePcol(d){
  //  console.log('making colors', d)
  if(d.properties.party == 'Democrat'){
    return 'blue'
  }
  else if(d.properties.party == 'Republican'){
    return 'red';
  }
  else{
    return 'yellow'
  }

}

makemap('upper');

d3.select("body")
.transition()
.style("background-color", "black");

function housech(value){
  console.log('house changed', value)
  makemap(value);
}

zoomed.js

  function zoomed() {
    features.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
    features.selectAll(".bords").style("stroke-width", 1.5 / d3.event.scale + "px");
    features.selectAll(".myloc").attr("r", 8 / d3.event.scale + "px");
}