Skip to content

Instantly share code, notes, and snippets.

@rkrueger11
Last active November 17, 2018 00:21
Show Gist options
  • Save rkrueger11/7204eed73b46153ba7ba24f024baa24f to your computer and use it in GitHub Desktop.
Save rkrueger11/7204eed73b46153ba7ba24f024baa24f to your computer and use it in GitHub Desktop.
Box Muti Select Service Area
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Service Area Demo</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css' rel='stylesheet' />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
#controls {
display: inline-flex;
flex-direction: column;
position: absolute;
right: 0px;
margin: 10%;
background: white;
}
button {
color: white;
border: none;
padding: 0;
border: 1px solid black;
font: inherit;
cursor: pointer;
outline: inherit;
}
</style>
</head>
<body>
<style>
.boxdraw {
background: rgba(6, 134, 34, 0.1);
border: 2px solid #05a305;
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
}
</style>
<div id='map'></div>
<div id='controls'>
<button id='selection'><svg width="48px" height="48px" viewBox="0 0 32 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.3 (67297) - http://www.bohemiancoding.com/sketch -->
<title>Artboard</title>
<desc>Created with Sketch.</desc>
<defs>
<polyline id="path-1" points="9 -1.59872116e-14 17.5 -1.59872116e-14 17.5 17 0.5 17 0.5 8.5"></polyline>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="17" height="17" fill="white">
<use xlink:href="#path-1"></use>
</mask>
</defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-2" transform="translate(5.000000, 6.000000)" stroke-width="2">
<use id="Rectangle-Copy-3" stroke="#4A4A4A" mask="url(#mask-2)" stroke-dasharray="3,1" transform="translate(9.000000, 8.500000) rotate(-180.000000) translate(-9.000000, -8.500000) " xlink:href="#path-1"></use>
<g id="Group" transform="translate(12.500000, 12.000000)" stroke="#000000">
<path d="M4.5,-2.66453526e-15 L4.5,9" id="Path"></path>
<path d="M9,4.5 L0,4.5" id="Path"></path>
</g>
</g>
</g>
</svg></button>
<button id='deselection'><svg width="48px" height="48px" viewBox="0 0 32 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.3 (67297) - http://www.bohemiancoding.com/sketch -->
<title>Artboard</title>
<desc>Created with Sketch.</desc>
<defs>
<polyline id="path-1" points="8.5 -1.59872116e-14 17 -1.59872116e-14 17 17 -3.19674842e-14 17 3.01980663e-14 8.5"></polyline>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="17" height="17" fill="white">
<use xlink:href="#path-1"></use>
</mask>
</defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Group-3" transform="translate(6.000000, 6.000000)" stroke-width="2">
<use id="Rectangle-Copy" stroke="#4A4A4A" mask="url(#mask-2)" stroke-dasharray="3,1" transform="translate(8.500000, 8.500000) rotate(-180.000000) translate(-8.500000, -8.500000) " xlink:href="#path-1"></use>
<g id="Group" transform="translate(12.000000, 16.000000)" stroke="#000000">
<path d="M9,0.5 L0,0.5" id="Path"></path>
</g>
</g>
</g>
</svg>
</button>
</div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiY2xvdWRvcHNhZG1pbnMiLCJhIjoiY2puYnI3emg5MGM4cTNrcGs4andxOXRvYyJ9.OEY_B7yNuD6YQwAL6xN1YQ';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/cloudopsadmins/cjokpgicj0cmu2sojfa6zpkb9',
center: [-86.158, 39.768],
minZoom: 4,
zoom: 10
});
let selectionButtonOn = false;
let deselectionButtonOn = false;
// Disable default box zooming.
map.boxZoom.disable();
map.dragRotate.disable();
// Create a popup, but don't add it to the map yet.
var popup = new mapboxgl.Popup({
closeButton: false
});
var selectedPostalCodes = ["USP446201",
"USP446204",
"USP446205",
"USP446208",
"USP446218",
"USP446220",
"USP446222",
"USP446225"];
map.on('load', function () {
const mouseText = document.getElementById('mouse');
var canvas = map.getCanvasContainer();
canvas.style.cursor = 'pointer';
// Variable to hold the starting xy coordinates
// when `mousedown` occured.
var start;
// Variable to hold the current xy coordinates
// when `mousemove` or `mouseup` occurs.
var current;
// Variable for the draw box element.
var box;
// Add the source to query. In this example we're using
// county polygons uploaded as vector tiles
map.addSource('postal-4', {
"type": "vector",
"url": "mapbox://mapbox.enterprise-boundaries-p4-v2"
});
map.addLayer({
"id": "postal",
"type": "fill",
"source": "postal-4",
"source-layer": "boundaries_postal_4",
"paint": {
"fill-color": "rgba(0,0,0,0)",
"fill-outline-color": "rgba(0,0,0,0)"
}
}, 'place-city-sm'); // Place polygon under these labels.
map.addLayer({
"id": "postal-highlighted",
"type": "fill",
"source": "postal-4",
"source-layer": "boundaries_postal_4",
"paint": {
"fill-outline-color": "#05a305",
"fill-color": "rgba(6, 134, 34, 0.5)",
"fill-opacity": 0.75
},
"filter": [
"in",
"id",
...selectedPostalCodes,
]
}, 'place-city-sm'); // Place polygon under these labels.
// Click/Tap to select
map.on("click", "postal", e => {
selectedPostalCodes.push(e.features[0].properties.id);
map.setFilter("postal-highlighted", ["in",
"id",
...selectedPostalCodes]);
});
// Click/Tap to deselect
map.on("click", "postal-highlighted", e => {
selectedPostalCodes = selectedPostalCodes.filter((code) => code != e.features[0].properties.id);
map.setFilter("postal-highlighted", ["in",
"id",
...selectedPostalCodes]);
});
document.addEventListener('keydown', (e) => {
if (e.key === "Meta") {
deselectionButtonOn = true;
canvas.style.cursor = 'crosshair';
map.dragPan.disable();
}
if (e.key === "Shift") {
selectionButtonOn = true;
canvas.style.cursor = 'crosshair';
map.dragPan.disable();
}
});
document.addEventListener('keyup', (e) => {
if (e.key === "Meta") {
deselectionButtonOn = false;
canvas.style.cursor = 'grab';
}
if (e.key === "Shift") {
selectionButtonOn = false;
canvas.style.cursor = 'grab';
}
});
// Set `true` to dispatch the event before other functions
// call it. This is necessary for disabling the default map
// dragging behaviour.
canvas.addEventListener('mousedown', mouseDown, true);
canvas.addEventListener('touchstart', mouseDown, true);
// Return the xy coordinates of the mouse position
function mousePos(e) {
var rect = canvas.getBoundingClientRect();
let clientX = e.clientX || (e.touches[0] ? e.touches[0].clientX : e.changedTouches[0].clientX);
let clientY = e.clientY || (e.touches[0] ? e.touches[0].clientY : e.changedTouches[0].clientY);
return new mapboxgl.Point(
clientX - rect.left - canvas.clientLeft,
clientY - rect.top - canvas.clientTop
);
}
function mouseDown(e) {
// Continue the rest of the function if selection or deselction is toggled on, through keypress or icon
if (!(selectionButtonOn || deselectionButtonOn)) return;
// Call functions for the following events
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('touchmove', onTouchMove, { passive: false });
document.addEventListener('mouseup', onMouseUp);
document.addEventListener('touchend', onMouseUp);
document.addEventListener('keydown', onKeyDown);
// Capture the first xy coordinates
start = mousePos(e);
}
function onTouchMove(e) {
e.preventDefault();
onMouseMove(e);
}
function onMouseMove(e) {
// Capture the ongoing xy coordinates
current = mousePos(e);
// Append the box element if it doesnt exist
if (!box) {
box = document.createElement('div');
box.classList.add('boxdraw');
canvas.appendChild(box);
}
var minX = Math.min(start.x, current.x),
maxX = Math.max(start.x, current.x),
minY = Math.min(start.y, current.y),
maxY = Math.max(start.y, current.y);
// Adjust box style based on selection/deselection
if (selectionButtonOn) {
box.style.background = 'rgba(6, 134, 34, 0.1)';
box.style.border = '2px solid #05a305';
} else if (deselectionButtonOn) {
box.style.background = 'rgba(134, 6, 34, 0.1)';
box.style.border = '2px solid rgb(134, 6, 34)';
}
// Adjust width and xy position of the box element ongoing
var pos = 'translate(' + minX + 'px,' + minY + 'px)';
box.style.transform = pos;
box.style.WebkitTransform = pos;
box.style.width = maxX - minX + 'px';
box.style.height = maxY - minY + 'px';
}
function onMouseUp(e) {
let mode = selectionButtonOn ? "select" : "deselect";
// Capture xy coordinates
finish([start, mousePos(e)], mode);
// Reset Button Toggles
selectionButtonOn = false;
deselectionButtonOn = false;
// Reset Map Style
canvas.style.cursor = 'grab';
}
function onKeyDown(e) {
// If the ESC key is pressed
if (e.keyCode === 27) finish();
}
function finish(bbox, mode) {
// Remove these events now that finish has been called.
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('touchmove', onTouchMove, { passive: false });
document.removeEventListener('keydown', onKeyDown);
document.removeEventListener('mouseup', onMouseUp);
document.removeEventListener('touchend', onMouseUp);
if (box) {
box.parentNode.removeChild(box);
box = null;
}
// If bbox exists. use this value as the argument for `queryRenderedFeatures`
if (bbox) {
var features = map.queryRenderedFeatures(bbox, { layers: ['postal'] });
// if (features.length >= 1000) {
// return window.alert('Select a smaller number of features');
// }
// Run through the selected features and set a filter
// to match features with unique FIPS codes to activate
// the `counties-highlighted` layer.
if (mode === 'select') {
features.map(function (feature) {
selectedPostalCodes.push(feature.properties.id);
});
} else if (mode === 'deselect') {
selectedPostalCodes = selectedPostalCodes.filter((code) => !features.map(f => f.properties.id).includes(code));
}
map.setFilter("postal-highlighted", ["in",
"id",
...selectedPostalCodes]);
}
map.dragPan.enable();
}
map.on('mousemove', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['postal'] });
if (!features.length) {
popup.remove();
return;
}
var feature = features[0];
// popup.setLngLat(e.lngLat)
// .setText(feature.properties.id.slice(4))
// .addTo(map);
});
document.getElementById('selection').addEventListener('click', function () {
selectionButtonOn = true;
deselectionButtonOn = false;
canvas.style.cursor = 'crosshair';
map.dragPan.disable();
});
document.getElementById('deselection').addEventListener('click', function () {
selectionButtonOn = false;
deselectionButtonOn = true;
canvas.style.cursor = 'crosshair';
map.dragPan.disable();
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment