Last active
April 29, 2018 20:50
-
-
Save lingyielia/ea6ad33ef89176dc9566eac049975ae5 to your computer and use it in GitHub Desktop.
NYC Cuisine Map
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: gpl-3.0 | |
height: 1700 | |
scrolling: no | |
border: yes |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta name="robots" content="noindex"> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>Cuisine Map</title> | |
<style id="jsbin-css"> | |
.zipcode { | |
stroke: black; | |
stroke-width: 1px; | |
fill: none; | |
} | |
.mark { | |
stroke: black; | |
} | |
.tooltip { | |
position: absolute; | |
z-index: 10; | |
visibility: hidden; | |
background: beige; | |
padding: 5px; | |
border: 1px solid black; | |
} | |
.x-axis path { | |
display: none; | |
} | |
.y-axis path { | |
display: none; | |
} | |
.grid path { | |
stroke-width: 0; | |
} | |
.grid line { | |
stroke: lightgrey; | |
stroke-opacity: 0.7; | |
shape-rendering: crispEdges; | |
} | |
.label { | |
fill: black; | |
font-size: 14px; | |
} | |
</style> | |
</head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script> | |
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.25.5/d3-legend.min.js"></script> | |
<body> | |
<div id="chart"> | |
<svg width="400" height="800" id="svg1"></svg> | |
<svg width="650" height="800" id="svg2"></svg> | |
</div> | |
<script id="jsbin-javascript"> | |
var ZIPCODE_URL = | |
"https://raw.githubusercontent.com/lingyielia/D3-visual/master/data/nyc_zip.geojson"; | |
var RES_BY_CUISINE_URL = | |
"https://raw.githubusercontent.com/lingyielia/D3-visual/master/data/nyc_restaurants_by_cuisine.json"; | |
d3.queue() | |
.defer(d3.json, ZIPCODE_URL) | |
.defer(d3.json, RES_BY_CUISINE_URL) | |
.await(createChart); | |
function createChart(error, zipcodes, byCuisine) { | |
//////////////////////////////////////////////////////// | |
///////////////// map plot ///////////////////////////// | |
//////////////////////////////////////////////////////// | |
var svg2 = d3.select("#svg2"), | |
gMap = svg2.append("g"), | |
canvasSize = [650,800], | |
projection = d3.geoMercator() | |
.scale(Math.pow(2, 10.66 + 5.34)) | |
.center([-73.975, 40.7]) | |
.translate([canvasSize[0]/2, canvasSize[1]/2]), | |
path = d3.geoPath() | |
.projection(projection); | |
gMap.selectAll(".zipcode") | |
.data(zipcodes.features) | |
.enter() | |
.append("path") | |
.attr("class", "zipcode") | |
.attr("d", path); | |
var index = 0; | |
function mapUpdate(index) { | |
var counts = byCuisine[index].perZip, | |
data = Object.entries(counts), | |
maxCount = d3.max(data, d => d[1]), | |
color = d3.scaleThreshold() | |
.domain(d3.range(0, maxCount, maxCount/5)) | |
.range(d3.schemeBlues[5]) | |
zc = gMap.selectAll(".zipcode") | |
.data(data, myKey); | |
zc.merge(zc) | |
.transition().duration(1000) | |
.style("fill", d => color(d[1])); | |
zc.exit() | |
.transition().duration(1000) | |
.style("fill", "transparent"); | |
var linear = d3.scaleLinear() | |
.domain([0,maxCount]) | |
.range(["#BFD9E5", "#0758A2"]); | |
gMap.append("g") | |
.attr("class", "legendLinear") | |
.attr("transform", "translate(15,100)"); | |
var legendLinear = d3.legendColor() | |
.title("Number of " + cuisine[index] + " Restauants") | |
.labelAlign("start") | |
.labelFormat(".2s") | |
.shapeHeight(5) | |
.shapeWidth(60) | |
.cells(4) | |
.orient('horizontal') | |
.scale(linear); | |
gMap.select(".legendLinear") | |
.call(legendLinear); | |
} | |
//////////////////////////////////////////////////////// | |
///////////////// bar plot ///////////////////////////// | |
//////////////////////////////////////////////////////// | |
var svg1 = d3.select("#svg1"), | |
g = svg1.append("g"), | |
cuisine = byCuisine.slice(0,25).map(function(d) {return d.cuisine;}), | |
total = byCuisine.slice(0,25).map(function(d) {return d.total;}), | |
maxValue = d3.max(total); | |
var w = d3.scaleLinear() | |
.domain([0, maxValue]) | |
.rangeRound([0, 200]); | |
// gridlines | |
var make_x_gridlines = d3.axisBottom() | |
.tickFormat("") | |
.tickSize(600) | |
.scale(w) | |
.ticks(5); | |
// add the x gridlines | |
g.append("g") | |
.attr("class", "grid") | |
.attr("transform", "translate(150,100)") | |
.call(make_x_gridlines); | |
g.selectAll(".mark") | |
.data(total) | |
.enter() | |
.append('rect') | |
.attr('class', 'mark') | |
.attr('x', 150) | |
.attr('y', function(d,i) {return 100+i*24;}) | |
.attr('width', function(d,i) {return w(d);}) | |
.attr('height', 22) | |
.attr('fill','lightgrey') | |
.on("mouseover", function(d) { | |
d3.select(this) | |
.transition().ease(d3.easeSin).duration(500) | |
.attr("fill", "SteelBlue") | |
.attr('x', 150) | |
.attr('width', function(d,i) {return w(d)+20;}) | |
.attr('height', 22+2); | |
var index = mapUpdate(total.indexOf(d)); | |
mapUpdate(index); | |
}) | |
.on("mouseout", function(d) { | |
d3.select(this) | |
.transition().duration(500) | |
.attr("fill", "lightgrey") | |
.attr('x', 150) | |
.attr('width', function(d,i) {return w(d);}) | |
.attr('height', 22); | |
}); | |
var xAxis = d3.axisBottom() | |
.scale(w) | |
.ticks(5); | |
var xAxisTop = d3.axisTop() | |
.scale(w) | |
.ticks(5); | |
g.append("g") | |
.attr("class", "x-axis") | |
.attr("transform", "translate(150,700)") | |
.call(xAxis) | |
.append("text") | |
.attr("class", "label") | |
.style("text-anchor", "middle") | |
.attr("transform","translate(100,40)") | |
.text("Number of Restaurants"); | |
g.append("g") | |
.attr("class", "x-axis") | |
.attr("transform", "translate(150,100)") | |
.call(xAxisTop); | |
var y = d3.scalePoint().domain(cuisine).range([0,577]); | |
var yAxis = d3.axisLeft() | |
.scale(y); | |
g.append("g") | |
.attr("class", "y-axis") | |
.attr("transform", "translate(146,110)") | |
.call(yAxis); | |
} | |
function myKey(d) { | |
return (d[0]?d[0]:d.properties.zipcode); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment