let map = null; let mapImg = null; let tokens = []; const worldBounds = [[180, -180],[-180, 180]]; function initializeMap(mapImgUrl) { let init = false; if (!map) { init = true; map = L.map('map', { minZoom: 0, maxZoom: 4, crs: L.CRS.Simple }); map.on("zoomend", ()=>{resizeMarkers();scaleSpritePreview();}); } if (mapImg) { mapImg.removeFrom(map); } mapImg = L.imageOverlay(mapImgUrl, worldBounds); mapImg.addTo(map); map.setMaxBounds(worldBounds); if (init) { map.setView([0,0], 2); } /* */ } // this works but assumes the map is square (reasonable limitation I think) function resizeMarkers() { tokens.forEach(t=>{ const icon = t.m.options.icon; const scaleFactor = mapImg._image.clientWidth / mapImg._image.naturalWidth; icon.options.iconSize = [scaleFactor * t.t.w, scaleFactor * t.t.h]; icon.options.iconAnchor = [scaleFactor * t.t.oX, scaleFactor * t.t.oY]; t.m.setIcon(icon); }); } function processTokens(tokenChanges) { for (const t of tokenChanges) { const i = tokens.findIndex(tk=>tk.t.id == t.id); if (i >= 0) { const self = tokens[i]; // token was made active if (t.x != null && t.y != null && !self.t.active && t.active) { self.t.active = true; self.m.addTo(map); // token was made inactive } else if (t.x != null && t.y != null && self.t.active && !t.active) { self.t.active = false; self.m.removeFrom(map); // token was destroyed } else if (t.x == null && t.y == null) { self.m.removeFrom(map); tokens.splice(i, 1); // token was moved } else { self.t.x = t.x; self.t.y = t.y; self.m.setLatLng([t.y, t.x]); } } else { if (t.x != null && t.y != null) { const self = NewToken(t); tokens.push(self); if (t.active) { self.m.addTo(map); } } } } resizeMarkers(); } function toggleActive(tokenId) { const existing = tokens.find(t=>t.t.id == tokenId); if (existing) { const self = Object.assign({}, existing.t); self.active = !self.active; console.log(self); publish({token: self}); } } function getCascadingPos() { const topLeft = [0,0]; const n = tokens.length; topLeft[1] += (n)*Math.random()*10 - 5; topLeft[0] -= (n)*Math.random()*10 - 5; return topLeft; } function moveToken(id) { const existing = tokens.find(t=>t.t.id == id); if (existing) { const self = Object.assign({}, existing.t); const realPos = existing.m.getLatLng(); self.x = realPos.lng; self.y = realPos.lat; console.log(self); publish({token: self}); } } function NewToken(token) { const marker = L.marker([token.y,token.x], { icon: L.icon({ iconUrl: token.sprite, iconSize: [token.w,token.h], iconAnchor: [token.oX, token.oY] }), title: token.name, draggable: true, autoPan: true }); marker.on("moveend", ()=>{moveToken(token.id)}); return { t: token, m: marker, }; } function addToken(token) { const self = { sz: token.sz, m: L.marker(token.pos, { icon: L.icon({ iconUrl: token.img, iconSize: token.sz, }), title: token.name, draggable: true, autoPan: true })}; tokens.push(self); self.m.addTo(map); } // token for testing in browser console const t = { img: "https://nilfm.cc/favicon.png", sz: [32,32], pos: [0,0], name: "test", }