Генерируем кастомные маркеры для Google Maps v3

в 9:08, , рубрики: Google, Google Maps, imagemagick, javascript, node.js, метки: , ,

Генерируем кастомные маркеры для Google Maps v3
Работаю я в одном проекте с картами Google. Новыми, версии 3. Новые карты всем хороши: и быстрые, и дизайн симпатичный, и клевая клиентская библиотека для них есть. Одна проблема — маркеры одноцветные, а мне нужны разноцветные. В этой статье мы эту проблему будем решать — сделаем маленький сервис, который будет отдавать перекрашенный стандартный маркер нужного нам цвета.
Результат, для нетерпеливых, доступен здесь.

Стандартный маркер

image
Стандартный маркер берется гуглокартами по адресу mt.googleapis.com/vt/icon/name=icons/spotlight/spotlight-poi.png&scale=2 (выяснить это можно с помощью, например, Firebug, просмотрев список загружаемых страницей изображений во вкладке «Сеть»).
В зависимости от параметра scale по ссылке возвращаются изображения разного размера:

scale Размер изображения
1 22px × 40px
2 44px × 80px
3 66px × 120px
4 88px × 160px

Как перекрасить маркер?

Перекрашивать маркеры мы будем следующим образом:

  1. Генерируем кастомные маркеры для Google Maps v3
    Сначала обесцветим стандартный маркер.

  2. Генерируем кастомные маркеры для Google Maps v3
    Создадим картинку-маску того же размера, что и и оригинальный маркер, полностью заполненную цветом, в который мы хотим перекрасить маркер. Это изображения будет маской для синего цвета.

  3. Генерируем кастомные маркеры для Google Maps v3
    Наложим маску на черно-белое изображение маркера с перекрытием.

  4. Генерируем кастомные маркеры для Google Maps v3
    И, наконец, восстановим прозрачность (скопировав альфа-канал черно-белого маркера).

Автоматизация

Выполнять необходимые нам преобразования изображений для перекраски маркера программно удобнее всего, используя пакет консольных утилит Imagemagick:

convert -size 88x160 xc:"#0000ff" mask.png # создаем маску
convert marker-bw.png  mask.png -compose Overlay -composite temp.png # накладываем оверлей
convert temp.png marker-bw.png -compose copy-opacity -composite ready.png # копируем альфа-канал

Реализация на сервере

Сервер для отдачи получаемых изображений в сеть реализован на Node.js. Давайте посмотрим, как происходим на нем обработка запроса /getmarker?scale={размер маркера}&color={HEX-код цвета маркера} на получения маркера с заданным размером и цветом:

var colorRegexp = /^(?:[0-9a-f]{3}){1,2}$/i; //задаем регулярное выражение, по которому мы будем проверять правильность запрошенного цвета
var scales = ["22x40", "44x80", "66x120", "88x160"]; //создадим массив, описывающий доступные размеры маркера

app.get('/getmarker',function(req, res){

    //проверим переданный в метод цвет, либо установим цвет по умолчанию
    var color = req.query["color"];
    if (!color || !colorRegexp.test(color)){
        color = "f55850"
    } else {
        color.toLowerCase();
    }

    //проверим переданный в метод размер маркера, либо установим его по умолчанию
    var scale = req.query["scale"];
    var scale = new Number(req.query["scale"]);
    if (!scale){
        scale = 1;
    }
    scale--;
    if (scale < 0) scale = 0;
    if (scale > scales.length - 1) scale = scales.length - 1;
    
    //зададим имя файла, куда мы будем сохранять полученный маркер, чтобы не генерировать его заново при повторном запросе
    var filename = "./markers/marker-" + color + "-" + scale + ".png";

    fs.exists(filename, function(exists) {
        if (exists) {
            //если мы уже сгенерировали такой маркер, вернем готовую картинку
            console.log(filename + " exists, sended");
            res.sendfile(filename);
        } else {
            exec(
                //создаем цветовую маску
                'convert -size ' + scales[scale] + ' xc:#"' + color + '" mask' + color + scale +'.png n' +
                //накладываем маску на черно-белое изображение маркера
                'convert marker-bw-' + scale + '.png  mask' + color + scale +'.png -compose Overlay -composite temp'  + color + scale +'.png n' +
                //копируем прозрачность на временное изображение, полученное после оверлея
                'convert temp' + color + scale +'.png marker-bw-' + scale + '.png -compose copy-opacity -composite ' + filename,
                    console.log(filename + " created and sended");
                    res.sendfile(filename, function(){
                        //почистим мусор
                        exec('rm temp' + color + scale +'.png mask' + color + scale +'.png');
                    });
            );
        }
    });
});

Полный код доступен на GitHub.

Используем маркеры на карте Google

Сервис доступен по адресу http://gmapsmarkergenerator.eu01.aws.af.cm. Сами же маркеры — gmapsmarkergenerator.eu01.aws.af.cm/getmarker?scale={размер маркера}&color={HEX-код цвета маркера}. Как использовать их на карте?
Рассмотрим пример, работающий на библиотеке gmaps.js:

var map = new GMaps({
    div: '#gmap',
    lat: 55.7722200,
    lng: 37.6155600,
    zoom: 11
});
map.addMarkers(
    [{
        "lat": "55.767293",
        "lng": "37.544298",
        "icon": "gmapsmarkergenerator.eu01.aws.af.cm/getmarker?scale=1&color=00ffff"
    },
    {
        "lat": "55.747215",
        "lng": "37.655428",
        "icon": "gmapsmarkergenerator.eu01.aws.af.cm/getmarker?scale=1&color=ff00ff"
    },
    {
        "lat": "55.741408",
        "lng": "37.629908",
        "icon": "gmapsmarkergenerator.eu01.aws.af.cm/getmarker?scale=1&color=ffff00"
    },
    {
        "lat": "55.799994",
        "lng": "37.618375",
        "icon": "gmapsmarkergenerator.eu01.aws.af.cm/getmarker?scale=1&color=ff0000"
    },
    {
        "lat": "55.730858",
        "lng": "37.561649",
        "icon": "gmapsmarkergenerator.eu01.aws.af.cm/getmarker?scale=1&color=00ff00"
    },
    {
        "lat": "55.800309",
        "lng": "37.639824",
        "icon": "gmapsmarkergenerator.eu01.aws.af.cm/getmarker?scale=1&color=0000ff"
    }]
);

Как видите, все очень просто, нужно только указать у каждого маркера параметр icon.


Ссылка на сервис
GitHub

Автор: MAD_GooZe

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js