Home Reference Source

src/Gisplay/Legend.js

/**
 * This class represents the Map Legend. 15/03
 */
export class Legend {
    /**
     * Creates an instance of Legend class.
     * @param {number} id -  The id of the legend.
     * @param {string} title - The title for the legend.
     * 
     * @memberOf Legend
     */
    constructor(id, title) {
        /**
         * Title of the Gisplay map Legend.
         * @type {string}
         */
        this.title = title;
        this.init(id);
        return this; //@Rui Remove this
    }

    /**
     * Appends the legend div element to the map container.
     * @param {*} map 
     */
    insertLegend(map) {
        this.legendDiv.appendChild(this.table);
        map.getContainer().appendChild(this.legendDiv);
    }

    /**
     * Inserts one row for the Aesthetic object.
     * @param {Aesthetic} currentaes - The Aesthetic object 
     * @param {*} mapobj 
     */
    insertPointRow(currentaes, mapobj) {
        this.insertRow(currentaes, mapobj, 2);
    }

    insertPolygonRow(currentaes, mapobj) {
        this.insertRow(currentaes, mapobj, 1);
    }

    insertRow(currentaes, mapobj, type) {

        const row = document.createElement('tr');
        const value = document.createElement('td');
        const color = document.createElement('td');
        let text;
        if (typeof currentaes.range[0] === 'number') {
            const mininput = currentaes.range[0] != null ? currentaes.range[0] : mapobj.min;
            const maxinput = currentaes.range[1] != null ? currentaes.range[1] : mapobj.max;
            if (currentaes.outer == false)
                text = document.createTextNode(`[${mininput}, ${maxinput}[`);
            else
                text = document.createTextNode(`[${mininput}, ${maxinput}]`);
        }
        else
            text = document.createTextNode(currentaes.range[0]);
        value.appendChild(text);

        const colorDiv = document.createElement('div');
        colorDiv.style.position = 'relative';
        const rgbc = `rgba(${currentaes.fillColor[0]},${currentaes.fillColor[1]},${currentaes.fillColor[2]},${currentaes.fillColor[3]})`;
        colorDiv.style['backgroundColor'] = rgbc;
        if (type == 1) {//polygon
            colorDiv.style.height = 25;//(mapCanvas.height / 10);
            colorDiv.style.width = 80;//(mapCanvas.width / 10);
            if (currentaes.strokeColor != null && currentaes != undefined)
                colorDiv.style['borderColor'] = `rgba(${currentaes.strokeColor[0]},${currentaes.strokeColor[1]},${currentaes.strokeColor[2]},${currentaes.strokeColor[3]})`;
            colorDiv.className = '_gisplayrectangle';
        }
        else if (type == 2) {//point
            let size;
            if (currentaes.pointSize != null) {
                size = Math.max(currentaes.pointSize, 5);
            }
            else
                size = 25;
            colorDiv.style.height = size;
            colorDiv.style.width = size;
            colorDiv.className = '_gisplaycircle';
        }


        color.appendChild(colorDiv);

        row.appendChild(color);
        row.appendChild(value);

        row.onclick = function () {
            if (window.profiling == true)
                var start = Date.now();
            if (mapobj.legendToggle != false) {
                const toFade = !currentaes.enableDisable();
                if (toFade == true) {
                    this.className += " _gisplayfade";
                }
                else {
                    this.className = this.className.replace(/(?:^|\s)_gisplayfade(?!\S)/g, '');
                }
            }
            if (mapobj.legendOnClickCall != null && mapobj.legendOnClickCall != undefined)
                mapobj.legendOnClickCall(currentaes);
            mapobj.draw();
            if (window.profiling == true) {
                const end = Date.now();
                window.console.log(`Tempo de processamento de filtragem pela legenda (segundos): ${(end - start) / 1000}`);
            }

        };

        this.table.appendChild(row);

    }

    insertGradient(mapobj, left, middle, right) {
        const row = document.createElement('tr');
        const value = document.createElement('td');
        const valueDiv = document.createElement('div');
        value.colSpan = 2;
        value.style.textAlign = 'center';
        let numberof = 5;
        if (mapobj.aesthetics.length > 5)
            numberof = mapobj.aesthetics.length;
        let strcolor = '';
        for (let i = 0; i < numberof; i++) {
            const color = mapobj.fcolor(i / numberof).rgb();
            strcolor += `,rgba(${Math.round(color[0])},${Math.round(color[1])},${Math.round(color[2])},${mapobj.alpha})`;
        }
        strcolor += ') ';
        valueDiv.style.background = `-webkit-linear-gradient(left${strcolor}`;

        valueDiv.style.height = 25;//(mapCanvas.height / 10);
        valueDiv.style.width = 130;//(mapCanvas.width / 10);

        const row2 = document.createElement('tr');
        const value2 = document.createElement('td');
        value2.colSpan = 2;

        const divleft = document.createElement('div');
        divleft.style.textAlign = 'left';
        divleft.style.width = '33%';
        divleft.style.display = "inline-block";
        const lefttext = document.createTextNode(left);
        const divmid = document.createElement('div');
        divmid.style.textAlign = 'center';
        divmid.style.width = '33%';
        divmid.style.display = "inline-block";
        const text = document.createTextNode(middle);
        const divright = document.createElement('div');
        divright.style.textAlign = 'right';
        divright.style.width = '33%';
        divright.style.display = "inline-block";
        const righttext = document.createTextNode(right);



        divleft.appendChild(lefttext);
        divmid.appendChild(text);
        divright.appendChild(righttext);
        value2.appendChild(divleft);
        value2.appendChild(divmid);
        value2.appendChild(divright);
        value.appendChild(valueDiv);
        row2.appendChild(value2);
        row.appendChild(value);
        this.table.appendChild(row);
        this.table.appendChild(row2);
    }

    init(id, classname) {
        //console.log("id == " + id);
        const mapCanvas = document.getElementById(`mapCanvas${id}`);
        this.legendDiv = document.createElement('div');
        if (classname != undefined && classname != null) {
            this.legendDiv.className = classname;
        }
        else {
            this.legendDiv.className = '_gisplaylegendBR';
        }
        this.legendDiv.id = `legendDiv${id}`;





        this.table = document.createElement('table');
        this.table.style.zIndex = "2000";
        const thvalue = document.createElement('th');
        const thcolor = document.createElement('th');
        thcolor.style.align = "center";
        //thcolor.style.width = 100;
        this.table.appendChild(thcolor);
        this.table.appendChild(thvalue);
        const titlerow = document.createElement('tr');
        const titletd = document.createElement('td');
        titletd.colSpan = 2;
        titletd.style.textAlign = 'center';
        titletd.style.width = 100;
        const titletext = document.createTextNode(this.title);
        titletd.appendChild(titletext);
        titlerow.appendChild(titletd);
        this.table.appendChild(titlerow);

    }

    insertProportionalSymbols(currentaes, mapobj, numberof) {
        if (this.lastdiv == undefined) {
            var row = document.createElement('tr');
            var value = document.createElement('td');
            value.colSpan = 2;
            value.style.textAlign = 'center';
            this.firstInsertion = true;
        } else { this.firstInsertion = false; }

        const rgbc = `rgba(${currentaes.fillColor[0]},${currentaes.fillColor[1]},${currentaes.fillColor[2]},${1})`;
        let strokecolor;

        if (currentaes.strokeColor != null && currentaes != undefined)
            strokecolor = `rgba(${currentaes.strokeColor[0]},${currentaes.strokeColor[1]},${currentaes.strokeColor[2]},${currentaes.strokeColor[3]})`;
        else
            strokecolor = `rgba(${0},${0},${0},${1})`;

        for (let i = numberof - 1; i >= 0; i--) {
            const current = document.createElement('div');
            let propvalue;
            if (this.firstInsertion == false && i == (numberof - 1) || numberof == 1)
                propvalue = currentaes.range[1];
            else
                propvalue = mapobj.min + i / (numberof - 1) * (mapobj.max - mapobj.min);

            const text = document.createTextNode(this.round(propvalue));
            current.appendChild(text);
            const colorDiv = document.createElement('div');
            colorDiv.style.position = 'relative';
            colorDiv.style.backgroundColor = rgbc;
            colorDiv.className = '_gisplayproportionalcircle';
            colorDiv.style.borderColor = strokecolor;
            const temppointsize = ((mapobj.maxpointsize - mapobj.minpointsize) / (mapobj.max - mapobj.min)) * (propvalue - mapobj.min);
            const size = Math.max(temppointsize, 7.5);
            colorDiv.style.height = size;
            colorDiv.style.width = size;
            colorDiv.style.inherit = false;

            colorDiv.onclick = function (e) {
                if (window.profiling == true)
                    var start = Date.now();
                if (mapobj.legendToggle != false) {
                    const toFade = !currentaes.enableDisable();
                    if (toFade == true) {
                        this.className += " _gisplayfade";
                    }
                    else {
                        this.className = this.className.replace(/(?:^|\s)_gisplayfade(?!\S)/g, '');
                    }
                }
                if (mapobj.legendOnClickCall != null && mapobj.legendOnClickCall != undefined)
                    mapobj.legendOnClickCall(currentaes);
                mapobj.draw();
                if (window.profiling == true) {
                    const end = Date.now();
                    window.console.log(`Tempo de processamento de filtragem pela legenda (segundos): ${(end - start) / 1000}`);
                }
                if (!e)
                    var e = window.event;
                e.cancelBubble = true;
                if (e.stopPropagation)
                    e.stopPropagation();

            };
            current.appendChild(colorDiv);
            if (/*i!= (numberof-1) &&*/ this.lastdiv != undefined) {
                this.lastdiv.appendChild(current);
                this.lastdiv = colorDiv;
            }
            else {
                value.appendChild(current);
                this.lastdiv = colorDiv;
            }

        }
        if (this.firstInsertion == true) {
            row.appendChild(value);
            this.table.appendChild(row);
        }


    }

    round(value, exp) {//@Rui Added cuz its used by insertProportionalSymbols
        if (typeof exp === 'undefined' || +exp === 0)
            return Math.round(value);

        value = +value;
        exp = +exp;

        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
            return NaN;

        // Shift
        value = value.toString().split('e');
        value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

        // Shift back
        value = value.toString().split('e');
        return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
    }
}