|
| 1 | +import L from "leaflet"; |
| 2 | +import { S } from "./Squaremap.js"; |
| 3 | + |
| 4 | +export const FogOfWar = L.Layer.extend({ |
| 5 | + onAdd: function (map) { |
| 6 | + this._map = map; |
| 7 | + this._canvas = L.DomUtil.create("canvas", "leaflet-fog-of-war"); |
| 8 | + this._canvas.style.position = "absolute"; |
| 9 | + this._canvas.style.top = "0"; |
| 10 | + this._canvas.style.left = "0"; |
| 11 | + this._canvas.style.pointerEvents = "none"; |
| 12 | + this._canvas.style.zIndex = "400"; |
| 13 | + |
| 14 | + const pane = map.getPane("overlayPane"); |
| 15 | + pane.appendChild(this._canvas); |
| 16 | + |
| 17 | + this._ctx = this._canvas.getContext("2d"); |
| 18 | + |
| 19 | + map.on("moveend resize zoomend", this._update, this); |
| 20 | + map.on("viewreset", this._update, this); |
| 21 | + |
| 22 | + this._update(); |
| 23 | + }, |
| 24 | + |
| 25 | + onRemove: function (map) { |
| 26 | + L.DomUtil.remove(this._canvas); |
| 27 | + map.off("moveend resize zoomend viewreset", this._update, this); |
| 28 | + }, |
| 29 | + |
| 30 | + _update: function () { |
| 31 | + if (!this._map || !S.playerList) return; |
| 32 | + |
| 33 | + const size = this._map.getSize(); |
| 34 | + this._canvas.width = size.x; |
| 35 | + this._canvas.height = size.y; |
| 36 | + this._canvas.style.width = size.x + "px"; |
| 37 | + this._canvas.style.height = size.y + "px"; |
| 38 | + |
| 39 | + this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height); |
| 40 | + |
| 41 | + // Fill entire canvas with dark overlay |
| 42 | + this._ctx.fillStyle = "rgba(0, 0, 0, 0.85)"; |
| 43 | + this._ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); |
| 44 | + |
| 45 | + // Clear circles around each player (flashlight effect) |
| 46 | + this._ctx.globalCompositeOperation = "destination-out"; |
| 47 | + |
| 48 | + const radius = 80; // pixels - adjust for flashlight size |
| 49 | + |
| 50 | + if (S.playerList.markers) { |
| 51 | + S.playerList.markers.forEach((marker, uuid) => { |
| 52 | + const player = S.playerList.players.get(uuid); |
| 53 | + if (!player) return; |
| 54 | + |
| 55 | + const pos = this._map.latLngToContainerPoint(marker.getLatLng()); |
| 56 | + |
| 57 | + // Create radial gradient for soft edge |
| 58 | + const gradient = this._ctx.createRadialGradient(pos.x, pos.y, radius * 0.3, pos.x, pos.y, radius); |
| 59 | + gradient.addColorStop(0, "rgba(0, 0, 0, 1)"); |
| 60 | + gradient.addColorStop(1, "rgba(0, 0, 0, 0)"); |
| 61 | + |
| 62 | + this._ctx.fillStyle = gradient; |
| 63 | + this._ctx.beginPath(); |
| 64 | + this._ctx.arc(pos.x, pos.y, radius, 0, Math.PI * 2); |
| 65 | + this._ctx.fill(); |
| 66 | + }); |
| 67 | + } |
| 68 | + |
| 69 | + this._ctx.globalCompositeOperation = "source-over"; |
| 70 | + }, |
| 71 | +}); |
| 72 | + |
| 73 | +export function fogOfWar() { |
| 74 | + return new FogOfWar(); |
| 75 | +} |
0 commit comments