Published
Edited
May 6, 2021
1 fork
1 star
Insert cell
md`# Leaflet-Heatmap`
Insert cell
L = require('leaflet@1.2.0')
Insert cell
html`<link href='${resolve('leaflet@1.2.0/dist/leaflet.css')}' rel='stylesheet' />`
Insert cell
import {Select} from "@observablehq/inputs"
Insert cell
import {date} from "@jashkenas/inputs"
Insert cell
d3 = require("d3@6")
Insert cell
uniqueCrimes = [...new Set( madCrimes.features.map(obj => obj.properties.incident)) ].sort();

Insert cell
madCrimes
Insert cell
grandCentral = {
let response = await fetch('https://nominatim.openstreetmap.org/search.php?q=grand+central+station%2C+new+york&polygon_geojson=1&format=json');
let json = await response.json();
return json[0].geojson
}
Insert cell
heatLayer = L, require('leaflet.heat').catch(() => L.heatLayer)
Insert cell
crimes = (await fetch('https://opendata.arcgis.com/datasets/6af5cb8dc38e4bcbac8168b27ee104aa_38.geojson')).json()
Insert cell
madCrimes = FileAttachment("new_data.geojson").json()
Insert cell
madCrimesFormatted = madCrimes.features.map((d) => {
d.properties.Occur_date = new Date(d.properties.Occur_date)
return d
})
Insert cell
viewof crimeCategory = Select(uniqueCrimes, {multiple: true, label: "Select crime category"})
Insert cell
new Date(Math.max(...madCrimes.features.map(e => new Date(e.Occur_date))));
Insert cell
madCrimes.features
Insert cell
maxDate = d3.max(madCrimes.features, d => d.properties.Occur_date)

Insert cell
minDate = d3.min(madCrimes.features, d => d.properties.Occur_date)
Insert cell
viewof start_date = date({
title: "Start",
min: minDate,
max: maxDate,
value: minDate,
description: "The earliest day is 01/01/2019"
})
Insert cell
start_date_formatted = new Date(start_date)
Insert cell
viewof end_date = date({
title: "End",
min: minDate,
max: maxDate,
value: maxDate,
description: "The last day in data is 03/10/2021"
})
Insert cell
end_date_formatted = new Date(end_date)
Insert cell
crimeMap = {
// You'll often see Leaflet examples initializing a map like L.map('map'),
// which tells the library to look for a div with the id 'map' on the page.
// In Observable, we instead create a div from scratch in this cell, so it's
// completely self-contained.
let container = DOM.element('div', { style: `width:${width}px;height:${width/1.6}px` });
// Note that I'm yielding the container pretty early here: this allows the
// div to be placed on the page. This is important, because Leaflet uses
// the div's .offsetWidth and .offsetHeight to size the map. If I were
// to only return the container at the end of this method, Leaflet might
// get the wrong idea about the map's size.
yield container;
// Create a map object and add a layer to it.
let map = L.map(container).setView([43.0927993, -89.4171004], 11);
let osmLayer = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// let osmLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
// attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
// }).addTo(map);
// Filter the data based on user input
let selectedCrimes = madCrimes.features.filter((d) => {
if (crimeCategory.length > 0){
return crimeCategory.includes(d.properties.incident) && new Date(d.properties.Occur_date) >= start_date_formatted && new Date(d.properties.Occur_date) <= end_date_formatted
} else if (crimeCategory.length === 0) {
return uniqueCrimes.includes(d.properties.incident) && new Date(d.properties.Occur_date) >= start_date_formatted && new Date(d.properties.Occur_date) <= end_date_formatted
}
})
//convert data points to [lat,lng, intensity]
let crimePoints = selectedCrimes.map(feature =>
feature.geometry.coordinates.slice().reverse().concat([0.1]));
//Add heatmap layer
let crimeLayer = heatLayer(crimePoints, {
minOpacity: 0.5,
maxZoom: 18,
max: 1.0,
radius: 8,
blur: 4,
gradient: null
}).addTo(map);
let markers = markerCluster({});
// Add popup on the markers
let schoolsLayer = L.geoJson(selectedCrimes, {
onEachFeature: function (feature, layer) {
const d = feature.properties;
// const html = `<div class="popup"><h2>${school.name}</h2>` +
// `<p>${school.district} District</p><p>grades: ${school.grades_served}</p></div>`
// layer.bindPopup(html);
layer.bindTooltip(`${d.incident}, ${d.Occur_date}`, {sticky: true});
}
});
markers.addLayer(schoolsLayer);
map.addLayer(markers);
}
Insert cell
markerCluster = L, require('leaflet.markercluster@1.1.0').catch(() => L.markerClusterGroup)
Insert cell
markerClusterCSS = html`<link href='${resolve('leaflet.markercluster@1.1.0/dist/MarkerCluster.Default.css')}' rel='stylesheet' />`
Insert cell
madCrimesFormatted
Insert cell
result = madCrimesFormatted.reduce(function(acc, curr) {
// Check if there exist an object in empty array whose CategoryId matches
var isElemExist = acc.findIndex(function(item) {
return item.Occur_weekday === curr.properties.Occur_weekday;
})
if (isElemExist === -1) {
var obj = {};
obj.Occur_weekday = curr.properties.Occur_weekday;
obj.count = 1;
acc.push(obj)
} else {
acc[isElemExist].count += 1
}
return acc;

}, [])

Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more