import * as MaplibreGL from 'https://cdn.skypack.dev/maplibre-gl?min'; import * as Diplomat from 'https://cdn.skypack.dev/@americana/diplomat?min'; import * as PMTiles from 'https://cdn.skypack.dev/pmtiles?min'; import * as D3 from 'https://cdn.skypack.dev/d3?min'; import turf from 'https://cdn.skypack.dev/turf?min'; // local imports import { CustomControl, } from './controls.js'; // add the PMTiles plugin to the maplibregl global. const pmproto = new PMTiles.Protocol(); MaplibreGL.addProtocol('pmtiles', pmproto.tile); // globals export const map = initMap(); export const urlState = initUrlState(); function initUrlState() { const params = new URLSearchParams(window.location.search); if (params.has('show')) { const show = params.get('show'); const vals = show.split(','); if (vals.includes('japan')) { loadJapan(); } } return params; } function initMap() { const map = new MaplibreGL.Map({ container: 'map', style: 'https://tiles.openfreemap.org/styles/positron', }); // overwrite basemap style const style = D3.json('https://tiles.openfreemap.org/styles/positron') style.then((data) => { data.layers = data.layers.map((l) => { if (l.id === "boundary_2") { l.paint["line-color"] = "red"; } if (l.id === "boundary_3") { l.minzoom = 4; l.paint["line-color"] = "orange"; } if (l.id === "label_state") { l.minzoom = 4; l.paint["text-color"] = "orange"; } if (l.id === "label_other") { l.minzoom = 4; l.paint["text-color"] = "orange"; } return l; }); map.setStyle(data); }); map.addControl(new MaplibreGL.FullscreenControl()); map.addControl(new MaplibreGL.NavigationControl({ showZoom: true, showCompass: true, visualizeRoll: true, visualizePitch: true, })); map.addControl(new MaplibreGL.GlobeControl()); map.addControl(new MaplibreGL.GeolocateControl({ positionOptions: { enableHighAccuracy: true }, })); map.addControl(new CustomControl({ label: 'Japan', icon: '🇯🇵', onclick: () => { loadJapan(); }, })); map.addControl(new CustomControl({ label: 'Raw', icon: 'R', onclick: () => { loadRaw(); }, })); map.addControl(new CustomControl({ label: 'Visited', icon: 'V', onclick: () => { loadVisited(); }, })); // https://github.com/osm-americana/diplomat/ map.once("styledata", (event) => { Diplomat.localizeStyle(map); }); return map; } function loadRaw() { const raw = D3.json('export-data/data.geojson'); raw.then((data) => { if (map.getSource('raw') === undefined) { map.addSource('raw', { type: 'geojson', data: data, }); map.addLayer({ id: 'raw', source: 'raw', type: 'heatmap', paint: { // Increase the heatmap weight based on frequency and property magnitude 'heatmap-weight': [ 'interpolate', ['linear'], ['get', 'mag'], 0, 0, 6, 1 ], // Increase the heatmap color weight weight by zoom level // heatmap-intensity is a multiplier on top of heatmap-weight 'heatmap-intensity': [ 'interpolate', ['linear'], ['zoom'], 0, 1, 9, 3 ], // Color ramp for heatmap. Domain is 0 (low) to 1 (high). // Begin color ramp at 0-stop with a 0-transparency color // to create a blur-like effect. '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)' ], // Adjust the heatmap radius by zoom level 'heatmap-radius': [ 'interpolate', ['linear'], ['zoom'], 0, 2, 9, 20 ], }, }); } map.fitBounds(turf.bbox(data), { padding: 50, }); }) } function loadVisited() { // add data const vis = D3.json('export-data/visited.geojson'); vis.then((data) => { if (map.getSource('visited') === undefined) { map.addSource('visited', { type: 'geojson', data: data, }); // boundaries map.addLayer({ id: 'visited-bounds', type: 'fill', source: 'visited', layout: {}, paint: { 'fill-color': 'hotpink', 'fill-opacity': 0.6, }, filter: ['==', '$type', 'Polygon'], }); // labels map.addLayer({ id: 'visited-labels', type: 'symbol', source: 'visited', layout: { 'text-field': '{iso3166}\n{timestamp}', 'text-font': ['Noto Sans Regular'], 'text-size': 12, 'text-variable-anchor': ['top', 'bottom', 'left', 'right'], 'text-radial-offset': 0.3, 'text-justify': 'auto', }, paint: { 'text-color': 'black', 'text-opacity': 1.0, }, filter: ['==', '$type', 'Polygon'], }); } map.fitBounds(turf.bbox(data), { padding: 50, }); }); } function loadJapan() { function normalizeLocation() { let addr = window.location.toString(); let idx = addr.lastIndexOf("/"); return addr.slice(0, idx); } const jpn_url = 'export-data/japan-admin_level=4.pmtiles' const jpn = new PMTiles.PMTiles(jpn_url); pmproto.add(jpn); jpn.getHeader().then(hdr => { map.fitBounds([[hdr.minLon, hdr.minLat],[hdr.maxLon, hdr.maxLat]], { padding: 1, }); // map.addSource('jpn', { // type: 'vector', // url: `pmtiles://${normalizeLocation()}/${jpn_url}`, // attribution: '© OSM-Boundaries' // }); // map.addLayer({ // id: 'jpn-bounds', // source: 'jpn', // 'source-layer': 'japan-bounds', // type: 'line', // layout: {}, // paint: { // 'line-color': 'orange', // 'line-width': 2, // 'line-opacity': 0.5, // }, // }); // map.addLayer({ // id: 'jpn-labels', // source: 'jpn', // 'source-layer': 'japan-labels', // type: 'symbol', // layout: { // 'text-field': '{name_en}', // 'text-font': ['Noto Sans Regular'], // 'text-size': 12, // 'text-variable-anchor': ['top', 'bottom', 'left', 'right'], // 'text-radial-offset': 0.2, // 'text-justify': 'auto', // }, // paint: { // 'text-color': 'black', // 'text-opacity': 1.0, // }, // }); }); }