Skip to content

Instantly share code, notes, and snippets.

@lingyielia
Created May 6, 2018 07:49
Show Gist options
  • Save lingyielia/ce2719ba65087e50a6e0bf01581dc312 to your computer and use it in GitHub Desktop.
Save lingyielia/ce2719ba65087e50a6e0bf01581dc312 to your computer and use it in GitHub Desktop.
JS Bin // source https://jsbin.com/xihewuk
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style id="jsbin-css">
#map {
width: 650px;
height: 650px;
float: left;
display: inline-block;
}
.zipcode {
stroke: black;
stroke-width: 1px;
fill: none;
}
.legendbox {
background: rgba(255,255,255,0.7);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
height: 45px;
width: 300px;
}
/* .leaflet-edit-move {
max-width: 16px;
max-height: 16px;
border-radius: 50%;
background: #ff7800;
border: 1px solid #000;
opacity: 0.85;
}
.leaflet-edit-resize {
max-width: 16px;
max-height: 16px;
border-radius: 50%;
background: #0078ff;
border: 1px solid #000;
opacity: 0.85;
} */
</style>
</head>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css"
integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js"
integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw=="
crossorigin=""></script>
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet.css" /> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet.js"></script> -->
<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>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.2/leaflet.draw.js"></script>
<body>
</div>
<div id="map">
</div>
<script id="jsbin-javascript">
const ZIPCODE_URL = "https://raw.githubusercontent.com/lingyielia/D3-visual/master/data/nyc_zip.geojson";
const count_url = "https://raw.githubusercontent.com/YukunVVan/DataViz-Project/master/DataPreprocess/defalt/casebyzip.json?token=AefhM2qQI6hcXfR-MdLqH2MW0YjflTl7ks5a93-mwA%3D%3D";
function createBaseMap() {
let center = [40.7, -73.975],
cusp = [40.692908,-73.9896452]
baseLight = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png',
{ minZoom: 10, }),
circle = L.circle(cusp, 1000, options={editable: true}),
dMap = L.map('map', {
center: center,
zoom: 10,
layers: [baseLight]
}),
svg = d3.select(dMap.getPanes().overlayPane).append("svg"),
g = svg.append("g").attr("class", "leaflet-zoom-hide");
L.control.layers({
"Light": baseLight,
},
{
"Selection": circle,
}).addTo(dMap);
let infoBox = L.control({position: 'bottomleft'});
infoBox.onAdd = function (map) {var div = L.DomUtil.create('div', 'infobox'); return div;}
infoBox.addTo(dMap);
return [svg, g, dMap, circle];
}
d3.queue()
.defer(d3.json, ZIPCODE_URL)
.defer(d3.json, count_url)
.await(createMap);
function createMap(error, zipcodes, countdata) {
let baseMap = createBaseMap();
function projectPoint(x, y) {
let point = dMap.latLngToLayerPoint(new L.LatLng(y, x));
this.stream.point(point.x, point.y);
}
let projection = d3.geoTransform({point: projectPoint}),
path = d3.geoPath().projection(projection),
svg = baseMap[0],
g = baseMap[1],
dMap = baseMap[2];
let legendControl = L.control({position: 'topleft'});
legendControl.onAdd = addLegendToMap;
legendControl.addTo(dMap);
dMap.on("zoomend", reproject);
reproject();
function addLegendToMap(map) {
let div = L.DomUtil.create('div', 'legendbox'),
ndiv = d3.select(div)
.style("left", "50px")
.style("top", "-75px"),
lsvg = ndiv.append("svg"),
legend = lsvg.append("g")
.attr("class", "legend")
.attr("transform", "translate(0, 20)");
legend.append("text")
.attr("class", "axis--map--caption")
.attr("y", -6);
return div;
};
function reproject() {
bounds = path.bounds(zipcodes);
let topLeft = bounds[0],
bottomRight = bounds[1];
svg.attr("width", bottomRight[0] - topLeft[0])
.attr("height", bottomRight[1] - topLeft[1])
.style("left", topLeft[0] + "px")
.style("top", topLeft[1] + "px");
// Then also transform our map group
g.attr("transform", `translate(${-topLeft[0]}, ${-topLeft[1]})`);
// And update the actual D3 visual elements
let zipShapes = g.selectAll(".zipcode")
.data(zipcodes.features); // we rejoin the data
zipShapes
.enter().append("path")
.attr("class", "zipcode")
.merge(zipShapes) // and perform updates on both match and unmatches
.attr("d", path);
// Redraw the map
updateMap(g, zipcodes, countdata);
}
}
function updateMap(g, zipcodes, countdata) {
var countbyzip = {},
counts = countdata.map(d => d.count),
maxCount = d3.max(counts),
color = d3.scaleThreshold()
.domain(d3.range(0, maxCount, maxCount/5))
.range(d3.schemePurples[5]),
x = d3.scaleLinear()
.domain([0, maxCount])
.rangeRound([50, 300]),
legend = d3.select(".legend");
let boxes = legend.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
return [(d[0]!==null?d[0]:x.domain()[0]),
(d[1]!==null?d[1]:x.domain()[1])];
}));
boxes
.enter().append("rect")
.merge(boxes)
.attr("height", 6)
.attr("x", d => x(d[0]))
.attr("width", d => (x(d[1]) - x(d[0])))
.attr("fill", d => 'rebeccapurple');
countdata.forEach(function (d) {
countbyzip[d.zipcode] = +d.count;
});
g.selectAll(".zipcode")
.data(zipcodes.features)
.style("fill", function(d) {return color(countbyzip[d.properties.zipcode]);});
legend.call(d3.axisBottom(x)
.ticks(5, "s")
.tickSize(10,0)
.tickValues(color.domain()))
.select(".domain")
.remove();
legend.select(".axis--map--caption")
.attr("x", x.range()[0])
.text('Number of Complaints');
}
</script>
<script id="jsbin-source-css" type="text/css">#map {
width: 650px;
height: 650px;
float: left;
display: inline-block;
}
.zipcode {
stroke: black;
stroke-width: 1px;
fill: none;
}
.legendbox {
background: rgba(255,255,255,0.7);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
height: 45px;
width: 300px;
}
/* .leaflet-edit-move {
max-width: 16px;
max-height: 16px;
border-radius: 50%;
background: #ff7800;
border: 1px solid #000;
opacity: 0.85;
}
.leaflet-edit-resize {
max-width: 16px;
max-height: 16px;
border-radius: 50%;
background: #0078ff;
border: 1px solid #000;
opacity: 0.85;
} */</script>
<script id="jsbin-source-javascript" type="text/javascript">const ZIPCODE_URL = "https://raw.githubusercontent.com/lingyielia/D3-visual/master/data/nyc_zip.geojson";
const count_url = "https://raw.githubusercontent.com/YukunVVan/DataViz-Project/master/DataPreprocess/defalt/casebyzip.json?token=AefhM2qQI6hcXfR-MdLqH2MW0YjflTl7ks5a93-mwA%3D%3D";
function createBaseMap() {
let center = [40.7, -73.975],
cusp = [40.692908,-73.9896452]
baseLight = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png',
{ minZoom: 10, }),
circle = L.circle(cusp, 1000, options={editable: true}),
dMap = L.map('map', {
center: center,
zoom: 10,
layers: [baseLight]
}),
svg = d3.select(dMap.getPanes().overlayPane).append("svg"),
g = svg.append("g").attr("class", "leaflet-zoom-hide");
L.control.layers({
"Light": baseLight,
},
{
"Selection": circle,
}).addTo(dMap);
let infoBox = L.control({position: 'bottomleft'});
infoBox.onAdd = function (map) {var div = L.DomUtil.create('div', 'infobox'); return div;}
infoBox.addTo(dMap);
return [svg, g, dMap, circle];
}
d3.queue()
.defer(d3.json, ZIPCODE_URL)
.defer(d3.json, count_url)
.await(createMap);
function createMap(error, zipcodes, countdata) {
let baseMap = createBaseMap();
function projectPoint(x, y) {
let point = dMap.latLngToLayerPoint(new L.LatLng(y, x));
this.stream.point(point.x, point.y);
}
let projection = d3.geoTransform({point: projectPoint}),
path = d3.geoPath().projection(projection),
svg = baseMap[0],
g = baseMap[1],
dMap = baseMap[2];
let legendControl = L.control({position: 'topleft'});
legendControl.onAdd = addLegendToMap;
legendControl.addTo(dMap);
dMap.on("zoomend", reproject);
reproject();
function addLegendToMap(map) {
let div = L.DomUtil.create('div', 'legendbox'),
ndiv = d3.select(div)
.style("left", "50px")
.style("top", "-75px"),
lsvg = ndiv.append("svg"),
legend = lsvg.append("g")
.attr("class", "legend")
.attr("transform", "translate(0, 20)");
legend.append("text")
.attr("class", "axis--map--caption")
.attr("y", -6);
return div;
};
function reproject() {
bounds = path.bounds(zipcodes);
let topLeft = bounds[0],
bottomRight = bounds[1];
svg.attr("width", bottomRight[0] - topLeft[0])
.attr("height", bottomRight[1] - topLeft[1])
.style("left", topLeft[0] + "px")
.style("top", topLeft[1] + "px");
// Then also transform our map group
g.attr("transform", `translate(${-topLeft[0]}, ${-topLeft[1]})`);
// And update the actual D3 visual elements
let zipShapes = g.selectAll(".zipcode")
.data(zipcodes.features); // we rejoin the data
zipShapes
.enter().append("path")
.attr("class", "zipcode")
.merge(zipShapes) // and perform updates on both match and unmatches
.attr("d", path);
// Redraw the map
updateMap(g, zipcodes, countdata);
}
}
function updateMap(g, zipcodes, countdata) {
var countbyzip = {},
counts = countdata.map(d => d.count),
maxCount = d3.max(counts),
color = d3.scaleThreshold()
.domain(d3.range(0, maxCount, maxCount/5))
.range(d3.schemePurples[5]),
x = d3.scaleLinear()
.domain([0, maxCount])
.rangeRound([50, 300]),
legend = d3.select(".legend");
let boxes = legend.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
return [(d[0]!==null?d[0]:x.domain()[0]),
(d[1]!==null?d[1]:x.domain()[1])];
}));
boxes
.enter().append("rect")
.merge(boxes)
.attr("height", 6)
.attr("x", d => x(d[0]))
.attr("width", d => (x(d[1]) - x(d[0])))
.attr("fill", d => 'rebeccapurple');
countdata.forEach(function (d) {
countbyzip[d.zipcode] = +d.count;
});
g.selectAll(".zipcode")
.data(zipcodes.features)
.style("fill", function(d) {return color(countbyzip[d.properties.zipcode]);});
legend.call(d3.axisBottom(x)
.ticks(5, "s")
.tickSize(10,0)
.tickValues(color.domain()))
.select(".domain")
.remove();
legend.select(".axis--map--caption")
.attr("x", x.range()[0])
.text('Number of Complaints');
}
</script></body>
</html>
#map {
width: 650px;
height: 650px;
float: left;
display: inline-block;
}
.zipcode {
stroke: black;
stroke-width: 1px;
fill: none;
}
.legendbox {
background: rgba(255,255,255,0.7);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
height: 45px;
width: 300px;
}
/* .leaflet-edit-move {
max-width: 16px;
max-height: 16px;
border-radius: 50%;
background: #ff7800;
border: 1px solid #000;
opacity: 0.85;
}
.leaflet-edit-resize {
max-width: 16px;
max-height: 16px;
border-radius: 50%;
background: #0078ff;
border: 1px solid #000;
opacity: 0.85;
} */
const ZIPCODE_URL = "https://raw.githubusercontent.com/lingyielia/D3-visual/master/data/nyc_zip.geojson";
const count_url = "https://raw.githubusercontent.com/YukunVVan/DataViz-Project/master/DataPreprocess/defalt/casebyzip.json?token=AefhM2qQI6hcXfR-MdLqH2MW0YjflTl7ks5a93-mwA%3D%3D";
function createBaseMap() {
let center = [40.7, -73.975],
cusp = [40.692908,-73.9896452]
baseLight = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png',
{ minZoom: 10, }),
circle = L.circle(cusp, 1000, options={editable: true}),
dMap = L.map('map', {
center: center,
zoom: 10,
layers: [baseLight]
}),
svg = d3.select(dMap.getPanes().overlayPane).append("svg"),
g = svg.append("g").attr("class", "leaflet-zoom-hide");
L.control.layers({
"Light": baseLight,
},
{
"Selection": circle,
}).addTo(dMap);
let infoBox = L.control({position: 'bottomleft'});
infoBox.onAdd = function (map) {var div = L.DomUtil.create('div', 'infobox'); return div;}
infoBox.addTo(dMap);
return [svg, g, dMap, circle];
}
d3.queue()
.defer(d3.json, ZIPCODE_URL)
.defer(d3.json, count_url)
.await(createMap);
function createMap(error, zipcodes, countdata) {
let baseMap = createBaseMap();
function projectPoint(x, y) {
let point = dMap.latLngToLayerPoint(new L.LatLng(y, x));
this.stream.point(point.x, point.y);
}
let projection = d3.geoTransform({point: projectPoint}),
path = d3.geoPath().projection(projection),
svg = baseMap[0],
g = baseMap[1],
dMap = baseMap[2];
let legendControl = L.control({position: 'topleft'});
legendControl.onAdd = addLegendToMap;
legendControl.addTo(dMap);
dMap.on("zoomend", reproject);
reproject();
function addLegendToMap(map) {
let div = L.DomUtil.create('div', 'legendbox'),
ndiv = d3.select(div)
.style("left", "50px")
.style("top", "-75px"),
lsvg = ndiv.append("svg"),
legend = lsvg.append("g")
.attr("class", "legend")
.attr("transform", "translate(0, 20)");
legend.append("text")
.attr("class", "axis--map--caption")
.attr("y", -6);
return div;
};
function reproject() {
bounds = path.bounds(zipcodes);
let topLeft = bounds[0],
bottomRight = bounds[1];
svg.attr("width", bottomRight[0] - topLeft[0])
.attr("height", bottomRight[1] - topLeft[1])
.style("left", topLeft[0] + "px")
.style("top", topLeft[1] + "px");
// Then also transform our map group
g.attr("transform", `translate(${-topLeft[0]}, ${-topLeft[1]})`);
// And update the actual D3 visual elements
let zipShapes = g.selectAll(".zipcode")
.data(zipcodes.features); // we rejoin the data
zipShapes
.enter().append("path")
.attr("class", "zipcode")
.merge(zipShapes) // and perform updates on both match and unmatches
.attr("d", path);
// Redraw the map
updateMap(g, zipcodes, countdata);
}
}
function updateMap(g, zipcodes, countdata) {
var countbyzip = {},
counts = countdata.map(d => d.count),
maxCount = d3.max(counts),
color = d3.scaleThreshold()
.domain(d3.range(0, maxCount, maxCount/5))
.range(d3.schemePurples[5]),
x = d3.scaleLinear()
.domain([0, maxCount])
.rangeRound([50, 300]),
legend = d3.select(".legend");
let boxes = legend.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
return [(d[0]!==null?d[0]:x.domain()[0]),
(d[1]!==null?d[1]:x.domain()[1])];
}));
boxes
.enter().append("rect")
.merge(boxes)
.attr("height", 6)
.attr("x", d => x(d[0]))
.attr("width", d => (x(d[1]) - x(d[0])))
.attr("fill", d => 'rebeccapurple');
countdata.forEach(function (d) {
countbyzip[d.zipcode] = +d.count;
});
g.selectAll(".zipcode")
.data(zipcodes.features)
.style("fill", function(d) {return color(countbyzip[d.properties.zipcode]);});
legend.call(d3.axisBottom(x)
.ticks(5, "s")
.tickSize(10,0)
.tickValues(color.domain()))
.select(".domain")
.remove();
legend.select(".axis--map--caption")
.attr("x", x.range()[0])
.text('Number of Complaints');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment