From 706ace27695681c3b019a41f03092cedcaf3c67c Mon Sep 17 00:00:00 2001 From: Dave Conway-Jones Date: Wed, 13 Dec 2023 15:29:19 +0000 Subject: [PATCH] Add ability for pmtiles to be slightly styled bump to 4.6.0 --- CHANGELOG.md | 1 + README.md | 17 ++++++++++++++++- package.json | 2 +- worldmap.js | 8 +++++++- worldmap/worldmap.js | 9 ++++++--- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6e687a..7e3da92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ### Change Log for Node-RED Worldmap + - v4.6.0 - let default pmtiles be light/dark or monocolored. - v4.5.2 - Tidy up when pmtiles removed. - v4.5.0 - Fix pmtiles to look for maps in userdir rather than modules. - v4.4.0 - Add quad(copter) drone icon. diff --git a/README.md b/README.md index b6acb22..6c35705 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 +- v4.6.0 - let default pmtiles be light/dark or monocolored. - v4.5.2 - Tidy up when pmtiles removed. - v4.5.0 - Fix pmtiles to look for maps in userdir rather than modules - v4.4.0 - Add quad(copter) drone icon. @@ -724,9 +725,23 @@ You can use a PMtiles format map archive file from [Protomaps](https://docs.prot Copy your .pmtiles file(s) into your `~/.node-red` user directory. On re-starting Node-RED the node will detect the file(s) and add them to the base map layer menu, using the file name as the layer name. +You can set some default options for the pmtiles by creating a file called **pmtiles.opts** in your user directory. For example to create a nightvision style + + { + "attribution": "Protomaps and OSM", + "maxDataZoom": 15, + "maxZoom": 20, + "shade": "red", + "dark": true + } + +The `maxDataZoom` should match the maximum zoom level in you pmtiles file(s) - whereas the `maxZoom` is the leaflet maximum zoom level you want to support. `shade` can be any valid html colour or #rrggbb string, and `dark` is a boolean (default false). + You can also load them dynamically with a command like - msg.payload = {"command":{"map":{"name":"MyMap","pmtiles":"/path/to/mymap.pmtiles"}}} + msg.payload = {"command":{"map":{"name":"MyMap", "pmtiles":"/path/to/mymap.pmtiles", "opt":"myOptionsObject"}}} + +Where `opt` can be as per the options file mentioned above - or omitted completely. ### Using a Docker Map Server diff --git a/package.json b/package.json index 4782191..0be51c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-web-worldmap", - "version": "4.5.2", + "version": "4.6.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 57b95eb..a38871a 100644 --- a/worldmap.js +++ b/worldmap.js @@ -16,6 +16,12 @@ module.exports = function(RED) { var pmtiles = fs.readdirSync(__dirname + '/worldmap').filter(fn => fn.endsWith('.pmtiles')); pmtiles.forEach(file => { fs.unlinkSync(__dirname + '/worldmap/'+file); }) pmtiles = fs.readdirSync(RED.settings.userDir).filter(fn => fn.endsWith('.pmtiles')); + var pmtilesopts; + try { + pmtilesopts = fs.readFileSync(RED.settings.userDir+'/pmtiles.opts'); + pmtilesopts = JSON.parse(pmtilesopts); + } + catch(e) {}; function worldMap(node, n) { var allPoints = {}; @@ -128,7 +134,7 @@ module.exports = function(RED) { if (err.code !== "EEXIST") { console.log(err); } } }) - client.write(JSON.stringify({command: {map: {name:pmtiles[p].split('.')[0], pmtiles:pmtiles[p] }}})); + client.write(JSON.stringify({command: {map: {name:pmtiles[p].split('.')[0], pmtiles:pmtiles[p], opt:pmtilesopts }}})); } var o = Object.values(allPoints); o.map(v => delete v.tout); diff --git a/worldmap/worldmap.js b/worldmap/worldmap.js index 66a106f..be5d2a7 100644 --- a/worldmap/worldmap.js +++ b/worldmap/worldmap.js @@ -1296,7 +1296,7 @@ var addOverlays = function(overlist) { changeDrawColour("#4040F0"); // Set default drawing color to blue on start } - // Add the countries (world-110m) for offline use + // Add the countries (world-50m geojson) outline for offline use if (overlist.indexOf("CO") !== -1 || !navigator.onLine) { var customTopoLayer = L.geoJson(null, {clickable:false, style: {color:"blue", weight:2, fillColor:"#cf6", fillOpacity:0.04}}); layers["_countries"] = omnivore.topojson('images/world-50m-flat.json',null,customTopoLayer); @@ -2605,11 +2605,14 @@ function doCommand(cmd) { existsalready = true; } var opt = {}; - if (cmd.map.hasOwnProperty("opt")) { opt = cmd.map.opt; } + if (cmd.map.hasOwnProperty("opt")) { opt = cmd.map.opt || {}; } opt.url = cmd.map.pmtiles; - opt.attribution = opt.attribution || '© Protomaps'; + opt.attribution = opt.attribution || '© Protomaps & OSM'; opt.maxDataZoom = opt.maxDataZoom || 15; opt.maxZoom = opt.maxZoom || 20; + // opt.shade = "grey"; + // opt.dark = false; + // opt.xray = true; console.log("New PMtiles:",cmd.map.name,opt); basemaps[cmd.map.name] = protomapsL.leafletLayer(opt); if (!existsalready) {