Published
Edited
Jan 22, 2019
27 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
clipGeometry = {
const {centerPoint, width, height} = dimensions;
const {portionVisible, aToB } = positionedMap

const divider = aToB.perp().unit().mult(-1);
const centerToVerticalEdge = divider.mult((width / 2) / Math.abs(divider.x));
const centerToHorizontalEdge = divider.mult((height / 2) / Math.abs(divider.y));

const tl = new mapboxgl.Point(0, 0);
const tr = new mapboxgl.Point(width, 0);
const bl = new mapboxgl.Point(0, height);
const br = new mapboxgl.Point(width, height);

if (portionVisible === 1) {
// Both dots fit on one map. Clip the entire map.
return [tl];
} else if (centerToVerticalEdge.mag() < centerToHorizontalEdge.mag()) {
const intersection0 = centerPoint.sub(centerToVerticalEdge);
const intersection1 = centerPoint.add(centerToVerticalEdge);
if (centerToVerticalEdge.x < 0) {
// line intersects left edge
return [intersection0, intersection1, tl, tr];
} else {
// line intersects right edge
return [intersection0, intersection1, br, bl];
}
} else {
const intersection0 = centerPoint.sub(centerToHorizontalEdge);
const intersection1 = centerPoint.add(centerToHorizontalEdge);
if (centerToHorizontalEdge.y < 0) {
// line intersects top edge
return [intersection0, intersection1, tr, br];
} else {
// line intersects bottom edge
return [intersection0, intersection1, bl, tl];
}
}
}
Insert cell
positionedMap = {
map1.setZoom(zoom);
map2.setZoom(zoom);
const {width, height} = dimensions;

const pA = map1.project(locationA);
const pB = map1.project(locationB);
const aToB = pB.sub(pA);

const paddingX = width / 4;
const paddingY = height / 4;
const maxX = width - 2 * paddingX;
const maxY = height - 2 * paddingY;

let portionVisible = Math.min(Math.abs(maxX / aToB.x), Math.abs(maxY / aToB.y), 1);
const pointToCenter = aToB.mult(portionVisible * 0.5);

map2.setCenter(map1.unproject(pB.sub(pointToCenter)));
map1.setCenter(map1.unproject(pA.add(pointToCenter)));
return {portionVisible, aToB};
}
Insert cell
Insert cell
Insert cell
markerGeojson = {
const markerGeojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": locationA.toArray()
}
}, {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": locationB.toArray()
}
}]
};
map1.getSource('locations').setData(markerGeojson);
map2.getSource('locations').setData(markerGeojson);
return markerGeojson;
}
Insert cell
Insert cell
Insert cell
Insert cell
loadMap = function(container) {
return new Promise((resolve, reject) => {
const map = new mapboxgl.Map({
container: container,
zoom: initialZoom,
center: [-79.45259500000701,43.64158592543481],
interactive: false,
style: 'mapbox://styles/mapbox/light-v9',
});
invalidation.then(() => map.remove());
map.on('load', () => {
map.addSource("locations", {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": []
}
});

map.addLayer({
"id": "dots",
"type": "circle",
"source": "locations",
"paint": {
"circle-radius": 10,
"circle-stroke-width": 2,
"circle-stroke-color": map.getPaintProperty('background', 'background-color')
}
});
resolve(map);
});
});
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
html`<style>
#maps {
position: relative;
width: 100%;
height: 500px;
}
#map1, #map2, #line {
position: absolute;
height: 100%;
width: 100%;
}
line {
stroke: black;
}
</style>`
Insert cell
Insert cell
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