Создание изображения маркера Google Maps из SVG в DOM

#jquery #node.js #google-maps #d3.js #leaflet

#jquery #node.js #google-карты #d3.js #брошюра

Вопрос:

Я пытаюсь создать динамический маркер SVG (в основном с текстовой частью изменения SVG для каждого маркера) в Google Maps, но я борюсь с его динамическим аспектом. Как вы можете видеть в приведенном ниже коде, я могу создать маркер SVG, используя new google.maps.MarkerImage() статический URL.

 var marker = new google.maps.Marker({
    position: new google.maps.LatLng(38.4269929, -81.7921109),
    icon: new google.maps.MarkerImage('https://dl.dropboxusercontent.com/u/64084190/test-marker.svg',
    null, null, null, new google.maps.Size(25, 25)),
    map: map
});
 

Но, похоже, я не могу заставить google.maps.MarkerImage() использовать внутренний HTML-код элемента SVG DOM в качестве первого аргумента — он всегда ищет URL.

 <svg id="svg_elem"></svg>

function createDynamicSVGMarker(id){
    var svg_elem = d3.select('#svg_elem');
    svg_elem.append('path')
        .attr('fill', "#3875D7")
        .attr('d', "M100 0h-100v100h36.768l13.431 19.876 13.431-19.876h36.37z");
    svg_elem.append('text')
        .attr('transform', "translate(30.979 80)")
        .attr("fill", "#fff")
        .attr("font-size", "36")
        .text(id);

    var marker = new google.maps.Marker({
        position: new google.maps.LatLng(38.4269929, -81.7921109),
        icon: new google.maps.MarkerImage($('#svg_elem').html(),
        null, null, null, new google.maps.Size(25, 25)),
        map: map
    });
    $('#svg_elem').empty();
}
 

Должен ли я использовать MarkerImage или есть лучший подход к решению этой проблемы? Я пытался сделать это в node.js (но в конечном итоге не удалось) — создание нового SVG для каждого идентификатора (или даже создание SVG с последующим сохранением в формате PNG) — но я подумал, что было бы более эффективно делать все на стороне клиента. Я открыт для предложений, используя node.js или код на стороне клиента.

Ответ №1:

MarkerImage устарел в Maps v3.

В любом случае ознакомьтесь с символами из руководства для разработчиков, а затем с этим примером:

Основываясь на этом примере, попробуйте следующее:

 var marker = new google.maps.Marker({
    position: new google.maps.LatLng(38.4269929, -81.7921109),
    icon: {
        path: $('#svg_elem').attr('d'),
        //style elements: fillColor, strokeWeight, etc
        // ...
    },
    map: map
});
 

Я не уверен, сможете ли вы получить все, что хотите, В одном пути SVG (текст и т. Д.), Но Это должно помочь вам пройти большую часть пути. В API Карт Google есть и другие методы, которые могут без особых проблем помещать текст сверху.

Комментарии:

1. Спасибо @TerryTate. Я пробовал это с помощью пути к полигональной части SVG, и это работает хорошо, но получение динамического текста на маркере — это то, где я не добился успеха.

2. Нет проблем. Если часть svg работает, можете ли вы опубликовать то, что вы пробовали для добавления текста?

Ответ №2:

Столкнувшись с вышеупомянутой путаницей с Google Maps, я просто решил начать использовать Leaflet, CSS3 и L.divIcon , см. Мое решение ниже.

 .markerIcon {
    width: 30px;
    height: 32px;
    box-shadow: 0 0 1px white;
}

.markerIcon .arrow {
    width: 0;
    height: 0;
    border-left: 7px solid transparent;
    border-right: 7px solid transparent;
    margin: 0 auto;
    border-top: 8px solid #446cff;
}

.markerIcon .top {
    color: white;
    font-size: 11px;
    text-align: center;
    width: 30px;
    height: 32px;
    background-color: #446cff;
    line-height: 1.3em;
    padding-top: 2px;
}

<div class="markerHolder" style="display: none">
    <div class="markerIcon">
        <div class="top">HEADER<br><span id="value">888</span></div>
        <div class="arrow"></div>
    </div>
</div>

var $marker = $('#value').text('99');
var marker = new ftzMarker(L.latLng(lat, lng), {
    icon: L.divIcon({
        html: $('.markerHolder').html()
    })
})
 

Ответ №3:

Единственное решение, которое я могу придумать, — это создать два маркера, один с изображением, а другой с текстом, и добавить текстовый маркер в тот же якорь, что и маркер изображения, но слой над ним. Для этого потребуются некоторые функции для привязки двух маркеров, если вы хотите, чтобы маркер можно было перетаскивать (прослушиватель событий, который прослушивает один маркер, получает его координаты и присваивает координаты второму маркеру, чтобы он также перемещался. Сложно, но возможно.

Ответ №4:

Существует решение, которое может быть полезным в этом случае.

Вы можете использовать альтернативный «URL» с svg в кодировке base64:

 var svg = '<svg width="400" height="110"><rect width="300" height="100" /></svg>';
icon.url = 'data:image/svg xml;charset=UTF-8;base64,'   btoa(svg);
 

JavaScript (Firefox) btoa() используется для получения кодировки base64 из текста SVG. Вы также можете использовать http://dopiaza.org/tools/datauri/index.php для создания URL-адресов базовых данных.

Вот полный пример jsfiddle:

 <!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
    </head>
    <body>
        <div id="map" style="width: 500px; height: 400px;"></div>
        <script type="text/javascript">
            var map = new google.maps.Map(document.getElementById('map'), {
                zoom: 10,
                center: new google.maps.LatLng(-33.92, 151.25),
                mapTypeId: google.maps.MapTypeId.ROADMAP
            });

            var template = [
                '<?xml version="1.0"?>',
                    '<svg width="26px" height="26px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">',
                        '<circle stroke="#222" fill="{{ color }}" cx="50" cy="50" r="35"/>',
                    '</svg>'
                ].join('n');
            var svg = template.replace('{{ color }}', '#800');

            var docMarker = new google.maps.Marker({
                position: new google.maps.LatLng(-33.92, 151.25),
                map: map,
                title: 'Dynamic SVG Marker',
                icon: { url: 'data:image/svg xml;charset=UTF-8;base64,'   btoa(svg) }
              });
        </script>
    </body>
</html>
 

Дополнительную информацию и другое решение InfoBox можно найти здесь.

Хотя этот ответ может быть слишком поздним для вас, он может помочь другим, ищущим решение той же проблемы.