WME Aerial Shifter (Updated API)

Adjusts the position and opacity of satellite imagery in WME

  1. // ==UserScript==
  2. // @name WME Aerial Shifter (Updated API)
  3. // @version 1.7.0
  4. // @description Adjusts the position and opacity of satellite imagery in WME
  5. // @match https://beta.waze.com/*editor*
  6. // @match https://www.waze.com/*editor*
  7. // @grant none
  8. // @icon http://s3.amazonaws.com/uso_ss/icon/176646/large.png?1391605696
  9. // @namespace https://www.waze.com/forum/viewtopic.php?t=53022
  10. // @author byo
  11. // @contributor berestovskyy, iainhouse, ragacs
  12. // ==/UserScript==
  13.  
  14. function initializeAerialShifter() {
  15. console.log("WME Aerial Shifter: Initializing...");
  16.  
  17. // Register a sidebar tab for the script
  18. const { tabLabel, tabPane } = W.userscripts.registerSidebarTab("wme-aerial-shifter");
  19.  
  20. // Set tab label
  21. tabLabel.innerText = 'Aerial Shifter';
  22. tabLabel.title = 'Adjust satellite imagery position';
  23.  
  24. // Create UI inside the tab
  25. tabPane.innerHTML = `
  26. <div style="padding: 10px;">
  27. <label>Horizontal shift (m):</label>
  28. <input type="number" id="was_sx" min="-100000" max="100000" step="100" value="0">
  29. <br>
  30. <label>Vertical shift (m):</label>
  31. <input type="number" id="was_sy" min="-100000" max="100000" step="100" value="0">
  32. <br>
  33. <label>Opacity (%):</label>
  34. <input type="number" id="was_opacity" min="0" max="100" step="10" value="100">
  35. <br>
  36. <button id="was_apply">Apply</button>
  37. <button id="was_reset">Reset</button>
  38. </div>
  39. `;
  40.  
  41. // Wait for the tab pane to be available in the DOM
  42. W.userscripts.waitForElementConnected(tabPane).then(() => {
  43. console.log("WME Aerial Shifter: UI loaded.");
  44.  
  45. // Attach event listeners
  46. document.getElementById("was_apply").addEventListener("click", applyChanges);
  47. document.getElementById("was_reset").addEventListener("click", resetDefaults);
  48.  
  49. loadSettings();
  50. });
  51. }
  52.  
  53. function applyChanges() {
  54. let shiftX = parseInt(document.getElementById("was_sx").value, 10);
  55. let shiftY = parseInt(document.getElementById("was_sy").value, 10);
  56. let opacity = parseInt(document.getElementById("was_opacity").value, 10);
  57.  
  58. let metersPerPixel = W.map.getResolution() * 39.37; // Convert to pixels
  59.  
  60. // Find the satellite layer dynamically
  61. let satLayer = W.map.getLayersBy("CLASS_NAME", "OpenLayers.Layer.Google")[0];
  62.  
  63. if (!satLayer || !satLayer.div) {
  64. console.error("WME Aerial Shifter: Satellite layer not found.");
  65. return;
  66. }
  67.  
  68. // Apply transformation to shift the satellite layer
  69. satLayer.div.style.transform = `translate(${Math.round(shiftX / metersPerPixel)}px, ${Math.round(shiftY / metersPerPixel)}px)`;
  70.  
  71. // Apply opacity change
  72. satLayer.div.style.opacity = opacity / 100;
  73.  
  74. saveSettings(shiftX, shiftY, opacity);
  75. }
  76.  
  77.  
  78.  
  79. function resetDefaults() {
  80. document.getElementById("was_sx").value = 0;
  81. document.getElementById("was_sy").value = 0;
  82. document.getElementById("was_opacity").value = 100;
  83. applyChanges();
  84. }
  85.  
  86. function loadSettings() {
  87. let settings = JSON.parse(localStorage.getItem("wme_aerial_shifter_settings"));
  88. if (settings) {
  89. document.getElementById("was_sx").value = settings.shiftX;
  90. document.getElementById("was_sy").value = settings.shiftY;
  91. document.getElementById("was_opacity").value = settings.opacity;
  92. }
  93. }
  94.  
  95. function saveSettings(shiftX, shiftY, opacity) {
  96. localStorage.setItem("wme_aerial_shifter_settings", JSON.stringify({
  97. shiftX,
  98. shiftY,
  99. opacity
  100. }));
  101. }
  102.  
  103. // Wait for WME to be fully initialized before running the script
  104. if (W?.userscripts?.state.isReady) {
  105. initializeAerialShifter();
  106. } else {
  107. document.addEventListener("wme-ready", initializeAerialShifter, { once: true });
  108. }