mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-04-14 14:53:20 +00:00
Support for multiple base layers
* Make the layers control visible which allows the base layer to be chosen, and individual overlay layers to be hidden * Add tiddlers tagged $:/tags/GeoBaseLayer to define some useful map base layers * Add geobaselayer widget to define base layers
This commit is contained in:
parent
9bfe6e3a5f
commit
dbabdfce53
@ -22,11 +22,14 @@ This demo requires that the API keys needed to access external services be obtai
|
||||
<$geomap
|
||||
state=<<qualify "$:/state/demo-map">>
|
||||
>
|
||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/GeoBaseLayer]]">
|
||||
<$geobaselayer title=<<currentTiddler>>/>
|
||||
</$list>
|
||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/GeoMarker]]">
|
||||
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}}/>
|
||||
<$geolayer lat={{!!lat}} long={{!!long}} alt={{!!alt}} color={{!!color}} name={{!!caption}}/>
|
||||
</$list>
|
||||
<$list filter="[all[tiddlers+shadows]tag[$:/tags/GeoFeature]]">
|
||||
<$geolayer json={{!!text}} color={{!!color}}/>
|
||||
<$geolayer json={{!!text}} color={{!!color}} name={{!!caption}}/>
|
||||
</$list>
|
||||
</$geomap>
|
||||
|
||||
|
@ -0,0 +1,2 @@
|
||||
title: $:/tags/GeoBaseLayer
|
||||
list: $:/plugins/tiddlywiki/geospatial/baselayers/openstreetmap $:/plugins/tiddlywiki/geospatial/baselayers/opentopomap $:/plugins/tiddlywiki/geospatial/baselayers/stamen-watercolor
|
@ -0,0 +1,7 @@
|
||||
title: $:/plugins/tiddlywiki/geospatial/baselayers/openstreetmap
|
||||
caption: OpenStreetMap
|
||||
tags: $:/tags/GeoBaseLayer
|
||||
tiles-url: https://tile.openstreetmap.org/{z}/{x}/{y}.png
|
||||
max-zoom: 19
|
||||
|
||||
© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>
|
7
plugins/tiddlywiki/geospatial/baselayers/opentopomap.tid
Normal file
7
plugins/tiddlywiki/geospatial/baselayers/opentopomap.tid
Normal file
@ -0,0 +1,7 @@
|
||||
title: $:/plugins/tiddlywiki/geospatial/baselayers/opentopomap
|
||||
caption: OpenTopoMap
|
||||
tags: $:/tags/GeoBaseLayer
|
||||
tiles-url: https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png
|
||||
max-zoom: 17
|
||||
|
||||
Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, <a href="http://viewfinderpanoramas.org">SRTM</a> | Map style: © <a href="https://opentopomap.org">OpenTopoMap</a> (<a href="https://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a>)
|
@ -0,0 +1,7 @@
|
||||
title: $:/plugins/tiddlywiki/geospatial/baselayers/stamen-watercolor
|
||||
caption: Stamen Watercolor
|
||||
tags: $:/tags/GeoBaseLayer
|
||||
tiles-url: https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg
|
||||
max-zoom: 16
|
||||
|
||||
© Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.
|
18
plugins/tiddlywiki/geospatial/docs/geobaselayer.tid
Normal file
18
plugins/tiddlywiki/geospatial/docs/geobaselayer.tid
Normal file
@ -0,0 +1,18 @@
|
||||
title: $:/plugins/tiddlywiki/geospatial/docs/geobaselayer
|
||||
caption: geobaselayer widget
|
||||
tags: $:/tags/GeospatialDocs
|
||||
|
||||
!! `<$geobaselayer>` widget
|
||||
|
||||
The `<$geobaselayer>` widget is used inside the `<$geomap>` widget to define the base layers to display on the map.
|
||||
|
||||
The following attributes are supported:
|
||||
|
||||
|!Attribute |!Description |
|
||||
|''title'' |Optional title of a tiddler that defines the base layer through the fields ''caption'', ''tiles-url'', ''max-zoom'' and ''text'' (the text field defines the attribution string for the base layer) |
|
||||
|''name'' |Optional name for the base layer |
|
||||
|''tiles-url'' |Optional templated tile server URL for the base layer |
|
||||
|''max-zoom'' |Optional maximum zoom level for the base layer |
|
||||
|''attribution'' |Optional attribution text for the base layer |
|
||||
|
||||
The base layer will only work if all four of the required items ''name'', ''tiles-url'', ''max-zoom'' and ''attribution'' must be provided, either through the base layer tiddler specified in the title attribute, or explicitly via their own attributes.
|
@ -98,8 +98,10 @@ The following attributes are supported:
|
||||
|
||||
<$testcase>
|
||||
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/widgets/geomap"/>
|
||||
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
|
||||
</$testcase>
|
||||
|
||||
<$testcase>
|
||||
<$data $compound-tiddler="$:/plugins/tiddlywiki/geospatial/tests/widgets/geomap-refresh"/>
|
||||
<$data $tiddler="$:/plugins/tiddlywiki/geospatial"/>
|
||||
</$testcase>
|
||||
|
@ -6,9 +6,7 @@
|
||||
"type": "application/javascript",
|
||||
"title": "$:/plugins/tiddlywiki/geospatial/leaflet.js",
|
||||
"module-type": "library"
|
||||
},
|
||||
"prefix": "",
|
||||
"suffix": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "leaflet.css",
|
||||
@ -16,9 +14,14 @@
|
||||
"type": "text/css",
|
||||
"title": "$:/plugins/tiddlywiki/geospatial/leaflet.css",
|
||||
"tags": "[[$:/tags/Stylesheet]]"
|
||||
},
|
||||
"prefix": "",
|
||||
"suffix": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "images/layers-2x.png",
|
||||
"fields": {
|
||||
"type": "image/png",
|
||||
"title": "$:/plugins/tiddlywiki/geospatial/leaflet/images/layers-2x.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "LICENSE",
|
||||
|
@ -2,3 +2,9 @@ title: $:/plugins/tiddlywiki/geospatial/styles
|
||||
tags: [[$:/tags/Stylesheet]]
|
||||
|
||||
\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline
|
||||
|
||||
.leaflet-retina .leaflet-control-layers-toggle,
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(<<datauri '$:/plugins/tiddlywiki/geospatial/leaflet/images/layers-2x.png'>>);
|
||||
|
||||
}
|
17
plugins/tiddlywiki/geospatial/widgets/geobaselayer.js
Normal file
17
plugins/tiddlywiki/geospatial/widgets/geobaselayer.js
Normal file
@ -0,0 +1,17 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/innerwiki/geobaselayer.js
|
||||
type: application/javascript
|
||||
module-type: widget
|
||||
|
||||
geobaselayer widget to represent a base layer for a geomap widget. Clone of the data widget
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.geobaselayer = require("$:/core/modules/widgets/data.js").data;
|
||||
|
||||
})();
|
@ -61,42 +61,16 @@ GeomapWidget.prototype.render = function(parent,nextSibling) {
|
||||
};
|
||||
|
||||
GeomapWidget.prototype.renderMap = function() {
|
||||
var self = this;
|
||||
// Create the map
|
||||
this.map = $tw.Leaflet.map(this.domNode);
|
||||
// No layers rendered
|
||||
this.renderedLayers = [];
|
||||
// Setup the tile layer
|
||||
const tiles = $tw.Leaflet.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(this.map);
|
||||
this.baseLayers = [];
|
||||
// Disable Leaflet attribution
|
||||
this.map.attributionControl.setPrefix("");
|
||||
// Add scale
|
||||
$tw.Leaflet.control.scale().addTo(this.map);
|
||||
};
|
||||
|
||||
GeomapWidget.prototype.refreshMap = function() {
|
||||
var self = this;
|
||||
// Remove any previously rendered layers
|
||||
$tw.utils.each(this.renderedLayers,function(layer) {
|
||||
self.map.removeLayer(layer);
|
||||
});
|
||||
this.renderedLayers = [];
|
||||
// Set the position
|
||||
if(!this.setMapView()) {
|
||||
// Default to showing the whole world
|
||||
this.map.fitWorld();
|
||||
}
|
||||
// Create default icon
|
||||
const iconProportions = 365/560,
|
||||
iconHeight = 50;
|
||||
const myIcon = new $tw.Leaflet.Icon({
|
||||
iconUrl: $tw.utils.makeDataUri(this.wiki.getTiddlerText("$:/plugins/tiddlywiki/geospatial/images/markers/pin"),"image/svg+xml"),
|
||||
iconSize: [iconHeight * iconProportions, iconHeight], // Size of the icon
|
||||
iconAnchor: [(iconHeight * iconProportions) / 2, iconHeight], // Position of the anchor within the icon
|
||||
popupAnchor: [0, -iconHeight] // Position of the popup anchor relative to the icon anchor
|
||||
});
|
||||
// Listen for pan and zoom events and update the state tiddler
|
||||
this.map.on("moveend zoomend",function(event) {
|
||||
if(self.geomapStateTitle) {
|
||||
@ -116,6 +90,73 @@ GeomapWidget.prototype.refreshMap = function() {
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
GeomapWidget.prototype.refreshMap = function() {
|
||||
var self = this;
|
||||
// Remove any previously rendered layers
|
||||
$tw.utils.each(this.renderedLayers,function(layer) {
|
||||
self.map.removeLayer(layer.layer);
|
||||
});
|
||||
this.renderedLayers = []; // Array of {name:,layer:}
|
||||
this.renderedBaseLayers = []; // Array of {name:,layer:}
|
||||
// Restore the saved map position and zoom level
|
||||
if(!this.setMapView()) {
|
||||
// If there was no saved position then default to showing the whole world
|
||||
this.map.fitWorld();
|
||||
}
|
||||
// Create default icon
|
||||
var iconProportions = 365/560,
|
||||
iconHeight = 50;
|
||||
var myIcon = new $tw.Leaflet.Icon({
|
||||
iconUrl: $tw.utils.makeDataUri(this.wiki.getTiddlerText("$:/plugins/tiddlywiki/geospatial/images/markers/pin"),"image/svg+xml"),
|
||||
iconSize: [iconHeight * iconProportions, iconHeight], // Size of the icon
|
||||
iconAnchor: [(iconHeight * iconProportions) / 2, iconHeight], // Position of the anchor within the icon
|
||||
popupAnchor: [0, -iconHeight] // Position of the popup anchor relative to the icon anchor
|
||||
});
|
||||
// Counter for autogenerated names
|
||||
var untitledCount = 1;
|
||||
// Process embedded geobaselayer widgets
|
||||
function loadBaseLayer(layerInfo) {
|
||||
if(layerInfo.title) {
|
||||
var tiddler = self.wiki.getTiddler(layerInfo.title);
|
||||
if(tiddler) {
|
||||
layerInfo.name = layerInfo.name || tiddler.fields["caption"];
|
||||
layerInfo.tilesUrl = layerInfo.tilesUrl || tiddler.fields["tiles-url"];
|
||||
layerInfo.maxZoom = layerInfo.maxZoom || tiddler.fields["max-zoom"];
|
||||
layerInfo.attribution = layerInfo.attribution || tiddler.fields.text;
|
||||
}
|
||||
}
|
||||
var baseLayer = $tw.Leaflet.tileLayer(layerInfo.tilesUrl, {
|
||||
maxZoom: layerInfo.maxZoom,
|
||||
attribution: layerInfo.attribution
|
||||
});
|
||||
if(self.renderedBaseLayers.length === 0) {
|
||||
baseLayer.addTo(self.map)
|
||||
}
|
||||
var name = layerInfo.name || ("Untitled " + untitledCount++);
|
||||
self.renderedBaseLayers.push({name: name, layer: baseLayer});
|
||||
}
|
||||
this.findChildrenDataWidgets(this.contentRoot.children,"geobaselayer",function(widget) {
|
||||
loadBaseLayer({
|
||||
name: widget.getAttribute("name"),
|
||||
title: widget.getAttribute("title"),
|
||||
tilesUrl: widget.getAttribute("tiles-url"),
|
||||
maxZoom: widget.getAttribute("max-zoom"),
|
||||
attribution: widget.getAttribute("attribution"),
|
||||
});
|
||||
});
|
||||
// Create the default base map if none was specified
|
||||
if(this.renderedBaseLayers.length === 0) {
|
||||
// Render in reverse order so that the first tagged base layer will be rendered last, and hence take priority
|
||||
var baseLayerTitles = this.wiki.getTiddlersWithTag("$:/tags/GeoBaseLayer").reverse();
|
||||
$tw.utils.each(baseLayerTitles,function(title) {
|
||||
loadBaseLayer({title: title});
|
||||
});
|
||||
}
|
||||
if(this.renderedBaseLayers.length === 0) {
|
||||
loadBaseLayer({title: "$:/plugins/tiddlywiki/geospatial/baselayers/openstreetmap"});
|
||||
}
|
||||
// Make a marker cluster
|
||||
var markers = $tw.Leaflet.markerClusterGroup({
|
||||
maxClusterRadius: 40
|
||||
@ -126,8 +167,10 @@ GeomapWidget.prototype.refreshMap = function() {
|
||||
var jsonText = widget.getAttribute("json"),
|
||||
geoJson = [];
|
||||
if(jsonText) {
|
||||
// Layer is defined by JSON blob
|
||||
geoJson = $tw.utils.parseJSONSafe(jsonText,[]);
|
||||
} else if(widget.hasAttribute("lat") && widget.hasAttribute("long")) {
|
||||
// Layer is defined by lat long fields
|
||||
var lat = $tw.utils.parseNumber(widget.getAttribute("lat","0")),
|
||||
long = $tw.utils.parseNumber(widget.getAttribute("long","0")),
|
||||
alt = $tw.utils.parseNumber(widget.getAttribute("alt","0"));
|
||||
@ -160,8 +203,24 @@ GeomapWidget.prototype.refreshMap = function() {
|
||||
}
|
||||
}
|
||||
}).addTo(self.map);
|
||||
self.renderedLayers.push(layer);
|
||||
var name = widget.getAttribute("name") || ("Untitled " + untitledCount++);
|
||||
self.renderedLayers.push({name: name, layer: layer});
|
||||
});
|
||||
// Setup the layer control
|
||||
if(this.layerControl) {
|
||||
this.map.removeControl(this.layerControl);
|
||||
}
|
||||
var baseLayers = {};
|
||||
$tw.utils.each(this.renderedBaseLayers,function(layer) {
|
||||
baseLayers[layer.name] = layer.layer;
|
||||
});
|
||||
var overlayLayers = {};
|
||||
$tw.utils.each(this.renderedLayers,function(layer) {
|
||||
overlayLayers[layer.name] = layer.layer;
|
||||
});
|
||||
this.layerControl = $tw.Leaflet.control.layers(baseLayers,overlayLayers,{
|
||||
collapsed: true
|
||||
}).addTo(this.map);
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user