Skip to content

Instantly share code, notes, and snippets.

@mpmckenna8
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mpmckenna8/12bfcf6cd85b7f205475 to your computer and use it in GitHub Desktop.
Save mpmckenna8/12bfcf6cd85b7f205475 to your computer and use it in GitHub Desktop.
zooming with d3 geo

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.

<!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="http://d3js.org/d3.v3.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="./zoomed.js"></script>
<script src="./twomap.js"></script>
</body>
/* 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;
}
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);
}
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");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment