// ==UserScript==
// @name WME Map Overlay (Google + OSM + Traffic Layers with Slider & Icons + Click to Maps)
// @namespace https://waze.com
// @version 2.8
// @description Sobreposição de mapas no WME com camadas Google Maps, Trânsito e OSM, sliders com ícones personalizados, UI moderna e botão de esconder/mostrar. Agora com clique direto para Google Maps, OSM e ArcGIS na mesma posição!
// @author ChatGPT
// @match https://www.waze.com/*editor*
// @grant none
// @require https://greatest.deepsurf.us/scripts/24851-wazewrap/code/WazeWrap.js
// @license MIT
// ==/UserScript==
(function () {
'use strict';
let gmap, trafficDiv, sliderContainer, isSliderVisible = true;
function initOverlay() {
if (typeof W === 'undefined' || typeof W.map === 'undefined') {
setTimeout(initOverlay, 1000);
return;
}
const map = W.map;
const googleBaseLayer = new OpenLayers.Layer.XYZ(
"Google Maps (Base)",
"https://mt.google.com/vt/lyrs=m&x=${x}&y=${y}&z=${z}",
{ isBaseLayer: false, opacity: 0.01, visibility: true }
);
const osmLayer = new OpenLayers.Layer.XYZ(
"OpenStreetMap",
"https://tile.openstreetmap.org/${z}/${x}/${y}.png",
{ isBaseLayer: false, opacity: 0.01, visibility: true }
);
map.addLayer(googleBaseLayer);
map.addLayer(osmLayer);
sliderContainer = document.createElement("div");
sliderContainer.style.position = "absolute";
sliderContainer.style.top = "80px";
sliderContainer.style.left = "50%";
sliderContainer.style.transform = "translateX(-50%)";
sliderContainer.style.zIndex = "1000";
sliderContainer.style.padding = "8px";
sliderContainer.style.background = "rgba(10, 25, 50, 0.95)";
sliderContainer.style.borderRadius = "10px";
sliderContainer.style.border = "1px solid white";
sliderContainer.style.boxShadow = "0 2px 6px rgba(0,0,0,0.3)";
sliderContainer.style.display = "flex";
sliderContainer.style.gap = "10px";
sliderContainer.style.fontFamily = "sans-serif";
sliderContainer.style.transition = "all 0.3s ease";
const layers = [
{
name: "Google Maps",
icon: "https://static.vecteezy.com/system/resources/previews/016/716/478/non_2x/google-maps-icon-free-png.png",
initial: 0.01,
onChange: value => googleBaseLayer.setOpacity(value)
},
{
name: "Traffic",
icon: "https://cdn-icons-png.flaticon.com/256/2228/2228204.png",
initial: 0.00,
onChange: value => {
if (trafficDiv) trafficDiv.style.opacity = value;
}
},
{
name: "OSM",
icon: "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b0/Openstreetmap_logo.svg/2048px-Openstreetmap_logo.svg.png",
initial: 0.01,
onChange: value => osmLayer.setOpacity(value)
},
{
name: "ArcGIS",
icon: "https://th.bing.com/th/id/OIP.e5Qa0gpEBMxdY1zIgJu5PQHaHa?w=164&h=180&c=7&r=0&o=5&pid=1.7",
initial: 0.00,
onChange: () => {},
isButton: true
}
];
layers.forEach(layer => {
const wrapper = document.createElement("div");
wrapper.style.width = "60px";
wrapper.style.textAlign = "center";
const img = document.createElement("img");
img.src = layer.icon;
img.alt = layer.name;
img.title = layer.name;
img.style.width = "60px";
img.style.height = "60px";
img.style.borderRadius = "12px";
img.style.border = "2px solid white";
img.style.transition = "transform 0.3s ease, border 0.3s ease";
img.style.display = "block";
img.style.marginBottom = "4px";
img.style.cursor = "pointer";
img.addEventListener("mouseenter", () => {
img.style.transform = "scale(1.1)";
img.style.border = "2px solid gold";
});
img.addEventListener("mouseleave", () => {
img.style.transform = "scale(1)";
img.style.border = "2px solid white";
});
img.addEventListener("click", () => {
const center = W.map.getCenter();
const zoom = W.map.getZoom();
const lonlat = new OpenLayers.LonLat(center.lon, center.lat);
lonlat.transform(
new OpenLayers.Projection("EPSG:900913"),
new OpenLayers.Projection("EPSG:4326")
);
const lat = lonlat.lat;
const lon = lonlat.lon;
if (layer.name === "Google Maps") {
const gmapsZoom = Math.min(Math.max(zoom + 0, 0), 21);
const gmapsUrl = `https://www.google.com/maps/@${lat},${lon},${gmapsZoom}z`;
window.open(gmapsUrl, '_blank');
}
if (layer.name === "OSM") {
const osmUrl = `https://www.openstreetmap.org/#map=${zoom}/${lat}/${lon}`;
window.open(osmUrl, '_blank');
}
if (layer.name === "ArcGIS") {
// Ajuste especial para o ArcGIS
// O zoom do ArcGIS é diferente do WME, precisamos converter
const arcgisZoom = Math.min(Math.max(zoom + 0, 0), 20); // Ajuste de nível de zoom
const arcgisUrl = `https://www.arcgis.com/apps/Viewer/index.html?appid=3801d24f76d246adb134d43a7a222b2c¢er=${lon},${lat}&level=${arcgisZoom}`;
window.open(arcgisUrl, '_blank');
}
});
wrapper.appendChild(img);
if (!layer.isButton) {
const slider = document.createElement("input");
slider.type = "range";
slider.min = "0";
slider.max = "1";
slider.step = "0.01";
slider.value = layer.initial;
slider.style.width = "100%";
slider.addEventListener("input", () => {
layer.onChange(parseFloat(slider.value));
});
wrapper.appendChild(slider);
}
sliderContainer.appendChild(wrapper);
});
const toggleButton = document.createElement("button");
toggleButton.textContent = isSliderVisible ? "Hide Sliders" : "Show Sliders";
toggleButton.style.position = "absolute";
toggleButton.style.top = "30px";
toggleButton.style.left = "50%";
toggleButton.style.transform = "translateX(-50%)";
toggleButton.style.zIndex = "2000";
toggleButton.style.padding = "5px 10px";
toggleButton.style.backgroundColor = "rgba(10, 25, 50, 0.8)";
toggleButton.style.color = "white";
toggleButton.style.border = "1px solid white";
toggleButton.style.borderRadius = "5px";
toggleButton.style.cursor = "pointer";
toggleButton.style.transition = "all 0.3s ease";
toggleButton.addEventListener("click", () => {
isSliderVisible = !isSliderVisible;
sliderContainer.style.display = isSliderVisible ? "flex" : "none";
toggleButton.textContent = isSliderVisible ? "Hide Sliders" : "Show Sliders";
});
document.body.appendChild(toggleButton);
document.body.appendChild(sliderContainer);
initTrafficLayer();
}
function initTrafficLayer() {
const trafficLayer = new google.maps.TrafficLayer();
trafficDiv = document.createElement('div');
trafficDiv.id = "trafficDiv";
trafficDiv.style.position = 'absolute';
trafficDiv.style.top = '0';
trafficDiv.style.left = '0';
trafficDiv.style.right = '0';
trafficDiv.style.bottom = '0';
trafficDiv.style.zIndex = '500';
trafficDiv.style.opacity = '0';
trafficDiv.style.pointerEvents = 'none';
W.map.olMap.getViewport().appendChild(trafficDiv);
const lonlat = new OpenLayers.LonLat(W.map.getCenter().lon, W.map.getCenter().lat);
lonlat.transform(new OpenLayers.Projection('EPSG:900913'), new OpenLayers.Projection('EPSG:4326'));
gmap = new google.maps.Map(trafficDiv, {
zoom: W.map.getZoom(),
center: { lat: lonlat.lat, lng: lonlat.lon },
disableDefaultUI: true,
zoomControl: false,
styles: [
{ elementType: 'labels', stylers: [{ visibility: 'off' }] },
{ featureType: 'road', elementType: 'geometry', stylers: [{ lightness: 100 }] },
{ featureType: 'road', elementType: 'labels', stylers: [{ visibility: 'off' }] },
{ featureType: 'transit', stylers: [{ visibility: 'off' }] },
{ featureType: 'poi', stylers: [{ visibility: 'off' }] },
{ featureType: 'administrative', stylers: [{ visibility: 'off' }] },
{ featureType: 'landscape', stylers: [{ visibility: 'off' }] },
{ featureType: 'water', stylers: [{ visibility: 'off' }] }
]
});
trafficLayer.setMap(gmap);
trafficDiv.firstElementChild.style.backgroundColor = 'rgba(0, 0, 0, 0)';
WazeWrap.Events.register('moveend', null, () => {
const lonlat = new OpenLayers.LonLat(W.map.getCenter().lon, W.map.getCenter().lat);
lonlat.transform(new OpenLayers.Projection('EPSG:900913'), new OpenLayers.Projection('EPSG:4326'));
gmap.panTo({ lat: lonlat.lat, lng: lonlat.lon });
});
WazeWrap.Events.register('zoomend', null, () => {
gmap.setZoom(W.map.getZoom());
});
}
function waitReady() {
if (W && WazeWrap && WazeWrap.Ready) {
initOverlay();
} else {
setTimeout(waitReady, 500);
}
}
waitReady();
})();