xxxxxxxxxx
<head>
<meta charset="utf-8">
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src='https://api.mapbox.com/mapbox-gl-js/v0.31.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v0.31.0/mapbox-gl.css' rel='stylesheet' />
<style>
/* apply a natural box layout model to all elements, but allowing components to change */
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin:0;position:fixed;top:0;right:0;bottom:0;left:0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #1A2D37;
font-size: 12px;
}
#map {
position:absolute;
width: 100%;
height: 100%;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
#property-card {
position: fixed;
height: 400px;
width: 300px;
top: 8px;
left: 8px;
border-radius: 4px;
background-color: #F2F2F4;
overflow: scroll;
}
.section {
background-color: #FFFFFF;
border-radius: 4px;
margin: 8px;
padding: 5px;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="property-card"></div>
<script>
function buildUrl(url, queryParams) {
url += '?';
queryParams.forEach(function(param){
url += `${param}&`
})
return url.slice(0, -1);
}
</script>
<script>
//Setup mapbox-gl map
mapboxgl.accessToken = 'pk.eyJ1Ijoiam9uc2Fka2EiLCJhIjoiY2l4ejkzM3FuMDA0bzMycDl2ZXE0cGw2byJ9.YVf_mtIw3xABynhjwojKQg';
const map = new mapboxgl.Map({
center: [-118.4, 34],
container: 'map', // id of the container
pitch: 40,
scrollZoom: true,
style: 'mapbox://styles/jonsadka/cixzpqzbj003g2srjakw769o5',
zoom: 9
})
map.addControl(new mapboxgl.NavigationControl())
function project(d) {
const position = getLatLong(d);
if (position) {
return map.project(position);
}
}
function getLatLong(d) {
const longitude = +d.center_lon || (+d.location_1 || {}).longitude;
const latitude = +d.center_lat || (+d.location_1 || {}).latitude;
if (longitude && latitude) {
return new mapboxgl.LngLat(longitude, latitude);
}
}
const container = map.getCanvasContainer();
const canvas = d3.select(container).append('canvas').node();
const boundingBox = document.body.getBoundingClientRect();
canvas.width = boundingBox.width;
canvas.height = boundingBox.height;
const context = canvas.getContext('2d');
const url06To16 = 'https://data.lacounty.gov/resource/hvzm-fn38.json';
d3.queue()
.defer(d3.json, buildUrl(url06To16, [
'$where=units > 22', '$limit=20000', 'yearbuilt=1989'
]))
.await(initialRender)
let diagram;
function initialRender(error, propertyData) {
if (error) return console.warn(error);
console.log(
propertyData.length,
propertyData[0],
getLatLong(propertyData[0]),
project(propertyData[0])
)
propertyData.map(function(property){
const point = project(property);
if (point) {
property.computed = property.computed || {};
property.computed.x = point.x;
property.computed.y = point.y;
}
return property;
})
const voronoi = d3.voronoi()
.x(function(d){ return d.computed.x})
.y(function(d){ return d.computed.y});
diagram = voronoi(propertyData);
// Initial render
render(propertyData);
// re-render our visualization whenever the view changes
map.on('viewreset', function() {
context.clearRect(0, 0, boundingBox.width, boundingBox.height);
propertyData.map(function(property){
const point = project(property);
if (point) {
property.computed = property.computed || {};
property.computed.x = point.x;
property.computed.y = point.y;
}
return property;
})
diagram = voronoi(propertyData);
render(propertyData);
})
map.on('move', function() {
context.clearRect(0, 0, boundingBox.width, boundingBox.height);
propertyData.map(function(property){
const point = project(property);
if (point) {
property.computed = property.computed || {};
property.computed.x = point.x;
property.computed.y = point.y;
}
return property;
})
diagram = voronoi(propertyData);
render(propertyData);
})
let lastProperty;
map.on('mousemove', function(event) {
const voronoiCell = diagram.find(event.point.x, event.point.y);
const propertyCard = document.getElementById('property-card');
if (lastProperty !== voronoiCell.data.propertylocation) {
lastProperty = voronoiCell.data.propertylocation;
var content = document.createElement('div');
content.innerText = lastProperty;
content.className = 'section';
propertyCard.append(content);
propertyCard.scrollTop = propertyCard.scrollHeight;
}
})
}
function render(data) {
const propertyValues = data.reduce(function(_propertyValues, property){
if (property.roll_totlandimp) {
_propertyValues.push(+property.roll_totlandimp);
}
return _propertyValues;
}, []);
const propertyValueColor = d3.scaleLog()
.range(['hsl(62,100%,90%)', 'hsl(228,30%,20%)'])
.domain([d3.quantile(propertyValues, .01), d3.quantile(propertyValues, .99)])
.interpolate(d3.interpolateHcl);
context.clearRect(0, 0, boundingBox.width, boundingBox.height);
data.forEach(function(property, idx) {
context.strokeStyle = '#F2F2F4';
if (property.computed) {
context.fillStyle = propertyValueColor(+property.roll_totlandimp);
context.beginPath();
context.arc(property.computed.x, property.computed.y, 4, 0, Math.PI * 2);
context.fill();
context.stroke();
}
})
}
</script>
</body>
https://d3js.org/d3.v4.min.js
https://api.mapbox.com/mapbox-gl-js/v0.31.0/mapbox-gl.js