From 4f9956d474464ef5d7c2dfc799ee7c435b308ff3 Mon Sep 17 00:00:00 2001 From: Dave Conway-Jones Date: Fri, 6 Oct 2023 15:31:24 +0100 Subject: [PATCH] Sync up drawing sessions across browsers --- CHANGELOG.md | 1 + README.md | 1 + package.json | 2 +- worldmap.js | 30 +++++++++++++++++++++++ worldmap/worldmap.js | 57 +++++++++++++++++++++++--------------------- 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c6c5b8..428dd2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### Change Log for Node-RED Worldmap + - v3.2.0 - Sync up drawing sessions across browsers to same map - v3.1.0 - Add esri overlay layers, and let geojson overlay rendering be customised - v3.0.0 - Bump to Leaflet 1.9.4 Move to geoman for drawing shapes. diff --git a/README.md b/README.md index 9395152..b5b3ef1 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Feel free to [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D% ### Updates +- v3.2.0 - Sync up drawing sessions across browsers to same map - v3.1.0 - Add esri overlay layers, and let geojson overlay rendering be customised - v3.0.0 - Bump to Leaflet 1.9.4 Move to geoman for drawing shapes. diff --git a/package.json b/package.json index 4abc28f..f0a52bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-web-worldmap", - "version": "3.1.0", + "version": "3.2.0", "description": "A Node-RED node to provide a web page of a world map for plotting things on.", "dependencies": { "@turf/bezier-spline": "~6.5.0", diff --git a/worldmap.js b/worldmap.js index ee97f60..fd305bf 100644 --- a/worldmap.js +++ b/worldmap.js @@ -69,12 +69,22 @@ module.exports = function(RED) { RED.httpNode.use(node.path, express.static(__dirname + '/worldmap')); // RED.httpNode.use(node.path, express.static(__dirname + '/worldmap', {maxage:3600000})); + var sendToRest = function(m,id) { + for (var c in clients) { + if (clients.hasOwnProperty(c) && c !== id) { + // console.log("RESEND",m); + clients[c].write(JSON.stringify(m)); + } + } + } + var callback = function(client) { if (!client.headers.hasOwnProperty("user-agent")) { client.close(); } //client.setMaxListeners(0); clients[client.id] = client; client.on('data', function(message) { message = JSON.parse(message); + // console.log("ACTION",message.action,client.id,message) if (message.action === "connected") { var m = {}; var c = {init:true}; @@ -113,6 +123,26 @@ module.exports = function(RED) { o.map(v => delete v.tout); setTimeout(function() { client.write(JSON.stringify(o)) }, 250); } + if (message.action === "draw") { + delete message.action; + delete message.type; + delete message.options?.pane; + allPoints[message.name] = RED.util.cloneMessage(message); + sendToRest(message,client.id); + } + if (message.action === "point") { + delete message.action; + sendToRest(message,client.id); + } + if (message.action === "move") { + delete message.action; + delete message.from; + sendToRest(message,client.id); + } + if (message.action === "delete") { + delete allPoints[message.name]; + sendToRest(message,client.id); + } }); client.on('close', function() { delete clients[client.id]; diff --git a/worldmap/worldmap.js b/worldmap/worldmap.js index 26e3b79..17d70c9 100644 --- a/worldmap/worldmap.js +++ b/worldmap/worldmap.js @@ -28,7 +28,7 @@ var heat; var minimap; var sidebyside; var layercontrol; -// var drawControl; +var drawCount = 0; var drawingColour = "#910000"; var sendDrawing; var colorControl; @@ -418,17 +418,17 @@ var Lgrid = L.latlngGraticule({ // Copyright (c) 2013 Måns Beckman, All rights reserved. var edgeAware = function() { if (!edgeEnabled) { return; } - map.removeLayer(edgeLayer) - edgeLayer = new L.layerGroup(); - var mapBounds = map.getBounds(); - var mapBoundsCenter = mapBounds.getCenter(); + map.removeLayer(edgeLayer) + edgeLayer = new L.layerGroup(); + var mapBounds = map.getBounds(); + var mapBoundsCenter = mapBounds.getCenter(); - pSW = map.options.crs.latLngToPoint(mapBounds.getSouthWest(), map.getZoom()); - pNE = map.options.crs.latLngToPoint(mapBounds.getNorthEast(), map.getZoom()); - pCenter = map.options.crs.latLngToPoint(mapBoundsCenter, map.getZoom()); + pSW = map.options.crs.latLngToPoint(mapBounds.getSouthWest(), map.getZoom()); + pNE = map.options.crs.latLngToPoint(mapBounds.getNorthEast(), map.getZoom()); + pCenter = map.options.crs.latLngToPoint(mapBoundsCenter, map.getZoom()); - var viewBounds = L.latLngBounds(map.options.crs.pointToLatLng(L.point(pSW.x - (pCenter.x - pSW.x ), pSW.y - (pCenter.y - pSW.y )), map.getZoom()) , map.options.crs.pointToLatLng(L.point(pNE.x + (pNE.x - pCenter.x) , pNE.y + (pNE.y - pCenter.y) ), map.getZoom()) ); - for (var id in markers) { + var viewBounds = L.latLngBounds(map.options.crs.pointToLatLng(L.point(pSW.x - (pCenter.x - pSW.x ), pSW.y - (pCenter.y - pSW.y )), map.getZoom()) , map.options.crs.pointToLatLng(L.point(pNE.x + (pNE.x - pCenter.x) , pNE.y + (pNE.y - pCenter.y) ), map.getZoom()) ); + for (var id in markers) { if (allData[id] && allData[id].hasOwnProperty("SIDC")) { markerLatLng = markers[id].getLatLng(); if ( viewBounds.contains(markerLatLng) && !mapBounds.contains(markerLatLng) ) { @@ -471,8 +471,8 @@ var edgeAware = function() { edgeLayer.addLayer(L.marker([lat,lng],{icon:myicon})) } } - } - edgeLayer.addTo(map) + } + edgeLayer.addTo(map) } // end of edge function @@ -814,7 +814,7 @@ var addThing = function() { //popped = false; var bits = thing.split(","); var icon = (bits[1] || "circle").trim(); - var lay = (bits[2] || "_drawing").trim(); + var lay = (bits[2] || "unknown").trim(); // TODO: Do we want _drawing here or unknown ? var colo = (bits[3] ?? "#910000").trim(); colo = colorKeywordToRGB(colo); var hdg = parseFloat(bits[4] || 0); @@ -1086,7 +1086,6 @@ var addOverlays = function(overlist) { layers["_drawing"] = new L.FeatureGroup(); overlays["drawing"] = layers["_drawing"]; - var drawCount = 0; map.pm.addControls({ position: 'topleft', drawMarker: false, @@ -1102,18 +1101,19 @@ var addOverlays = function(overlist) { color: drawingColour, fillColor: drawingColour, fillOpacity: 0.4 - }); + }); } var shape; map.on("pm:create", (e) => { - var name = e.shape + drawCount; drawCount = drawCount + 1; + var name = e.shape + drawCount; e.layer.on('contextmenu', function(e) { L.DomEvent.stopPropagation(e); + var name = e.target.name; var rmen = L.popup({offset:[0,-12]}).setLatLng(e.latlng); - rmen.setContent("
"); + rmen.setContent("
"); map.openPopup(rmen); }); e.layer.bindPopup(name); @@ -1127,7 +1127,7 @@ var addOverlays = function(overlist) { else { cent = e.layer.getBounds().getCenter(); } - var m = {action:"draw", name:name, type:e.shape, layer:"_drawing", options:e.layer.options, radius:e.layer._mRadius, lat:la, lon:lo}; + var m = {action:"draw", name:name, type:e.shape, layer:"_drawing", options:e.layer.options, radius:e.layer._mRadius, lat:la, lon:lo, drawCount:drawCount}; if (e.layer.hasOwnProperty("_latlngs")) { if (e.layer.options.fill === false) { m.line = e.layer._latlngs; } else { m.area = e.layer._latlngs[0]; } @@ -1250,6 +1250,8 @@ var addOverlays = function(overlist) { sendDrawing(n); }); } + + changeDrawColour("#4040F0"); // Set default drawing color to blue on start } // Add the countries (world-110m) for offline use @@ -1496,15 +1498,15 @@ function setMarker(data) { var ll; var lli = null; - var opt = {}; - opt.color = data.color ?? data.lineColor ?? "#910000"; - opt.fillColor = data.fillColor ?? "#910000"; - opt.stroke = (data.hasOwnProperty("stroke")) ? data.stroke : true; - opt.weight = data.weight; - opt.opacity = data.opacity; - opt.fillOpacity = data.fillOpacity; + var opt = data.options || {}; + opt.color = opt.color ?? data.color ?? data.lineColor ?? "#910000"; + opt.fillColor = opt.fillColor ?? data.fillColor ?? "#910000"; + opt.stroke = opt.stroke ?? (data.hasOwnProperty("stroke")) ? data.stroke : true; + opt.weight = opt.weight ?? data.weight; + opt.opacity = opt.opacity ?? data.opacity; + opt.fillOpacity = opt.fillOpacity ?? data.fillOpacity; opt.clickable = (data.hasOwnProperty("clickable")) ? data.clickable : false; - opt.fill = (data.hasOwnProperty("fill")) ? data.fill : true; + opt.fill = opt.fill ?? (data.hasOwnProperty("fill")) ? data.fill : true; if (data.hasOwnProperty("dashArray")) { opt.dashArray = data.dashArray; } if (opt.fillOpacity === undefined) { opt.fillOpacity = 0.2; } if (opt.opacity === undefined) { opt.opacity = 1; } @@ -1594,6 +1596,7 @@ function setMarker(data) { map.fitBounds(polygons[data.name].getBounds(),{padding:[50,50]}) } } + if (data.hasOwnProperty("drawCount")) { drawCount = data.drawCount; } if (data.hasOwnProperty("greatcircle") && Array.isArray(data.greatcircle) && data.greatcircle.length === 2) { delete opt.fill; opt.vertices = opt.vertices || 20; @@ -2528,7 +2531,7 @@ function doCommand(cmd) { } if (cmd.map.hasOwnProperty("fly") && (cmd.map.fly === true)) { map.flyToBounds(overlays[cmd.map.overlay].getBounds()); } else if (cmd.map.hasOwnProperty("fit") && (cmd.map.fit === true)) { map.fitBounds(overlays[cmd.map.overlay].getBounds()); } - } + } catch(e) { console.log(e); } } // Add a new NVG XML overlay layer