mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
Merge pull request #667 from Freika/fix/map-performance-improvement-with-canvas
Improve map performance with canvas rendering
This commit is contained in:
commit
b75b8670af
10 changed files with 209 additions and 98 deletions
|
|
@ -1 +1 @@
|
||||||
0.22.2
|
0.22.3
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
# 0.22.3 - 2025-01-14
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- The Map now uses a canvas to draw polylines, points and fog of war. This should improve performance in browser with a lot of points and polylines.
|
||||||
|
|
||||||
# 0.22.2 - 2025-01-13
|
# 0.22.2 - 2025-01-13
|
||||||
|
|
||||||
✨ The Fancy Routes release ✨
|
✨ The Fancy Routes release ✨
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,21 +0,0 @@
|
||||||
/* Ensure fog overlay is positioned relative to the map container */
|
|
||||||
#fog {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.8); /* Adjust the opacity here */
|
|
||||||
pointer-events: none;
|
|
||||||
mix-blend-mode: multiply;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unfogged-circle {
|
|
||||||
position: absolute;
|
|
||||||
pointer-events: none;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: white;
|
|
||||||
mix-blend-mode: destination-out;
|
|
||||||
filter: blur(3px); /* Apply no blur to the circles */
|
|
||||||
}
|
|
||||||
|
|
@ -17,6 +17,6 @@ class Api::V1::Countries::VisitedCitiesController < ApiController
|
||||||
private
|
private
|
||||||
|
|
||||||
def required_params
|
def required_params
|
||||||
%i[start_at end_at]
|
%i[start_at end_at api_key]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -16,33 +16,23 @@ import {
|
||||||
import { fetchAndDrawAreas } from "../maps/areas";
|
import { fetchAndDrawAreas } from "../maps/areas";
|
||||||
import { handleAreaCreated } from "../maps/areas";
|
import { handleAreaCreated } from "../maps/areas";
|
||||||
|
|
||||||
import { showFlashMessage } from "../maps/helpers";
|
import { showFlashMessage, fetchAndDisplayPhotos, debounce } from "../maps/helpers";
|
||||||
import { fetchAndDisplayPhotos } from '../maps/helpers';
|
|
||||||
|
|
||||||
import { osmMapLayer } from "../maps/layers";
|
import {
|
||||||
import { osmHotMapLayer } from "../maps/layers";
|
osmMapLayer,
|
||||||
import { OPNVMapLayer } from "../maps/layers";
|
osmHotMapLayer,
|
||||||
import { openTopoMapLayer } from "../maps/layers";
|
OPNVMapLayer,
|
||||||
import { cyclOsmMapLayer } from "../maps/layers";
|
openTopoMapLayer,
|
||||||
import { esriWorldStreetMapLayer } from "../maps/layers";
|
cyclOsmMapLayer,
|
||||||
import { esriWorldTopoMapLayer } from "../maps/layers";
|
esriWorldStreetMapLayer,
|
||||||
import { esriWorldImageryMapLayer } from "../maps/layers";
|
esriWorldTopoMapLayer,
|
||||||
import { esriWorldGrayCanvasMapLayer } from "../maps/layers";
|
esriWorldImageryMapLayer,
|
||||||
|
esriWorldGrayCanvasMapLayer
|
||||||
|
} from "../maps/layers";
|
||||||
import { countryCodesMap } from "../maps/country_codes";
|
import { countryCodesMap } from "../maps/country_codes";
|
||||||
|
|
||||||
import "leaflet-draw";
|
import "leaflet-draw";
|
||||||
|
import { initializeFogCanvas, drawFogCanvas, createFogOverlay } from "../maps/fog_of_war";
|
||||||
function debounce(func, wait) {
|
|
||||||
let timeout;
|
|
||||||
return function executedFunction(...args) {
|
|
||||||
const later = () => {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
func(...args);
|
|
||||||
};
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(later, wait);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ["container"];
|
static targets = ["container"];
|
||||||
|
|
@ -84,7 +74,10 @@ export default class extends Controller {
|
||||||
|
|
||||||
this.polylinesLayer = createPolylinesLayer(this.markers, this.map, this.timezone, this.routeOpacity, this.userSettings, this.distanceUnit);
|
this.polylinesLayer = createPolylinesLayer(this.markers, this.map, this.timezone, this.routeOpacity, this.userSettings, this.distanceUnit);
|
||||||
this.heatmapLayer = L.heatLayer(this.heatmapMarkers, { radius: 20 }).addTo(this.map);
|
this.heatmapLayer = L.heatLayer(this.heatmapMarkers, { radius: 20 }).addTo(this.map);
|
||||||
this.fogOverlay = L.layerGroup(); // Initialize fog layer
|
|
||||||
|
// Create a proper Leaflet layer for fog
|
||||||
|
this.fogOverlay = createFogOverlay();
|
||||||
|
|
||||||
this.areasLayer = L.layerGroup(); // Initialize areas layer
|
this.areasLayer = L.layerGroup(); // Initialize areas layer
|
||||||
this.photoMarkers = L.layerGroup();
|
this.photoMarkers = L.layerGroup();
|
||||||
|
|
||||||
|
|
@ -94,11 +87,12 @@ export default class extends Controller {
|
||||||
this.addSettingsButton();
|
this.addSettingsButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize layers for the layer control
|
||||||
const controlsLayer = {
|
const controlsLayer = {
|
||||||
Points: this.markersLayer,
|
Points: this.markersLayer,
|
||||||
Routes: this.polylinesLayer,
|
Routes: this.polylinesLayer,
|
||||||
Heatmap: this.heatmapLayer,
|
Heatmap: this.heatmapLayer,
|
||||||
"Fog of War": this.fogOverlay,
|
"Fog of War": new this.fogOverlay(),
|
||||||
"Scratch map": this.scratchLayer,
|
"Scratch map": this.scratchLayer,
|
||||||
Areas: this.areasLayer,
|
Areas: this.areasLayer,
|
||||||
Photos: this.photoMarkers
|
Photos: this.photoMarkers
|
||||||
|
|
@ -131,6 +125,7 @@ export default class extends Controller {
|
||||||
maxWidth: 120
|
maxWidth: 120
|
||||||
}).addTo(this.map)
|
}).addTo(this.map)
|
||||||
|
|
||||||
|
// Initialize layer control
|
||||||
this.layerControl = L.control.layers(this.baseMaps(), controlsLayer).addTo(this.map);
|
this.layerControl = L.control.layers(this.baseMaps(), controlsLayer).addTo(this.map);
|
||||||
|
|
||||||
// Fetch and draw areas when the map is loaded
|
// Fetch and draw areas when the map is loaded
|
||||||
|
|
@ -230,6 +225,19 @@ export default class extends Controller {
|
||||||
localStorage.setItem('mapPanelOpen', 'false');
|
localStorage.setItem('mapPanelOpen', 'false');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update event handlers
|
||||||
|
this.map.on('moveend', () => {
|
||||||
|
if (document.getElementById('fog')) {
|
||||||
|
this.updateFog(this.markers, this.clearFogRadius);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.map.on('zoomend', () => {
|
||||||
|
if (document.getElementById('fog')) {
|
||||||
|
this.updateFog(this.markers, this.clearFogRadius);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
|
|
@ -528,39 +536,11 @@ export default class extends Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFog(markers, clearFogRadius) {
|
updateFog(markers, clearFogRadius) {
|
||||||
var fog = document.getElementById('fog');
|
const fog = document.getElementById('fog');
|
||||||
fog.innerHTML = ''; // Clear previous circles
|
if (!fog) {
|
||||||
markers.forEach((point) => {
|
initializeFogCanvas(this.map);
|
||||||
const radiusInPixels = this.metersToPixels(this.map, clearFogRadius);
|
}
|
||||||
this.clearFog(point[0], point[1], radiusInPixels);
|
requestAnimationFrame(() => drawFogCanvas(this.map, markers, clearFogRadius));
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
metersToPixels(map, meters) {
|
|
||||||
const zoom = map.getZoom();
|
|
||||||
const latLng = map.getCenter(); // Get map center for correct projection
|
|
||||||
const metersPerPixel = this.getMetersPerPixel(latLng.lat, zoom);
|
|
||||||
return meters / metersPerPixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
getMetersPerPixel(latitude, zoom) {
|
|
||||||
const earthCircumference = 40075016.686; // Earth's circumference in meters
|
|
||||||
const metersPerPixel = earthCircumference * Math.cos(latitude * Math.PI / 180) / Math.pow(2, zoom + 8);
|
|
||||||
return metersPerPixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearFog(lat, lng, radius) {
|
|
||||||
var fog = document.getElementById('fog');
|
|
||||||
var point = this.map.latLngToContainerPoint([lat, lng]);
|
|
||||||
var size = radius * 2;
|
|
||||||
var circle = document.createElement('div');
|
|
||||||
circle.className = 'unfogged-circle';
|
|
||||||
circle.style.width = size + 'px';
|
|
||||||
circle.style.height = size + 'px';
|
|
||||||
circle.style.left = (point.x - radius) + 'px';
|
|
||||||
circle.style.top = (point.y - radius) + 'px';
|
|
||||||
circle.style.backdropFilter = 'blur(0px)'; // Remove blur for the circles
|
|
||||||
fog.appendChild(circle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeDrawControl() {
|
initializeDrawControl() {
|
||||||
|
|
@ -822,6 +802,17 @@ export default class extends Controller {
|
||||||
// Debounce the heavy operations
|
// Debounce the heavy operations
|
||||||
const updateLayers = debounce(() => {
|
const updateLayers = debounce(() => {
|
||||||
try {
|
try {
|
||||||
|
// Store current layer visibility states
|
||||||
|
const layerStates = {
|
||||||
|
Points: this.map.hasLayer(this.markersLayer),
|
||||||
|
Routes: this.map.hasLayer(this.polylinesLayer),
|
||||||
|
Heatmap: this.map.hasLayer(this.heatmapLayer),
|
||||||
|
"Fog of War": this.map.hasLayer(this.fogOverlay),
|
||||||
|
"Scratch map": this.map.hasLayer(this.scratchLayer),
|
||||||
|
Areas: this.map.hasLayer(this.areasLayer),
|
||||||
|
Photos: this.map.hasLayer(this.photoMarkers)
|
||||||
|
};
|
||||||
|
|
||||||
// Check if speed_colored_routes setting has changed
|
// Check if speed_colored_routes setting has changed
|
||||||
if (newSettings.speed_colored_routes !== this.userSettings.speed_colored_routes) {
|
if (newSettings.speed_colored_routes !== this.userSettings.speed_colored_routes) {
|
||||||
if (this.polylinesLayer) {
|
if (this.polylinesLayer) {
|
||||||
|
|
@ -845,19 +836,35 @@ export default class extends Controller {
|
||||||
this.routeOpacity = parseFloat(newSettings.route_opacity) || 0.6;
|
this.routeOpacity = parseFloat(newSettings.route_opacity) || 0.6;
|
||||||
this.clearFogRadius = parseInt(newSettings.fog_of_war_meters) || 50;
|
this.clearFogRadius = parseInt(newSettings.fog_of_war_meters) || 50;
|
||||||
|
|
||||||
// Update layer control
|
// Remove existing layer control
|
||||||
this.map.removeControl(this.layerControl);
|
if (this.layerControl) {
|
||||||
|
this.map.removeControl(this.layerControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new controls layer object with proper initialization
|
||||||
const controlsLayer = {
|
const controlsLayer = {
|
||||||
Points: this.markersLayer,
|
Points: this.markersLayer || L.layerGroup(),
|
||||||
Routes: this.polylinesLayer,
|
Routes: this.polylinesLayer || L.layerGroup(),
|
||||||
Heatmap: this.heatmapLayer,
|
Heatmap: this.heatmapLayer || L.heatLayer([]),
|
||||||
"Fog of War": this.fogOverlay,
|
"Fog of War": new this.fogOverlay(),
|
||||||
"Scratch map": this.scratchLayer,
|
"Scratch map": this.scratchLayer || L.layerGroup(),
|
||||||
Areas: this.areasLayer,
|
Areas: this.areasLayer || L.layerGroup(),
|
||||||
Photos: this.photoMarkers
|
Photos: this.photoMarkers || L.layerGroup()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add new layer control
|
||||||
this.layerControl = L.control.layers(this.baseMaps(), controlsLayer).addTo(this.map);
|
this.layerControl = L.control.layers(this.baseMaps(), controlsLayer).addTo(this.map);
|
||||||
|
|
||||||
|
// Restore layer visibility states
|
||||||
|
Object.entries(layerStates).forEach(([name, wasVisible]) => {
|
||||||
|
const layer = controlsLayer[name];
|
||||||
|
if (wasVisible && layer) {
|
||||||
|
layer.addTo(this.map);
|
||||||
|
} else if (layer && this.map.hasLayer(layer)) {
|
||||||
|
this.map.removeLayer(layer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating map settings:', error);
|
console.error('Error updating map settings:', error);
|
||||||
console.error(error.stack);
|
console.error(error.stack);
|
||||||
|
|
|
||||||
94
app/javascript/maps/fog_of_war.js
Normal file
94
app/javascript/maps/fog_of_war.js
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
export function initializeFogCanvas(map) {
|
||||||
|
// Remove existing fog canvas if it exists
|
||||||
|
const oldFog = document.getElementById('fog');
|
||||||
|
if (oldFog) oldFog.remove();
|
||||||
|
|
||||||
|
// Create new fog canvas
|
||||||
|
const fog = document.createElement('canvas');
|
||||||
|
fog.id = 'fog';
|
||||||
|
fog.style.position = 'absolute';
|
||||||
|
fog.style.top = '0';
|
||||||
|
fog.style.left = '0';
|
||||||
|
fog.style.pointerEvents = 'none';
|
||||||
|
fog.style.zIndex = '400';
|
||||||
|
|
||||||
|
// Set canvas size to match map container
|
||||||
|
const mapSize = map.getSize();
|
||||||
|
fog.width = mapSize.x;
|
||||||
|
fog.height = mapSize.y;
|
||||||
|
|
||||||
|
// Add canvas to map container
|
||||||
|
map.getContainer().appendChild(fog);
|
||||||
|
|
||||||
|
return fog;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function drawFogCanvas(map, markers, clearFogRadius) {
|
||||||
|
const fog = document.getElementById('fog');
|
||||||
|
if (!fog) return;
|
||||||
|
|
||||||
|
const ctx = fog.getContext('2d');
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
const size = map.getSize();
|
||||||
|
|
||||||
|
// Clear the canvas
|
||||||
|
ctx.clearRect(0, 0, size.x, size.y);
|
||||||
|
|
||||||
|
// Keep the light fog for unexplored areas
|
||||||
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
|
||||||
|
ctx.fillRect(0, 0, size.x, size.y);
|
||||||
|
|
||||||
|
// Set up for "cutting" holes
|
||||||
|
ctx.globalCompositeOperation = 'destination-out';
|
||||||
|
|
||||||
|
// Draw clear circles for each point
|
||||||
|
markers.forEach(point => {
|
||||||
|
const latLng = L.latLng(point[0], point[1]);
|
||||||
|
const pixelPoint = map.latLngToContainerPoint(latLng);
|
||||||
|
const radiusInPixels = metersToPixels(map, clearFogRadius);
|
||||||
|
|
||||||
|
// Make explored areas completely transparent
|
||||||
|
const gradient = ctx.createRadialGradient(
|
||||||
|
pixelPoint.x, pixelPoint.y, 0,
|
||||||
|
pixelPoint.x, pixelPoint.y, radiusInPixels
|
||||||
|
);
|
||||||
|
gradient.addColorStop(0, 'rgba(255, 255, 255, 1)'); // 100% transparent
|
||||||
|
gradient.addColorStop(0.85, 'rgba(255, 255, 255, 1)'); // Still 100% transparent
|
||||||
|
gradient.addColorStop(1, 'rgba(255, 255, 255, 0)'); // Fade to fog at edge
|
||||||
|
|
||||||
|
ctx.fillStyle = gradient;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(pixelPoint.x, pixelPoint.y, radiusInPixels, 0, Math.PI * 2);
|
||||||
|
ctx.fill();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset composite operation
|
||||||
|
ctx.globalCompositeOperation = 'source-over';
|
||||||
|
}
|
||||||
|
|
||||||
|
function metersToPixels(map, meters) {
|
||||||
|
const zoom = map.getZoom();
|
||||||
|
const latLng = map.getCenter();
|
||||||
|
const metersPerPixel = getMetersPerPixel(latLng.lat, zoom);
|
||||||
|
return meters / metersPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMetersPerPixel(latitude, zoom) {
|
||||||
|
const earthCircumference = 40075016.686;
|
||||||
|
return earthCircumference * Math.cos(latitude * Math.PI / 180) / Math.pow(2, zoom + 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createFogOverlay() {
|
||||||
|
return L.Layer.extend({
|
||||||
|
onAdd: (map) => {
|
||||||
|
initializeFogCanvas(map);
|
||||||
|
},
|
||||||
|
onRemove: (map) => {
|
||||||
|
const fog = document.getElementById('fog');
|
||||||
|
if (fog) {
|
||||||
|
fog.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -297,3 +297,15 @@ export function createPhotoMarker(photo, userSettings, photoMarkers, apiKey) {
|
||||||
|
|
||||||
photoMarkers.addLayer(marker);
|
photoMarkers.addLayer(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function debounce(func, wait) {
|
||||||
|
let timeout;
|
||||||
|
return function executedFunction(...args) {
|
||||||
|
const later = () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
func(...args);
|
||||||
|
};
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,19 @@
|
||||||
import { createPopupContent } from "./popups";
|
import { createPopupContent } from "./popups";
|
||||||
|
|
||||||
export function createMarkersArray(markersData, userSettings) {
|
export function createMarkersArray(markersData, userSettings) {
|
||||||
|
// Create a canvas renderer
|
||||||
|
const renderer = L.canvas({ padding: 0.5 });
|
||||||
|
|
||||||
if (userSettings.pointsRenderingMode === "simplified") {
|
if (userSettings.pointsRenderingMode === "simplified") {
|
||||||
return createSimplifiedMarkers(markersData);
|
return createSimplifiedMarkers(markersData, renderer);
|
||||||
} else {
|
} else {
|
||||||
return markersData.map((marker) => {
|
return markersData.map((marker) => {
|
||||||
const [lat, lon] = marker;
|
const [lat, lon] = marker;
|
||||||
|
|
||||||
const popupContent = createPopupContent(marker, userSettings.timezone, userSettings.distanceUnit);
|
const popupContent = createPopupContent(marker, userSettings.timezone, userSettings.distanceUnit);
|
||||||
let markerColor = marker[5] < 0 ? "orange" : "blue";
|
let markerColor = marker[5] < 0 ? "orange" : "blue";
|
||||||
|
|
||||||
return L.circleMarker([lat, lon], {
|
return L.circleMarker([lat, lon], {
|
||||||
|
renderer: renderer, // Use canvas renderer
|
||||||
radius: 4,
|
radius: 4,
|
||||||
color: markerColor,
|
color: markerColor,
|
||||||
zIndexOffset: 1000,
|
zIndexOffset: 1000,
|
||||||
|
|
@ -19,7 +23,7 @@ export function createMarkersArray(markersData, userSettings) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSimplifiedMarkers(markersData) {
|
export function createSimplifiedMarkers(markersData, renderer) {
|
||||||
const distanceThreshold = 50; // meters
|
const distanceThreshold = 50; // meters
|
||||||
const timeThreshold = 20000; // milliseconds (3 seconds)
|
const timeThreshold = 20000; // milliseconds (3 seconds)
|
||||||
|
|
||||||
|
|
@ -48,9 +52,15 @@ export function createSimplifiedMarkers(markersData) {
|
||||||
const [lat, lon] = marker;
|
const [lat, lon] = marker;
|
||||||
const popupContent = createPopupContent(marker);
|
const popupContent = createPopupContent(marker);
|
||||||
let markerColor = marker[5] < 0 ? "orange" : "blue";
|
let markerColor = marker[5] < 0 ? "orange" : "blue";
|
||||||
|
|
||||||
return L.circleMarker(
|
return L.circleMarker(
|
||||||
[lat, lon],
|
[lat, lon],
|
||||||
{ radius: 4, color: markerColor, zIndexOffset: 1000 }
|
{
|
||||||
|
renderer: renderer, // Use canvas renderer
|
||||||
|
radius: 4,
|
||||||
|
color: markerColor,
|
||||||
|
zIndexOffset: 1000
|
||||||
|
}
|
||||||
).bindPopup(popupContent);
|
).bindPopup(popupContent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,9 @@ export function addHighlightOnHover(polylineGroup, map, polylineCoordinates, use
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createPolylinesLayer(markers, map, timezone, routeOpacity, userSettings, distanceUnit) {
|
export function createPolylinesLayer(markers, map, timezone, routeOpacity, userSettings, distanceUnit) {
|
||||||
|
// Create a canvas renderer
|
||||||
|
const renderer = L.canvas({ padding: 0.5 });
|
||||||
|
|
||||||
const splitPolylines = [];
|
const splitPolylines = [];
|
||||||
let currentPolyline = [];
|
let currentPolyline = [];
|
||||||
const distanceThresholdMeters = parseInt(userSettings.meters_between_routes) || 500;
|
const distanceThresholdMeters = parseInt(userSettings.meters_between_routes) || 500;
|
||||||
|
|
@ -298,7 +301,6 @@ export function createPolylinesLayer(markers, map, timezone, routeOpacity, userS
|
||||||
|
|
||||||
for (let i = 0; i < polylineCoordinates.length - 1; i++) {
|
for (let i = 0; i < polylineCoordinates.length - 1; i++) {
|
||||||
const speed = calculateSpeed(polylineCoordinates[i], polylineCoordinates[i + 1]);
|
const speed = calculateSpeed(polylineCoordinates[i], polylineCoordinates[i + 1]);
|
||||||
|
|
||||||
const color = getSpeedColor(speed, userSettings.speed_colored_routes);
|
const color = getSpeedColor(speed, userSettings.speed_colored_routes);
|
||||||
|
|
||||||
const segment = L.polyline(
|
const segment = L.polyline(
|
||||||
|
|
@ -307,11 +309,12 @@ export function createPolylinesLayer(markers, map, timezone, routeOpacity, userS
|
||||||
[polylineCoordinates[i + 1][0], polylineCoordinates[i + 1][1]]
|
[polylineCoordinates[i + 1][0], polylineCoordinates[i + 1][1]]
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
|
renderer: renderer, // Use canvas renderer
|
||||||
color: color,
|
color: color,
|
||||||
originalColor: color,
|
originalColor: color,
|
||||||
opacity: routeOpacity,
|
opacity: routeOpacity,
|
||||||
weight: 3,
|
weight: 3,
|
||||||
speed: speed, // Store the calculated speed
|
speed: speed,
|
||||||
startTime: polylineCoordinates[i][4],
|
startTime: polylineCoordinates[i][4],
|
||||||
endTime: polylineCoordinates[i + 1][4]
|
endTime: polylineCoordinates[i + 1][4]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue