Public
Edited
Apr 26, 2023
1 star
Insert cell
Insert cell
Insert cell
concentricCircles = [15, 30, 45, 60, 75, 90, 105, 120].map(m => m * (tuning||1) * 100) //100 is a magic constant to match with lines
Insert cell
Insert cell
data = [
{id: "hornstull", origin: [18.034721, 59.315417], time: 15, satisfaction: 0.9, type: "dorm"},
{id: "sollentuna", origin: [17.950187, 59.426650], time: 45, satisfaction: 0.5, type: "homestay"},
{id: "south", origin: [18.252459, 59.247726], time: 60, satisfaction: 0.2, type: "homestay"},
{id: "årsta", origin: [18.063085, 59.301675], time: 60, satisfaction: 0.6, type: "dorm"},
]
Insert cell
Insert cell
lines = data.map(m => makeLine(dis, m.origin, m.time))
Insert cell
makeLine = function(center, origin, k = 1) {
const diff = vector.substract(origin, center);
const normalised = vector.normalise(diff);
const scaled = vector.multiply(normalised, k * (tuning||1) / 100000); //magic constant to match with concentric circles
return [origin, vector.add(center, scaled)]
}

Insert cell
Insert cell
vector = {
const add = (a,b) => [a[0] + b[0], a[1] + b[1]];
const substract = (a,b) => [a[0] - b[0], a[1] - b[1]];
const multiply = (a, k) => [a[0] * k, a[1] * k];
const divide = (a, k) => [a[0] / k, a[1] / k];
const length = (a) => Math.sqrt(Math.pow(a[0]/180, 2) + Math.pow(a[1]/90, 2)); //lng goes up to 180, lat goes up to 90
const normalise = (a) => divide(a, length(a) || 1);
return {add, substract, divide, multiply, length, normalise};
}


Insert cell
Insert cell
geojson = ({
'type': 'FeatureCollection',
'features': lines.map(coordinates => ({
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'LineString',
'coordinates': coordinates
}
}))
})
Insert cell
Insert cell
Insert cell
{
// Create space for a map
let container = html`<div style='height:800px;' />`;

yield container;

// Creates map from Mapbox
let map = new mapboxgl.Map({
container,
// Coordinates of DIS
center: [18.081271, 59.343769],
// Starting zoom
zoom: 10,
// Choose from different Mapbox styles like light, dark, or I chose light version 11
style: "mapbox://styles/mapbox/light-v11"
});


map.on('load', () => {
map.addSource('line', {
type: 'geojson',
lineMetrics: true,
data: geojson
});

// following this tutorial: https://docs.mapbox.com/mapbox-gl-js/example/line-gradient/
// the layer must be of type 'line'
map.addLayer({
type: 'line',
source: 'line',
id: 'line',
paint: {
'line-color': 'red',
'line-width': 5
},
layout: {
'line-cap': 'round',
'line-join': 'round'
}
});

concentricCircles.forEach(r => {
new circle(dis, r, {
editable: false,
minRadius: 1,
fillColor: "transparent",
strokeColor: "#888"
}).addTo(map);
})

data.forEach(d => {
new circle(d.origin, Math.sqrt(circleSize(d.satisfaction)), {
editable: false,
minRadius: 1,
fillColor: colors(d.type)
}).addTo(map);
})
});

}
Insert cell
circleSize = d3.scaleLinear().domain([0,1]).range([0,1000000])
Insert cell
colors = d3.scaleOrdinal().range(d3.schemeCategory10)
Insert cell
Insert cell
Insert cell
mapboxgl = {
const gl = await require("mapbox-gl@v2.13.0");
if (!gl.accessToken) {
gl.accessToken = "pk.eyJ1IjoiZGlzc3RvY2tob2xtIiwiYSI6ImNsYXB4ZDBsODFjeGYzcHF2bDd5dmtuajQifQ.aqSUxGoF8DkpeJyEx3diOg";
const href = await require.resolve("mapbox-gl@v2.13.0/dist/mapbox-gl.css");
document.head.appendChild(html`<link href=${href} rel=stylesheet>`);
}
return gl;
}
Insert cell
circle = require("https://npmcdn.com/mapbox-gl-circle/dist/mapbox-gl-circle.min.js");
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