Files
traque/traque-front/hook/mapDrawing.jsx
2024-06-06 23:55:36 +02:00

126 lines
4.3 KiB
JavaScript

import { TileNumber, latLngToTileNumber } from "@/components/util/map";
import { useEffect, useState } from "react";
import { useLeafletContext } from '@react-leaflet/core';
import L from 'leaflet';
export function useMapCircleDraw(area, setArea) {
const [drawing, setDrawing] = useState(false);
const [center, setCenter] = useState(area?.center || null);
const [radius, setRadius] = useState(area?.radius || null);
useEffect(() => {
setDrawing(false);
setCenter(area?.center || null);
setRadius(area?.radius || null);
}, [area])
function handleClick(e) {
if (!drawing) {
setCenter(e.latlng);
setRadius(null);
setDrawing(true);
} else {
setDrawing(false);
setArea({ center, radius });
}
}
function handleMouseMove(e) {
if (drawing) {
setRadius(e.latlng.distanceTo(center));
}
}
return {
handleClick,
handleMouseMove,
center,
radius,
}
}
export function useMapGrid(tilesColor, tileSize) {
const { layerContainer, map } = useLeafletContext();
const [grid, setGrid] = useState(null);
const Grid = L.GridLayer.extend({
createTile: function (coords) {
const tile = L.DomUtil.create('canvas', 'leaflet-tile');
const ctx = tile.getContext('2d');
const size = this.getTileSize();
tile.width = size.x
tile.height = size.y
// calculate projection coordinates of top left tile pixel
const nwPoint = coords.scaleBy(size);
// calculate geographic coordinates of top left tile pixel
const nw = map.unproject(nwPoint, coords.z);
// calculate fraction tile number at top left point
const nwTile = latLngToTileNumber(nw, tileSize)
// calculate projection coordinates of bottom right tile pixel
const sePoint = new L.Point(nwPoint.x + size.x - 1, nwPoint.y + size.y - 1)
// calculate geographic coordinates of bottom right tile pixel
const se = map.unproject(sePoint, coords.z);
// calculate fractional tile number at bottom right point
const seTile = latLngToTileNumber(se, tileSize)
const minTileX = nwTile.x
const maxTileX = seTile.x
const minTileY = nwTile.y
const maxTileY = seTile.y
for (let x = Math.ceil(minTileX) - 1; x <= Math.floor(maxTileX) + 1; x++) {
for (let y = Math.ceil(minTileY) - 1; y <= Math.floor(maxTileY) + 1; y++) {
let tile = new TileNumber(x, y)
const xMinPixel = Math.round(size.x * (x - minTileX) / (maxTileX - minTileX));
const xMaxPixel = Math.round(size.x * (x + 1 - minTileX) / (maxTileX - minTileX));
const yMinPixel = Math.round(size.y * (y - minTileY) / (maxTileY - minTileY));
const yMaxPixel = Math.round(size.y * (y + 1 - minTileY) / (maxTileY - minTileY));
if (this.tilesColor?.some(t => t.x == tile.x && t.y == tile.y)) {
ctx.fillStyle = this.tilesColor.find(t => t.x == tile.x && t.y == tile.y).color;
}
else {
ctx.fillStyle = 'rgba(255, 255, 255, 0)';
}
ctx.fillRect(xMinPixel, yMinPixel, xMaxPixel - xMinPixel, yMaxPixel - yMinPixel);
}
}
return tile;
},
});
useEffect(() => {
let g = new Grid({
minZoom: 12,
});
setGrid(g);
layerContainer.addLayer(g);
}, [])
useEffect(() => {
if (grid) {
grid.tilesColor = tilesColor;
grid.redraw();
}
}, [tilesColor,grid]);
}
export function useTilesColor(zone) {
const [tilesColor, setTilesColor] = useState([]);
useEffect(() => {
if (zone) {
setTilesColor(zone.map(t => {
if(t.removeDate == null) {
return { x: t.x, y: t.y, color: 'rgba(0, 0, 255, 0.3'}
}else {
return { x: t.x, y: t.y, color: 'rgba(255, 255, 0, 0.3'}
}
}));
}
}, [zone]);
return tilesColor;
}