HuasoFoundries/ig_markerfactory

View on GitHub
src/markerfactory.js

Summary

Maintainability
A
1 hr
Test Coverage
/** global: google, r, g, b */

import { IconObject } from "./icon_object.js";

import { createClusterIcon } from "./create_cluster_icon.js";
import { createTextMarker } from "./create_text_marker.js";

import { createFatMarkerIcon } from "./create_fat_marker_icon.js";

import { createGroupedIcon } from "./create_grouped_icon.js";

import { createTransparentMarkerIcon } from "./create_transparent_marker_icon.js";

import { parseHex, parseHSL, parseRGB, hslToRGB, rgbToHSL } from "./parsers.js";

import { omit, serializeOptions } from "./helpers.js";

function padHex(str_in) {
    if (("" + str_in).length === 1) {
        return "0" + String(str_in);
    } else {
        return String(str_in);
    }
}

const MarkerFactory = {
    createTransparentMarkerIcon: createTransparentMarkerIcon,
    createFatMarkerIcon: createFatMarkerIcon,
    createTextMarker: createTextMarker,
    createClusterIcon: createClusterIcon,
    createGroupedIcon: createGroupedIcon,

    readCache: function(cacheKey, options) {
        if (options.no_cache) {
            return null;
        }

        var cached = window.sessionStorage.getItem(cacheKey);
        if (cached === null) {
            return null;
        }

        var cachedObj = JSON.parse(cached);
        var iconObj = new IconObject(
            cachedObj.url,
            cachedObj.fillColor,
            omit(cachedObj, function(key) {
                return ["url", "fillColor"].indexOf(key) !== -1;
            })
        );
        return iconObj;
    },

    setCache: function(cacheKey, iconObj) {
        var cached = iconObj.toJSON();
        cached.url = iconObj.url;
        window.sessionStorage.setItem(cacheKey, JSON.stringify(cached));
        return iconObj;
    },

    generateAutoicon: function(options) {
        var generatorFN;

        if (!options.is_icon) {
            options.type = "textmarker";
            generatorFN = MarkerFactory.createTextMarker;
        } else if (options.shadow || options.type === "grouped") {
            options.type = "grouped";
            generatorFN = MarkerFactory.createGroupedIcon;
        } else if (options.transparent_background) {
            options.type = "transparent";
            generatorFN = MarkerFactory.createTransparentMarkerIcon;
        } else {
            generatorFN = MarkerFactory.createFatMarkerIcon;
            options.type = "fatmarker";
        }
        var cacheKey = serializeOptions(options);
        var iconObj = MarkerFactory.readCache(cacheKey, options);
        if (iconObj === null) {
            iconObj = generatorFN(options);
        }
        if (options.no_cache) {
            return iconObj;
        }
        return MarkerFactory.setCache(cacheKey, iconObj);
    },
    /**
     * Receives a color string rgb(a), hsl(a) or hex, returns its components
     * in rgba and hsla, with optional transparency
     * plus a darkened version (default is half of each RGB component) and a
     *
     * @param {string} somecolor    - A color string in  rgb(a), hsl(a) or hex format
     * @param {Number} opacity      - Opacity to apply to the color. Optional, default 1
     * @param {Number} darkenfactor - How much darker should the resulting color be. Optional, default 1
     *
     * @return     {Object}  input color parsed and modified as requested
     */
    parseColorString: function(somecolor, opacity, darkenfactor) {
        let parsedcolor = {
                original: somecolor
            },
            hsl,
            rgb;

        darkenfactor = darkenfactor || 1;
        opacity = isNaN(parseFloat(opacity, 10)) ? 1 : parseFloat(opacity, 10);

        if (somecolor.indexOf("hsl") !== -1) {
            hsl = parseHSL(somecolor, opacity);
            rgb = hslToRGB(hsl.h, hsl.s, hsl.l, hsl.a, darkenfactor);
        } else if (somecolor.indexOf("rgb") !== -1) {
            rgb = parseRGB(somecolor, opacity, darkenfactor);
        } else {
            rgb = parseHex(somecolor, opacity, darkenfactor);
        }

        hsl = rgbToHSL(rgb.r, rgb.g, rgb.b, rgb.a);

        parsedcolor.hsl = {
            h: hsl.h,
            s: hsl.s,
            l: hsl.l,
            a: hsl.a
        };
        parsedcolor.rgb = {
            r: rgb.r,
            g: rgb.g,
            b: rgb.b,
            a: rgb.a
        };

        parsedcolor.fillColor = rgb.fillColor;
        parsedcolor.rgba = rgb.fillColor;
        parsedcolor.hsla = hsl.fillColor;
        parsedcolor.strokeColor = rgb.strokeColor;
        parsedcolor.hex = [
            "#",
            padHex(rgb.r.toString(16)),
            padHex(rgb.g.toString(16)),
            padHex(rgb.b.toString(16)),
            rgb.a === 0 ? "00" : ""
        ].join("");
        return parsedcolor;
    },

    /**
     * Generates an google maps marker (or an image as dataurl from the given options)
     *
     * @param      {Object}  options  The options
     * @return     {Object}  { description_of_the_return_value }
     */
    autoIcon: function(options) {
        if (typeof options !== "object") {
            console.warn("autoIcon expects an object as its only parameter");
            return null;
        }
        // unless explicitly set to false, the icon doesn't have a marker-like wrapper
        options.transparent_background =
            options.transparent_background !== false;

        options.label = String(options.label || "A");
        options.color = options.color || "#FF0000";

        if (
            options.label.length === 4 ||
            options.label.substring(0, 2) === "0x"
        ) {
            options.font = options.font || "fontello";
            options.label = (options.label || "e836").slice(-4);
            options.unicodelabel = String.fromCharCode("0x" + options.label);
            options.scale = options.scale || 1;
            options.is_icon = true;

            return MarkerFactory.generateAutoicon(options);
        } else if (options.shadow) {
            console.log("createClusterIcon", JSON.stringify(options));

            return MarkerFactory.createClusterIcon(options);
        } else {
            options.scale = options.scale || 0.75;
            options.label = String(options.label || "A");
            options.fontsize = options.fontsize || 11;
            options.font = options.font || "Arial";
            // This is text I should print literally

            return MarkerFactory.generateAutoicon(options);
        }
    }
};

export { MarkerFactory };