Modify Traces

Modify the Waze & User trace displayed by URs

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Modify Traces
// @namespace    https://greasyfork.org/users/30701-justins83-waze
// @version      2018.11.07.01
// @description  Modify the Waze & User trace displayed by URs
// @author       JustinS83
// @include      https://www.waze.com/editor*
// @include      https://www.waze.com/*/editor*
// @include      https://beta.waze.com*
// @exclude      https://www.waze.com/*user/editor*
// @grant        none
// ==/UserScript==

/* global W */
/* global OL */
/* ecmaVersion 2017 */
/* global $ */
/* global _ */
/* global WazeWrap */
/* global require */
/* eslint curly: ["warn", "multi-or-nest"] */

(function() {
    'use strict';

    var URMO;
    var recoloredArrow = "";
    var recoloredUserArrow = "";
    var img = new Image();
    var userArrow = new Image();
    var mIcon;

    function bootstrap(tries = 1) {
        if (W && W.map &&
            W.model && W.loginManager.user &&
            $)
            init();
        else if (tries < 1000)
            setTimeout(function () {bootstrap(tries++);}, 200);
    }

    bootstrap();

    function modifyRules(){
        getTraceLayer().then(val => {
            //In theory these are always the same index - but better to search and be sure we get the right ones
            let sugRouteArrowIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "suggestedRouteArrow";});
            let sugRouteIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "suggestedRoute";});
            let userRouteArrowIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "driveArrow";});
            let userRouteIndex = val.styleMap.styles.default.rules.findIndex(function(e){ return e.filter.value == "drive";});

            //Waze suggested route
            //default is 5
            val.styleMap.styles.default.rules[sugRouteArrowIndex].symbolizer.graphicHeight = 8;
            //default is 9
            val.styleMap.styles.default.rules[sugRouteArrowIndex].symbolizer.graphicWidth = 12;

            //User driven route
            //default is 5
            val.styleMap.styles.default.rules[userRouteArrowIndex].symbolizer.graphicHeight = 8;
            //default is 9
            val.styleMap.styles.default.rules[userRouteArrowIndex].symbolizer.graphicWidth = 12;
            //This would change the route color from dark purple
            //val.styleMap.styles.default.rules[sugRouteIndex].symbolizer.strokeColor = "#c77aff";

            getModifiedArrow().then(result => {
                val.styleMap.styles.default.rules[sugRouteArrowIndex].symbolizer.externalGraphic = recoloredArrow;
                val.redraw();
            });

            getModifiedUserArrow().then(result => {
                val.styleMap.styles.default.rules[userRouteArrowIndex].symbolizer.externalGraphic = recoloredUserArrow;
                val.redraw();
            });

            val.redraw();
            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.
        });

    }

    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
        return new Promise((resolve, reject) => {
            if (W.map.getLayersByName("problemMoreInfo").length > 0)
                resolve(W.map.getLayersByName("problemMoreInfo")[0]);
            else {
                if(tries <= 10)
                    setTimeout(() => resolve(getTraceLayer(tries++)), 100);
            }
        });
    }

    function getModifiedArrow(tries = 1){
        return new Promise((resolve, reject) =>{
            if(recoloredArrow === ""){
                if(tries <= 50)
                    setTimeout(() => resolve(getModifiedArrow(tries++)), 100);
            }
            else
                resolve(recoloredArrow);
        });
    }

    function getModifiedUserArrow(tries = 1){
        return new Promise((resolve, reject) =>{
            if(recoloredUserArrow === ""){
                if(tries <= 50)
                    setTimeout(() => resolve(getModifiedUserArrow(tries++)), 100);
            }
            else
                resolve(recoloredUserArrow);
        });
    }

    function URLayerPopulated(mutations){
        mutations.forEach(function(mutation) {
            for (var i = 0; i < mutation.addedNodes.length; i++) {
                var addedNode = mutation.addedNodes[i];
                if (addedNode.nodeType === Node.ELEMENT_NODE && $(addedNode).hasClass('mapUpdateRequest'))
                    modifyRules();
            }
        });
    }

    function init(){
        img.crossOrigin = "anonymous";
        img.onload = recolorArrow;
        img.src = "https://editor-assets.waze.com/production/img/one-way-routed9aa340910f8fc7a0fd2285fa0aab968.png";

        userArrow.crossOrigin = "anonymous";
        userArrow.onload = recolorUserArrow;
        userArrow.src = "https://editor-assets.waze.com/production/img/one-way-drivee7f57df07fa6d5f61eee9b71ae5e18b1.png";

        URMO = new MutationObserver(URLayerPopulated);
        URMO.observe($('#panel-container')[0], {childList : true, subtree: true});
    }

    //changes the purple Waze drive arrows to white for more contrast.
    function recolorArrow() {
        let canvas = document.createElement('canvas');
        let ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);
        let imgData = ctx.getImageData(0, 0, 9, 5);
        let data = imgData.data;

        for (var i = 0; i < data.length; i += 4) {
            let red = data[i + 0];
            let green = data[i + 1];
            let blue = data[i + 2];
            let alpha = data[i + 3];

            // skip transparent/semiTransparent pixels
            if (alpha < 10)
                continue;

            let hsl = rgbToHsl(red, green, blue);
            let hue = hsl.h * 360;

            // change purple pixels to the new color
            if (hue > 260 && hue < 270) {
                var newRgb = hslToRgb((hue - 200)/360, hsl.s, 100);//hsl.l); //Setting l to 100 forces it to white
                data[i + 0] = newRgb.r;
                data[i + 1] = newRgb.g;
                data[i + 2] = newRgb.b;
                //data[i + 3] = 255;
            }
        }
        let mycanvas = document.createElement('canvas');
        $(mycanvas).attr('width', 9);
        $(mycanvas).attr('height', 5);
        let newctx = mycanvas.getContext('2d');
        newctx.putImageData(imgData,0,0);
        recoloredArrow = mycanvas.toDataURL();
    }

    function recolorUserArrow() {
        let canvas = document.createElement('canvas');
        let ctx = canvas.getContext("2d");
        ctx.drawImage(userArrow, 0, 0);
        let imgData = ctx.getImageData(0, 0, 9, 5);
        let data = imgData.data;

        for (var i = 0; i < data.length; i += 4) {
            let red = data[i + 0];
            let green = data[i + 1];
            let blue = data[i + 2];
            let alpha = data[i + 3];

            // skip transparent/semiTransparent pixels
            if (alpha < 10)
                continue;

            let hsl = rgbToHsl(red, green, blue);
            let hue = hsl.h * 360;

            // change green pixels to the new color
            if (hue > 157 && hue < 160) {
                var newRgb = hslToRgb((hue - 157)/360, .037, .106);//hsl.l);
                data[i + 0] = newRgb.r;
                data[i + 1] = newRgb.g;
                data[i + 2] = newRgb.b;
            }
        }
        let mycanvas = document.createElement('canvas');
        $(mycanvas).attr('width', 9);
        $(mycanvas).attr('height', 5);
        let newctx = mycanvas.getContext('2d');
        newctx.putImageData(imgData,0,0);
        recoloredUserArrow = mycanvas.toDataURL();
    }

    function rgbToHsl(r, g, b) {
        r /= 255;
        g /= 255;
        b /= 255;
        let max = Math.max(r, g, b),
            min = Math.min(r, g, b);
        let h, s, l = (max + min) / 2;

        if (max == min)
            h = s = 0; // achromatic
        else {
            let d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch (max) {
                case r:
                    h = (g - b) / d + (g < b ? 6 : 0);
                    break;
                case g:
                    h = (b - r) / d + 2;
                    break;
                case b:
                    h = (r - g) / d + 4;
                    break;
            }
            h /= 6;
        }

        return ({
            h: h,
            s: s,
            l: l,
        });
    }

    function hue2rgb(p, q, t) {
        if (t < 0) t += 1;
        if (t > 1) t -= 1;
        if (t < 1 / 6) return p + (q - p) * 6 * t;
        if (t < 1 / 2) return q;
        if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
        return p;
    }

    function hslToRgb(h, s, l) {
        let r, g, b;

        if (s == 0)
            r = g = b = l; // achromatic
        else {
            let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
            let p = 2 * l - q;
            r = hue2rgb(p, q, h + 1 / 3);
            g = hue2rgb(p, q, h);
            b = hue2rgb(p, q, h - 1 / 3);
        }

        return ({
            r: Math.round(r * 255),
            g: Math.round(g * 255),
            b: Math.round(b * 255),
        });
    }
})();