camper/web/static/map.js

132 lines
4.2 KiB
JavaScript

(function () {
'use strict';
const container = document.getElementById('campground_map');
container.style.height = '80vh';
const svg = container.childNodes[0];
svg.remove();
const latLngBounds = L.latLngBounds([[0, 0], [1192, 1500]]);
const map = L.map(container, {
center: latLngBounds.getCenter(),
minZoom: -2,
maxZoom: 2,
zoom: -1,
scrollWheelZoom: false,
maxBounds: latLngBounds,
maxBoundsViscosity: 1.0,
zoomSnap: 0,
crs: L.CRS.Simple,
});
map.fitBounds(latLngBounds);
L.svgOverlay(svg, latLngBounds).addTo(map);
// from https://github.com/jkroso/parse-svg-path/
const parse = (function () {
'use strict';
const length = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}
const segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig;
const number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig;
function parseValues(args) {
const numbers = args.match(number)
return numbers ? numbers.map(Number) : []
}
return function (path) {
const data = []
path.replace(segment, function (_, command, args) {
let type = command.toLowerCase()
args = parseValues(args)
// overloaded moveTo
if (type === 'm' && args.length > 2) {
data.push([command].concat(args.splice(0, 2)))
type = 'l'
command = command === 'm' ? 'l' : 'L'
}
while (true) {
if (args.length === length[type]) {
args.unshift(command)
return data.push(args)
}
if (args.length < length[type]) throw new Error('malformed path data')
data.push([command].concat(args.splice(0, length[type])))
}
})
return data
}
})();
function highlightAccommodation(e) {
const layer = e.target;
layer.setStyle({
color: '#ffe673',
});
layer.bringToFront();
}
function resetHighlight(e) {
const layer = e.target;
layer.setStyle({
color: 'transparent',
});
}
// XXX: this is from the “parceles” layer.
const ctm = [1, 0, 0, 1, 83.2784, 66.1766];
const transform = function (x, y) {
return [ctm[0] * x + ctm[2] * y + ctm[4], ctm[1] * x + ctm[3] * y + ctm[5]];
}
const language = document.documentElement.getAttribute('lang');
const prefix = 'cp_';
for (const campsite of Array.from(container.querySelectorAll(`[id^="${prefix}"]`))) {
const label = campsite.id.substring(prefix.length);
if (!label) {
continue;
}
const path = campsite.firstElementChild;
const commands = parse(path.getAttribute('d'));
const points = [];
const p0 = [0, 0];
for (const cmd of commands) {
switch (cmd[0]) {
case 'M':
case 'L':
const cmdM = transform(cmd[1], cmd[2]);
p0[0] = cmdM[0];
p0[1] = latLngBounds.getNorth() - cmdM[1];
break;
case 'm':
case 'l':
p0[0] += cmd[1];
p0[1] -= cmd[2];
break;
case 'C':
const cmdC = transform(cmd[5], cmd[6]);
p0[0] = cmdC[0];
p0[1] = latLngBounds.getNorth() - cmdC[1];
break;
case 'Z':
case 'z':
continue;
default:
console.error(cmd);
}
points.push([p0[1], p0[0]]);
}
const accommodation = L.polygon(points, {color: 'transparent'}).addTo(map);
accommodation.on({
mouseover: highlightAccommodation,
mouseout: resetHighlight,
click: function () {
window.location = `/${language}/campsites/${label}`;
},
})
}
})();