// ==UserScript==
// @name WME Multi Overlay
// @namespace https://greasyfork.org/de/users/863740-horst-wittlich
// @version 2025.05.15
// @description Fügt die TopPlus Open WMS-Karte, Dark Map und Basemap DE vom Geodatenzentrum zum Waze Map Editor hinzu
// @author Hiwi234
// @match https://www.waze.com/editor*
// @match https://www.waze.com/*/editor*
// @match https://beta.waze.com/editor*
// @match https://beta.waze.com/*/editor*
// @grant unsafeWindow
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const SCRIPT_NAME = 'WME TopPlus & Dark Map & Basemap DE';
const SCRIPT_ID = 'wme-topplus-dark-basemap';
const TOPPLUS_LAYER_NAME = 'TopPlus WMS';
const DARK_LAYER_NAME = 'OSM Dark Matter';
const BASEMAP_DE_LAYER_NAME = 'Basemap DE';
const DEFAULT_OPACITY = 0.64;
const DEFAULT_ZINDEX = 2000; // Extrem hoher Z-Index für Overlay-Layer
const DARK_ATTRIBUTION = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>';
const BASEMAP_DE_ATTRIBUTION = '© <a href="https://www.basemap.de">basemap.de</a>';
function createTopPlusLayer() {
const olMap = W.map.getOLMap();
const topPlusLayer = new OpenLayers.Layer.WMS(
TOPPLUS_LAYER_NAME,
"https://sgx.geodatenzentrum.de/wms_topplus_web_open",
{
layers: 'web',
format: 'image/png',
transparent: true
},
{
transitionEffect: 'resize',
attribution: '© BKG',
isBaseLayer: false,
visibility: false,
opacity: DEFAULT_OPACITY,
projection: new OpenLayers.Projection("EPSG:3857"),
displayInLayerSwitcher: false,
alwaysInRange: true,
zIndex: DEFAULT_ZINDEX
}
);
topPlusLayer.setOpacity(DEFAULT_OPACITY);
olMap.addLayer(topPlusLayer);
window.topPlusLayer = topPlusLayer;
}
function createDarkLayer() {
const olMap = W.map.getOLMap();
const darkLayer = new OpenLayers.Layer.XYZ(
DARK_LAYER_NAME,
[
"https://a.basemaps.cartocdn.com/dark_all/${z}/${x}/${y}@2x.png",
"https://b.basemaps.cartocdn.com/dark_all/${z}/${x}/${y}@2x.png",
"https://c.basemaps.cartocdn.com/dark_all/${z}/${x}/${y}@2x.png"
],
{
attribution: DARK_ATTRIBUTION,
transitionEffect: 'resize',
isBaseLayer: false,
visibility: false,
opacity: DEFAULT_OPACITY,
displayInLayerSwitcher: false,
alwaysInRange: true,
zIndex: DEFAULT_ZINDEX
}
);
darkLayer.setOpacity(DEFAULT_OPACITY);
olMap.addLayer(darkLayer);
window.darkLayer = darkLayer;
}
function createBasemapDELayer() {
const olMap = W.map.getOLMap();
const basemapDELayer = new OpenLayers.Layer.WMS(
BASEMAP_DE_LAYER_NAME,
"https://sgx.geodatenzentrum.de/wms_basemapde",
{
layers: 'de_basemapde_web_raster_farbe',
format: 'image/png',
transparent: true
},
{
transitionEffect: 'resize',
attribution: BASEMAP_DE_ATTRIBUTION,
isBaseLayer: false,
visibility: false,
opacity: DEFAULT_OPACITY,
projection: new OpenLayers.Projection("EPSG:3857"),
displayInLayerSwitcher: false,
alwaysInRange: true,
zIndex: DEFAULT_ZINDEX
}
);
basemapDELayer.setOpacity(DEFAULT_OPACITY);
olMap.addLayer(basemapDELayer);
window.basemapDELayer = basemapDELayer;
}
function createLayerControl(layer, name) {
const container = document.createElement('div');
container.className = 'layer-control';
// Sichtbarkeits-Checkbox
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = layer.getVisibility();
checkbox.addEventListener('change', () => layer.setVisibility(checkbox.checked));
const label = document.createElement('label');
label.appendChild(checkbox);
label.appendChild(document.createTextNode(name));
// Transparenz-Slider
const opacityContainer = document.createElement('div');
opacityContainer.className = 'slider-container';
const opacityLabel = document.createElement('span');
opacityLabel.textContent = 'Transparenz: ';
const opacitySlider = document.createElement('input');
opacitySlider.type = 'range';
opacitySlider.min = '0';
opacitySlider.max = '1';
opacitySlider.step = '0.1';
opacitySlider.value = layer.opacity;
opacitySlider.addEventListener('input', () => layer.setOpacity(parseFloat(opacitySlider.value)));
opacityContainer.appendChild(opacityLabel);
opacityContainer.appendChild(opacitySlider);
// Z-Index-Slider
const zIndexContainer = document.createElement('div');
zIndexContainer.className = 'slider-container';
const zIndexLabel = document.createElement('span');
zIndexLabel.textContent = 'Ebene: ';
const zIndexSlider = document.createElement('input');
zIndexSlider.type = 'range';
zIndexSlider.min = '5'; // Sehr hoher minimaler Z-Index
zIndexSlider.max = '2500'; // Maximaler Z-Index
zIndexSlider.step = '5';
zIndexSlider.value = layer.getZIndex() || DEFAULT_ZINDEX;
zIndexSlider.addEventListener('input', () => {
const zIndex = parseInt(zIndexSlider.value);
layer.setZIndex(zIndex);
});
zIndexContainer.appendChild(zIndexLabel);
zIndexContainer.appendChild(zIndexSlider);
// Füge alle Elemente zum Container hinzu
container.appendChild(label);
container.appendChild(opacityContainer);
container.appendChild(zIndexContainer);
return container;
}
async function initializeScript() {
try {
// Registriere Script-Info
W.userscripts[SCRIPT_ID] = {
name: SCRIPT_NAME,
author: 'Hiwi234',
version: GM_info.script.version
};
// Erstelle Layer
createTopPlusLayer();
createDarkLayer();
createBasemapDELayer();
// Erstelle Sidebar Tab
const { tabLabel, tabPane } = W.userscripts.registerSidebarTab(SCRIPT_ID);
// Setze Tab-Label
tabLabel.textContent = 'Multi 🗺️';
tabLabel.title = 'Karten-Overlays';
// Warte auf DOM-Verfügbarkeit
await W.userscripts.waitForElementConnected(tabPane);
// Erstelle Content Container
const content = document.createElement('div');
content.className = 'overlay-tab';
// Füge Layer-Steuerelemente hinzu
content.appendChild(createLayerControl(window.topPlusLayer, TOPPLUS_LAYER_NAME));
content.appendChild(createLayerControl(window.darkLayer, DARK_LAYER_NAME));
content.appendChild(createLayerControl(window.basemapDELayer, BASEMAP_DE_LAYER_NAME));
// Füge Content zum Tab-Pane hinzu
tabPane.appendChild(content);
// Füge Styles hinzu
const style = document.createElement('style');
style.textContent = `
.overlay-tab { padding: 8px; }
.layer-control {
margin-bottom: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.layer-control label {
display: block;
margin-bottom: 10px;
font-weight: bold;
}
.slider-container {
margin: 8px 0;
}
.slider-container span {
display: inline-block;
width: 100px;
}
.slider-container input[type="range"] {
width: calc(100% - 105px);
vertical-align: middle;
}
`;
document.head.appendChild(style);
console.log(SCRIPT_NAME + ': Erfolgreich initialisiert');
} catch (error) {
console.error(SCRIPT_NAME + ': Fehler bei der Initialisierung:', error);
}
}
// Starte Initialisierung wenn WME bereit ist
if (W?.userscripts?.state.isReady) {
initializeScript();
} else {
document.addEventListener('wme-ready', initializeScript, { once: true });
}
})();