A Pen by Chris Smith on CodePen.
Created
November 23, 2019 18:10
-
-
Save smitty1eGH/d47a326631d233904cef1d0aace7b843 to your computer and use it in GitHub Desktop.
SmithAssignment6
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
<div id='map'></div> | |
<div class='filter-ctrl'> | |
<input id='filter-input' type='text' name='filter' placeholder='Filter by pri_mo ' /> | |
</div> | |
<div id='menu'></div> |
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
//https://docs.mapbox.com/mapbox-gl-js/example/simple-map/ | |
/* Default style options | |
mapbox://styles/mapbox/streets-v10 | |
mapbox://styles/mapbox/outdoors-v10 | |
mapbox://styles/mapbox/light-v9 | |
mapbox://styles/mapbox/dark-v9 | |
mapbox://styles/mapbox/satellite-v9 | |
mapbox://styles/mapbox/satellite-streets-v10 | |
mapbox://styles/mapbox/navigation-preview-day-v2 | |
mapbox://styles/mapbox/navigation-preview-night-v2 | |
mapbox://styles/mapbox/navigation-guidance-day-v2 | |
mapbox://styles/mapbox/navigation-guidance-night-v2 | |
*/ | |
mapboxgl.accessToken = | |
"pk.eyJ1Ijoic21pdHR5MWUiLCJhIjoiY2syY2NnNmhjMXkyazNib2psYzhuNXc4dyJ9.U-kpFeCWrn84xGTm3PZ_rw"; | |
// filtering content | |
var filterInput = document.getElementById("filter-input"); | |
// create map | |
var map = new mapboxgl.Map({ | |
container: "map", | |
style: "mapbox://styles/mapbox/light-v10", | |
center: [-122.4102, 37.79], | |
zoom: 15.7, | |
pitch: 65, | |
bearing: 83, | |
container: "map", | |
antialias: true | |
}); | |
fetch( | |
"https://smitty1egh.carto.com/api/v2/sql?format=GeoJSON&q=SELECT CASE WHEN weap='blunt_instrument' THEN 'golf-15' WHEN weap='other' THEN 'alcohol-shop-15' WHEN weap='knife' THEN 'monument-15' WHEN weap='fist' THEN 'police-1' WHEN weap='gun' THEN 'drinking-water-15' END AS w, * FROM (SELECT coalesce(weapon,'fist') as weap, coalesce(primary_mo,'KUNG FU FIGHTING') AS pri_mo, * FROM nyc_homicides) AS A " | |
) | |
.then(response => { | |
return response.json(); // check whether the reply is json | |
}) | |
.then(poi_data => { | |
// if promise fulfilled, i.e., json | |
// console.log("Number of Feature: ", geonames_data.features.length); | |
// console.log(poi_data.features.length); | |
// poi_data.features.forEach(function(feature) { | |
// console.log(feature.properties.name); | |
// }); | |
map.on("load", function() { | |
//heatmap-begin | |
map.addSource("poi-heatmap", { | |
data: poi_data, | |
type: "geojson" | |
}); | |
// heatmap cluster layer | |
map.addLayer({ | |
id: "poi-heat", | |
type: "heatmap", | |
source: "poi-heatmap", | |
maxzoom: 15, | |
paint: { | |
// increase intensity as zoom level increases | |
"heatmap-intensity": { | |
stops: [[11, 1], [15, 3]] | |
}, | |
// assign color values be applied to points depending on their density | |
"heatmap-color": [ | |
"interpolate", | |
["linear"], | |
["heatmap-density"], | |
0, | |
"rgba(33,102,172,0)", | |
0.2, | |
"rgb(103,169,207)", | |
0.4, | |
"rgb(209,229,240)", | |
0.6, | |
"rgb(253,219,199)", | |
0.8, | |
"rgb(239,138,98)", | |
1, | |
"rgb(178,24,43)" | |
], // increase radius as zoom increases | |
"heatmap-radius": { | |
stops: [[11, 8], [15, 12]] | |
}, | |
// decrease opacity to transition into the circle layer | |
"heatmap-opacity": { | |
default: 1, | |
stops: [[14, 1], [15, 0]] | |
} | |
} | |
}); //map.on("load" | |
map.addLayer({ | |
id: "3d-buildings", | |
source: "composite", | |
"source-layer": "building", | |
filter: ["==", "extrude", "true"], | |
type: "fill-extrusion", | |
minzoom: 15, | |
paint: { | |
"fill-extrusion-color": "#aaa", | |
//'interpolate' expression adds smooth transition effect to the | |
// buildings as the user zooms in | |
"fill-extrusion-height": [ | |
"interpolate", | |
["linear"], | |
["zoom"], | |
15, | |
0, | |
15.05, | |
["get", "height"] | |
], | |
"fill-extrusion-base": [ | |
"interpolate", | |
["linear"], | |
["zoom"], | |
15, | |
0, | |
15.05, | |
["get", "min_height"] | |
], | |
"fill-extrusion-opacity": 0.6 | |
} | |
}); // map.addLayer({ 3d-buildings | |
//Add source from our GeoJSON data, set the 'cluster'=true. | |
// GL-JS adds point_count property to source data. | |
map.addSource("poi-clusters", { | |
type: "geojson", | |
data: poi_data, | |
cluster: true, | |
clusterMaxZoom: 14, // Max zoom to cluster points on | |
clusterRadius: 50 // Cluster radius when clustering (defaults=50) | |
}); | |
map.addLayer({ | |
id: "poi-clusters", | |
type: "circle", | |
source: "poi-clusters", | |
filter: ["has", "point_count"], | |
paint: { | |
// Use step expressions (https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step) | |
// with three steps to implement three types of circles: | |
// * Blue, 20px circles when point count is less than 100 | |
// * Yellow, 30px circles when point count is between 100 and 750 | |
// * Pink, 40px circles when point count is greater than or equal to 750 | |
"circle-color": [ | |
"step", | |
["get", "point_count"], | |
"#51bbd6", | |
250, | |
"#f1f075", | |
1000, | |
"#f28cb1" | |
], | |
"circle-radius": [ | |
"step", | |
["get", "point_count"], | |
20, | |
250, | |
30, | |
1000, | |
40 | |
] | |
} | |
}); // map.addLayer({ poi-clusters | |
map.addLayer({ | |
id: "cluster-count", | |
type: "symbol", | |
source: "poi-clusters", | |
filter: ["has", "point_count"], | |
layout: { | |
"text-field": "{point_count_abbreviated}", | |
"text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"], | |
"text-size": 12 | |
} | |
}); | |
map.addLayer({ | |
id: "unclustered-point", | |
type: "symbol", | |
source: "poi-clusters", | |
filter: ["!", ["has", "point_count"]], | |
layout: { | |
"icon-image": ['get', 'w'], | |
"icon-size" : 2 | |
} | |
}); | |
// fit map to bounds of data | |
// https://stackoverflow.com/questions/35586360/mapbox-gl-js-getbounds-fitbounds | |
var bounds = new mapboxgl.LngLatBounds(); | |
poi_data.features.forEach(function(feature) { | |
bounds.extend(feature.geometry.coordinates); | |
}); | |
map.fitBounds(bounds); | |
filterInput.addEventListener("keypress", function(e) { | |
// If the input value matches a layerID set | |
// it's visibility to 'visible' or else hide it. | |
var key = e.which || e.keyCode; | |
if (key === 13) { | |
// 13 is enter - if key is enter key, read out value of text field | |
var term = e.target.value.trim().toLowerCase(); | |
console.log(term); | |
var filteredFeatures = poi_data.features.filter(function(feature) { | |
return feature.properties.pri_mo.toLowerCase().includes(term); | |
}); | |
var filteredFeatureCollection = { | |
type: "FeatureCollection", | |
features: filteredFeatures | |
}; | |
map.getSource("poi-clusters").setData(filteredFeatureCollection); | |
} | |
}); // filterInput | |
//popup-begin | |
// Create a popup, but don't add it to the map yet. | |
var popup = new mapboxgl.Popup({ | |
closeButton: false, | |
closeOnClick: false | |
}); | |
// single location markers | |
// See also https://docs.mapbox.com/mapbox-gl-js/example/popup-on-hover/ | |
map.on("mouseenter", "unclustered-point", function(e) { | |
// Change the cursor style as a UI indicator. | |
map.getCanvas().style.cursor = "pointer"; | |
//TODO: need to pull the correct field names from | |
// the dataset for the description variable. | |
var coordinates = e.features[0].geometry.coordinates.slice(); | |
var description = "Primary MO - " + e.features[0].properties.pri_mo; | |
// Ensure that if the map is zoomed out such that multiple | |
// copies of the feature are visible, the popup appears | |
// over the copy being pointed to. | |
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) { | |
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360; | |
} | |
// Populate the popup and set its coordinates | |
// based on the feature found. | |
popup | |
.setLngLat(coordinates) | |
.setHTML(description) | |
.addTo(map); | |
}); | |
map.on("mouseleave", "unclustered-point", function() { | |
map.getCanvas().style.cursor = ""; | |
popup.remove(); | |
}); | |
//popup-end | |
//layer-begin | |
//code due to https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/ | |
var toggleableLayerIds = [ "poi-clusters" | |
, "poi-heat" | |
]; | |
for (var i = 0; i < toggleableLayerIds.length; i++) { | |
var id = toggleableLayerIds[i]; | |
var link = document.createElement('a'); | |
link.href = '#'; | |
link.className = 'active'; | |
link.textContent = id; | |
link.onclick = function (e) { | |
var clickedLayer = this.textContent; | |
e.preventDefault(); | |
e.stopPropagation(); | |
var visibility = map.getLayoutProperty(clickedLayer, 'visibility'); | |
if (visibility === 'visible') { | |
map.setLayoutProperty(clickedLayer, 'visibility', 'none'); | |
this.className = ''; | |
} else { | |
this.className = 'active'; | |
map.setLayoutProperty(clickedLayer, 'visibility', 'visible'); | |
} | |
}; | |
var layers = document.getElementById('menu'); | |
layers.appendChild(link); | |
} | |
//layer-end | |
}); | |
}) | |
.catch(err => { | |
console.log("Erro loading data: ", err); | |
}); |
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
<script src="https://cdnjs.cloudflare.com/ajax/libs/mapbox-gl/1.4.0/mapbox-gl.js"></script> |
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
body { | |
margin: 0; | |
padding: 0; | |
} | |
#map { | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
width: 100%; | |
} | |
#menu { | |
position: absolute; | |
top: 10px; | |
right: 10px; | |
display: flex; | |
border-radius: 3px; | |
background-color: rgb(255, 255, 255); | |
padding: 10px; | |
z-index: 10; | |
display: flex; | |
flex-flow: column; | |
justify-content: space-between; | |
} | |
.switch-container { | |
display: flex; | |
flex-flow: row; | |
justify-content: space-between; | |
} | |
.switch { | |
margin-left: 3px; | |
} | |
.filter-ctrl { | |
position: absolute; | |
top: 10px; | |
right: 10px; | |
z-index: 1; | |
width: 180px; | |
} | |
.filter-ctrl input[type="text"] { | |
font: 12px/20px "Helvetica Neue", Arial, Helvetica, sans-serif; | |
width: 100%; | |
border: 0; | |
background-color: #fff; | |
height: 40px; | |
margin: 0; | |
color: rgba(0, 0, 0, 0.5); | |
padding: 10px; | |
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1); | |
border-radius: 3px; | |
} |
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
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.1/mapbox-gl.css" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment