Greasy Fork 还支持 简体中文。

Modify Traces

Modify the Waze & User trace displayed by URs

目前為 2018-05-25 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Modify Traces
  3. // @namespace https://greasyfork.org/users/30701-justins83-waze
  4. // @version 0.3
  5. // @description Modify the Waze & User trace displayed by URs
  6. // @author JustinS83
  7. // @include https://www.waze.com/editor*
  8. // @include https://www.waze.com/*/editor*
  9. // @include https://beta.waze.com*
  10. // @exclude https://www.waze.com/*user/editor*
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. var URMO;
  18. var recoloredArrow = "";
  19. var img = new Image();
  20. var mIcon;
  21.  
  22. function bootstrap(tries = 1) {
  23.  
  24. if (W &&
  25. W.map &&
  26. W.model &&
  27. W.loginManager.user &&
  28. $) {
  29. init();
  30. } else if (tries < 1000) {
  31. setTimeout(function () {bootstrap(tries++);}, 200);
  32. }
  33. }
  34.  
  35. bootstrap();
  36.  
  37. function modifyRules(){
  38. getTraceLayer().then(val => {
  39. //In theory these are always the same index - but better to search and be sure we get the right ones
  40. let sugRouteArrowIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "suggestedRouteArrow";});
  41. let sugRouteIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "suggestedRoute";});
  42. let userRouteArrowIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "driveArrow";});
  43. let userRouteIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "drive";});
  44.  
  45. //Waze suggested route
  46. //default is 5
  47. val.styleMap.styles.default.rules[sugRouteArrowIndex].symbolizer.graphicHeight = 8;
  48. //default is 9
  49. val.styleMap.styles.default.rules[sugRouteArrowIndex].symbolizer.graphicWidth = 12;
  50.  
  51. //User driven route
  52. //default is 5
  53. val.styleMap.styles.default.rules[userRouteArrowIndex].symbolizer.graphicHeight = 8;
  54. //default is 9
  55. val.styleMap.styles.default.rules[userRouteArrowIndex].symbolizer.graphicWidth = 12;
  56. //This would change the route color from dark purple
  57. //val.styleMap.styles.default.rules[sugRouteIndex].symbolizer.strokeColor = "#c77aff";
  58.  
  59. getModifiedArrow().then(result => {
  60. val.styleMap.styles.default.rules[sugRouteArrowIndex].symbolizer.externalGraphic = recoloredArrow;
  61. val.redraw();
  62. });
  63.  
  64. val.redraw();
  65. URMO.disconnect(); //We only need the MO to fire once - once the rule is set it persists on the layer. The layer isn't created until the first time a user clicks on a UR, though.
  66. for(var mObj in W.map.updateRequestLayer.markers){
  67. if(W.map.updateRequestLayer.markers.hasOwnProperty(mObj)){
  68. mIcon = W.map.updateRequestLayer.markers[mObj].icon.div;
  69. mIcon.removeEventListener("click", modifyRules, false);
  70. }
  71. }
  72. });
  73.  
  74. }
  75.  
  76. function getTraceLayer(tries = 1) { //Need to use a promise to get the layer - if we do not, we have to fudge some delay after clicking to wait until the layer is created and everything set up before we go through our changes
  77. return new Promise((resolve, reject) => {
  78. if (W.map.getLayersByName("problemMoreInfo").length > 0){
  79. resolve(W.map.getLayersByName("problemMoreInfo")[0]);
  80. } else {
  81. if(tries <= 10)
  82. setTimeout(() => resolve(getTraceLayer(tries++)), 100);
  83. }
  84. });
  85. }
  86.  
  87. function getModifiedArrow(tries = 1){
  88. return new Promise((resolve, reject) =>{
  89. if(recoloredArrow === ""){
  90. if(tries <= 50)
  91. setTimeout(() => resolve(getModifiedArrow(tries++)), 100);
  92. }
  93. else{
  94. resolve(recoloredArrow);
  95. }
  96. });
  97. }
  98.  
  99. function URLayerPopulated()
  100. {
  101. for(var mObj in W.map.updateRequestLayer.markers){
  102. if(W.map.updateRequestLayer.markers.hasOwnProperty(mObj)){
  103. mIcon = W.map.updateRequestLayer.markers[mObj].icon.div;
  104. mIcon.addEventListener("click", modifyRules, false);
  105. }
  106. }
  107. }
  108.  
  109. function init(){
  110. URMO = new MutationObserver(URLayerPopulated);
  111. URMO.observe(W.map.updateRequestLayer.div, {childList : true});
  112.  
  113. img.crossOrigin = "anonymous";
  114. img.onload = recolorArrow;
  115. img.src = "https://editor-assets.waze.com/production/img/one-way-routed9aa340910f8fc7a0fd2285fa0aab968.png";
  116. }
  117.  
  118. //changes the purple Waze drive arrows to yellow for more contrast. Ugly, but effective. Like your mom.
  119. function recolorArrow() {
  120. var canvas = document.createElement('canvas');
  121. var ctx = canvas.getContext("2d");
  122. ctx.drawImage(img, 0, 0);
  123. let imgData = ctx.getImageData(0, 0, 9, 5);
  124. let data = imgData.data;
  125.  
  126. for (var i = 0; i < data.length; i += 4) {
  127. let red = data[i + 0];
  128. let green = data[i + 1];
  129. let blue = data[i + 2];
  130. let alpha = data[i + 3];
  131.  
  132. // skip transparent/semiTransparent pixels
  133. if (alpha < 10)
  134. continue;
  135.  
  136. let hsl = rgbToHsl(red, green, blue);
  137. let hue = hsl.h * 360;
  138.  
  139. // change purple pixels to the new color
  140. if (hue > 260 && hue < 270) {
  141. var newRgb = hslToRgb((hue - 200)/360, hsl.s, 100);//hsl.l); //Setting l to 100 forces it to white
  142. data[i + 0] = newRgb.r;
  143. data[i + 1] = newRgb.g;
  144. data[i + 2] = newRgb.b;
  145. //data[i + 3] = 255;
  146. }
  147. }
  148. var mycanvas = document.createElement('canvas');
  149. $(mycanvas).attr('width', 9);
  150. $(mycanvas).attr('height', 5);
  151. var newctx = mycanvas.getContext('2d');
  152. newctx.putImageData(imgData,0,0);
  153. recoloredArrow = mycanvas.toDataURL();
  154. }
  155.  
  156. function rgbToHsl(r, g, b) {
  157. r /= 255;
  158. g /= 255;
  159. b /= 255;
  160. let max = Math.max(r, g, b),
  161. min = Math.min(r, g, b);
  162. let h, s, l = (max + min) / 2;
  163.  
  164. if (max == min)
  165. h = s = 0; // achromatic
  166. else {
  167. let d = max - min;
  168. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  169. switch (max) {
  170. case r:
  171. h = (g - b) / d + (g < b ? 6 : 0);
  172. break;
  173. case g:
  174. h = (b - r) / d + 2;
  175. break;
  176. case b:
  177. h = (r - g) / d + 4;
  178. break;
  179. }
  180. h /= 6;
  181. }
  182.  
  183. return ({
  184. h: h,
  185. s: s,
  186. l: l,
  187. });
  188. }
  189.  
  190. function hue2rgb(p, q, t) {
  191. if (t < 0) t += 1;
  192. if (t > 1) t -= 1;
  193. if (t < 1 / 6) return p + (q - p) * 6 * t;
  194. if (t < 1 / 2) return q;
  195. if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
  196. return p;
  197. }
  198.  
  199. function hslToRgb(h, s, l) {
  200. let r, g, b;
  201.  
  202. if (s == 0)
  203. r = g = b = l; // achromatic
  204. else {
  205. let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  206. let p = 2 * l - q;
  207. r = hue2rgb(p, q, h + 1 / 3);
  208. g = hue2rgb(p, q, h);
  209. b = hue2rgb(p, q, h - 1 / 3);
  210. }
  211.  
  212. return ({
  213. r: Math.round(r * 255),
  214. g: Math.round(g * 255),
  215. b: Math.round(b * 255),
  216. });
  217. }
  218. })();