Як використовувати маркери SVG в API Карт Google v3


91

Чи можу я використовувати свій перетворений image.svg як піктограму карти Google. Я перетворював своє зображення у форматі png у формат svg, і я хочу використовувати цей символ на карті Google, який можна повертати. Я вже намагався використовувати символ google map, але я хочу мати такий значок, як автомобіль, людина тощо ... Ось чому я перетворив свої файли png на svg, як і на цьому прикладі сайту, що він використовує для цих http: / /www.goprotravelling.com/


1
Для тих, хто шукає подібне запитання: часткове рішення, сумісне з IE 9+, тут: stackoverflow.com/a/30890373/634386 розмістить SVG у DOM замість на полотні, щоб ви могли маніпулювати CSS3 після (якщо ви дивлячись, щоб обертати цей елемент на льоту).
Mike Kormendy

Відповіді:


144

Ви можете відтворити свою піктограму за допомогою позначення контуру SVG .

Докладнішу інформацію див. У документації Google .

Ось базовий приклад:

var icon = {

    path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
    fillColor: '#FF0000',
    fillOpacity: .6,
    anchor: new google.maps.Point(0,0),
    strokeWeight: 0,
    scale: 1
}

var marker = new google.maps.Marker({
    position: event.latLng,
    map: map,
    draggable: false,
    icon: icon
});

Ось робочий приклад того, як відобразити та масштабувати піктограму SVG маркера:

Демонстрація JSFiddle

Редагувати:

Інший приклад тут із складною піктограмою:

Демонстрація JSFiddle

Редагувати 2:

І ось як ви можете мати файл SVG як піктограму:

Демонстрація JSFiddle


, дуже складно зробити автомобіль svg.
jemz

У вас є зображення SVG тієї машини, яку ви хочете? Тоді просто відкрийте його за допомогою текстового редактора і знайдіть у ньому шлях!
MrUpsidown

3
SVG зазвичай використовується для значків та інших символів. Один колір. Це просто шлях, як буква шрифтом. Перевагами є те, що ви можете легко масштабувати його, обертати та змінювати колір, не втрачаючи якості. Це векторна фігура.
MrUpsidown

1
Це було одне з найкорисніших речей, які я прочитав цього року! Велике спасибі
Джонатан Ла'Фей

2
@MrUpsidown Але, звичайно, SVG чудово працює за межами карт - ніколи там не виникало проблем. Це пов’язано з помилкою в підтримці Google SVG у їх рендерінгу полотна - яку можна вимкнути, щоб SVG замість цього вставляли в DOM. Тоді є проблема з розрахунковими розмірами маркерів, які є кілька властивостей в реалізації маркерів карти , які можуть змусити size.I've знайти часткове рішення тут: stackoverflow.com/a/30890373/634386
Майк Корменді

68

Якщо вам потрібен повний svg не лише шлях, і ви хочете, щоб його можна було модифікувати на стороні клієнта (наприклад, змінити текст, приховати деталі, ...), ви можете використовувати альтернативну "URL-адресу" даних із включеним svg:

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,' + encodeURIComponent(svg), scaledSize: new google.maps.Size(20, 20) },
optimized: false
            });

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

Додаткову інформацію можна знайти тут .

Уникайте кодування base64:

Щоб уникнути кодування base64, ви можете замінити 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(svg)на'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg)

Це має працювати з сучасними браузерами аж до IE9. Перевага полягає в тому, що encodeURIComponentфункція js за замовчуванням доступна у всіх сучасних браузерах. Ви також можете отримати менші посилання, але вам потрібно протестувати це і розглянути можливість використання 'замість цього "у своєму svg.

Також див. Оптимізацію SVG в URI даних для отримання додаткової інформації.

Підтримка IE: Для підтримки SVG Markers в IE потрібні дві невеликі адаптації, як описано тут: SVG Markers в IE . Я оновив приклад коду для підтримки IE.


3
Хороша інформація, але швидко зауважте, що кодування base64 насправді не є необхідним чи бажаним. Замість цього ви можете використовувати кодування svg безпосередньо в URI даних, наприклад data:image/svg+xml;utf8,. Більше інформації: css-tricks.com/probably-dont-base64-svg
Джош із Карібу

Ви маєте рацію, було б чудово, якби ми змогли уникнути кодування base64. Як ви це зробили, могли б навести приклад? Якщо я просто додаю код svg до URI, він не працює з деякими символами, як-от #ви використовували кодування URL-адреси?
Том,

Я повинен згадати, що він закодований utf8; svg - це формат. Надане посилання має кілька прикладів.
Джош із Карібу

1
Як використовувати обертати зображення svg, використовуючи це?
Сомнатхарат

Хіба ми всі не любимо IE;) Як завжди, це вимагає додаткової роботи, щоб вона працювала у всіх браузерах. Я адаптував приклад для підтримки IE, сподіваюся, це допоможе.
Том

30

Я знаю, що цей пост трохи старий, але я бачив стільки поганої інформації про це в SO, що я міг кричати. Тож я просто повинен кинути свої два центи із зовсім іншим підходом, який, на мою думку, працює, оскільки я надійно використовую його на багатьох картах. Крім того, я вважаю, що ОП хотіла можливість повертати маркер стрілки навколо точки на карті, що відрізняється від обертання значка навколо власної осі х, у, яка буде змінюватися там, де маркер стрілки вказує на карті.

По-перше, пам’ятайте, що ми граємо з картами Google і SVG, тому ми повинні враховувати спосіб, яким Google застосовує свою реалізацію SVG для маркерів (або власне символів). Google встановлює якір для зображення маркера SVG на рівні 0,0, що НЕ є лівим верхнім кутом вікна SVG viewBox. Для того, щоб обійти це, ви повинні намалювати своє зображення SVG трохи інакше, щоб надати Google бажане ... так, відповідь полягає в тому, як ви насправді створюєте шлях SVG у своєму редакторі SVG (Illustrator, Inkscape тощо). .).

Першим кроком є ​​позбавлення від viewBox. Це можна зробити, встановивши viewBox у вашому XML на 0 ... правильно, просто один нуль замість звичайних чотирьох аргументів для viewBox. Це вимикає поле перегляду (і так, це семантично правильно). Ви, мабуть, помітите, що розмір вашого зображення негайно стрибає, коли ви це робите, і це тому, що svg більше не має основи (viewBox) для масштабування зображення. Отже, ми створюємо це посилання безпосередньо, встановлюючи ширину та висоту для фактичної кількості пікселів, які ви хочете, щоб ваше зображення знаходилось у редакторі XML вашого редактора SVG.

Встановивши ширину та висоту зображення svg у редакторі XML, ви створюєте базову лінію для масштабування зображення, і цей розмір стає значенням 1 для властивостей масштабу маркера за замовчуванням. Ви можете побачити перевагу цього в динамічному масштабуванні маркера.

Тепер, коли у вас є розмір вашого зображення, переміщуйте зображення до тих пір, поки частина зображення, яку ви хочете отримати, оскільки прив'язка не перевищує 0,0 координат редактора svg. Після цього скопіюйте значення атрибута d шляху svg. Ви помітите, що приблизно половина цифр є від’ємними, що є результатом вирівнювання точки опори для 0,0 зображення замість viewBox.

Потім цей метод дозволить вам правильно обертати маркер навколо точки широти та довжини на карті. Це єдиний надійний спосіб прив’язати потрібну точку на маркері svg до широти та довжини місця розмітки маркера.

Я намагався зробити JSFiddle для цього , але в реалізації є деяка помилка, одна з причин, чому я не так люблю переосмислений код. Тож натомість я подав нижче повністю самостійний приклад, який ви можете спробувати, адаптувати та використовувати як довідковий матеріал. Це той самий код, який я спробував у JSFiddle, але який не вдався, але він пропливає через Firebug без хитання.

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8" />
    <meta name="viewport"  content="width=device-width, initial-scale=1" />
    <meta name="author"    content="Drew G. Stimson, Sr. ( Epiphany )" />
    <title>Create Draggable and Rotatable SVG Marker</title>
    <script src="http://maps.googleapis.com/maps/api/js?sensor=false"> </script>
    <style type="text/css">
      #document_body {
        margin:0;
        border: 0;
        padding: 10px;
        font-family: Arial,sans-serif;
        font-size: 14px;
        font-weight: bold;
        color: #f0f9f9;
        text-align: center;
        text-shadow: 1px 1px 1px #000;
        background:#1f1f1f;
      }
      #map_canvas, #rotation_control {
        margin: 1px;
        border:1px solid #000;
        background:#444;
        -webkit-border-radius: 4px;
           -moz-border-radius: 4px;
                border-radius: 4px;
      }
      #map_canvas { 
        width: 100%;
        height: 360px;
      }
      #rotation_control { 
        width: auto;
        padding:5px;
      }
      #rotation_value { 
        margin: 1px;
        border:1px solid #999;
        width: 60px;
        padding:2px;
        font-weight: bold;
        color: #00cc00;
        text-align: center;
        background:#111;
        border-radius: 4px;
      }
</style>

<script type="text/javascript">
  var map, arrow_marker, arrow_options;
  var map_center = {lat:41.0, lng:-103.0};
  var arrow_icon = {
    path: 'M -1.1500216e-4,0 C 0.281648,0 0.547084,-0.13447 0.718801,-0.36481 l 17.093151,-22.89064 c 0.125766,-0.16746 0.188044,-0.36854 0.188044,-0.56899 0,-0.19797 -0.06107,-0.39532 -0.182601,-0.56215 -0.245484,-0.33555 -0.678404,-0.46068 -1.057513,-0.30629 l -11.318243,4.60303 0,-26.97635 C 5.441639,-47.58228 5.035926,-48 4.534681,-48 l -9.06959,0 c -0.501246,0 -0.906959,0.41772 -0.906959,0.9338 l 0,26.97635 -11.317637,-4.60303 c -0.379109,-0.15439 -0.812031,-0.0286 -1.057515,0.30629 -0.245483,0.33492 -0.244275,0.79809 0.0055,1.13114 L -0.718973,-0.36481 C -0.547255,-0.13509 -0.281818,0 -5.7002158e-5,0 Z',
    strokeColor: 'black',
    strokeOpacity: 1,
    strokeWeight: 1,
    fillColor: '#fefe99',
    fillOpacity: 1,
    rotation: 0,
    scale: 1.0
  };

function init(){
  map = new google.maps.Map(document.getElementById('map_canvas'), {
    center: map_center,
    zoom: 4,
    mapTypeId: google.maps.MapTypeId.HYBRID
  });
  arrow_options = {
    position: map_center,
    icon: arrow_icon,
    clickable: false,
    draggable: true,
    crossOnDrag: true,
    visible: true,
    animation: 0,
    title: 'I am a Draggable-Rotatable Marker!' 
  };
  arrow_marker = new google.maps.Marker(arrow_options);
  arrow_marker.setMap(map);
}
function setRotation(){
  var heading = parseInt(document.getElementById('rotation_value').value);
  if (isNaN(heading)) heading = 0;
  if (heading < 0) heading = 359;
  if (heading > 359) heading = 0;
  arrow_icon.rotation = heading;
  arrow_marker.setOptions({icon:arrow_icon});
  document.getElementById('rotation_value').value = heading;
}
</script>
</head>
<body id="document_body" onload="init();">
  <div id="rotation_control">
    <small>Enter heading to rotate marker&nbsp;&nbsp;&nbsp;&nbsp;</small>
    Heading&deg;<input id="rotation_value" type="number" size="3" value="0" onchange="setRotation();" />
    <small>&nbsp;&nbsp;&nbsp;&nbsp;Drag marker to place marker</small>
    </div>
    <div id="map_canvas"></div>
</body>
</html>

Це саме те, що Google робить для своїх власних кількох символів, доступних у класі SYMBOL API Maps, тому, якщо це вас не переконує ... У будь-якому випадку, я сподіваюся, це допоможе вам правильно зробити і встановити маркер SVG для Ваші мапи Google.


2
Приємна відповідь, я створив робочу скрипку вашого коду, щоб люди могли бачити jsfiddle.net/v2pjfp7r
Роб Шмукер

"<3" Це важлива інформація, яка повинна бути частиною документації Google.
користувач7653815

12

Так, ви можете використовувати файл .svg для значка так само, як і .png або інший формат файлу зображення. Просто встановіть URL-адресу значка в каталог, де знаходиться файл .svg. Наприклад:

var icon = {
        url: 'path/to/images/car.svg',
        size: new google.maps.Size(sizeX, sizeY),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(sizeX/2, sizeY/2)
};

var marker = new google.maps.Marker({
        position: event.latLng,
        map: map,
        draggable: false,
        icon: icon
});

1
Об'єкт піктограм, який ви показуєте, призначений для стандартного маркера, а не маркера SVG. Маркер svg використовує властивості класу символів, які потім призначаються як властивість піктограми класу маркера. (див. об'єкт піктограми MrUpsidown для правильного посилання ...)
Богоявлення

2
Це також порушиться, якщо у SVG є більше одного "d" шляху (зазвичай пов'язаного з кількома шарами на зображенні svg).
Богоявлення

2
Зверніть увагу, що у вашому файлі svg слід чітко встановити розміри піктограми так: width="33px" height="50px"- див. Stackoverflow.com/a/21783089/165673
Ярін,

10

Справа йде краще, зараз ви можете використовувати файли SVG.

        marker = new google.maps.Marker({
            position: {lat: 36.720426, lng: -4.412573},
            map: map,
            draggable: true,
            icon: "img/tree.svg"
        });

1
не допускає обертання
Метт Вестлейк

5

Як згадували інші в цьому потоці, не забудьте явно встановити атрибути width і height у svg так:

<svg id="some_id" data-name="some_name" xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 26 42"
     width="26px" height="42px">

якщо ви цього не зробите, жодна маніпуляція з js не може вам допомогти, оскільки gmaps не матиме системи відліку і завжди використовуватиме стандартний розмір.

(я знаю, що це згадувалося в деяких коментарях, але їх легко пропустити. Ця інформація мені допомагала у різних випадках)


1

ГАРАЗД! Я зробив це незабаром у своєму Інтернеті, я намагаюся двома способами створити власний маркер карти Google, цей код запуску canvg.js є найкращою сумісністю для браузера. Коментований код не підтримує IE11 в даний час.

var marker;
var CustomShapeCoords = [16, 1.14, 21, 2.1, 25, 4.2, 28, 7.4, 30, 11.3, 30.6, 15.74, 25.85, 26.49, 21.02, 31.89, 15.92, 43.86, 10.92, 31.89, 5.9, 26.26, 1.4, 15.74, 2.1, 11.3, 4, 7.4, 7.1, 4.2, 11, 2.1, 16, 1.14];

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 13,
    center: {
      lat: 59.325,
      lng: 18.070
    }
  });
  var markerOption = {
    latitude: 59.327,
    longitude: 18.067,
    color: "#" + "000",
    text: "ha"
  };
  marker = createMarker(markerOption);
  marker.setMap(map);
  marker.addListener('click', changeColorAndText);
};

function changeColorAndText() {
  var iconTmpObj = createSvgIcon( "#c00", "ok" );
  marker.setOptions( {
                icon: iconTmpObj
            } );
};

function createMarker(options) {
  //IE MarkerShape has problem
  var markerObj = new google.maps.Marker({
    icon: createSvgIcon(options.color, options.text),
    position: {
      lat: parseFloat(options.latitude),
      lng: parseFloat(options.longitude)
    },
    draggable: false,
    visible: true,
    zIndex: 10,
    shape: {
      coords: CustomShapeCoords,
      type: 'poly'
    }
  });

  return markerObj;
};

function createSvgIcon(color, text) {
  var div = $("<div></div>");

  var svg = $(
    '<svg width="32px" height="43px"  viewBox="0 0 32 43" xmlns="http://www.w3.org/2000/svg">' +
    '<path style="fill:#FFFFFF;stroke:#020202;stroke-width:1;stroke-miterlimit:10;" d="M30.6,15.737c0-8.075-6.55-14.6-14.6-14.6c-8.075,0-14.601,6.55-14.601,14.6c0,4.149,1.726,7.875,4.5,10.524c1.8,1.801,4.175,4.301,5.025,5.625c1.75,2.726,5,11.976,5,11.976s3.325-9.25,5.1-11.976c0.825-1.274,3.05-3.6,4.825-5.399C28.774,23.813,30.6,20.012,30.6,15.737z"/>' +
    '<circle style="fill:' + color + ';" cx="16" cy="16" r="11"/>' +
    '<text x="16" y="20" text-anchor="middle" style="font-size:10px;fill:#FFFFFF;">' + text + '</text>' +
    '</svg>'
  );
  div.append(svg);

  var dd = $("<canvas height='50px' width='50px'></cancas>");

  var svgHtml = div[0].innerHTML;

  canvg(dd[0], svgHtml);

  var imgSrc = dd[0].toDataURL("image/png");
  //"scaledSize" and "optimized: false" together seems did the tricky ---IE11  &&  viewBox influent IE scaledSize
  //var svg = '<svg width="32px" height="43px"  viewBox="0 0 32 43" xmlns="http://www.w3.org/2000/svg">'
  //    + '<path style="fill:#FFFFFF;stroke:#020202;stroke-width:1;stroke-miterlimit:10;" d="M30.6,15.737c0-8.075-6.55-14.6-14.6-14.6c-8.075,0-14.601,6.55-14.601,14.6c0,4.149,1.726,7.875,4.5,10.524c1.8,1.801,4.175,4.301,5.025,5.625c1.75,2.726,5,11.976,5,11.976s3.325-9.25,5.1-11.976c0.825-1.274,3.05-3.6,4.825-5.399C28.774,23.813,30.6,20.012,30.6,15.737z"/>'
  //    + '<circle style="fill:' + color + ';" cx="16" cy="16" r="11"/>'
  //    + '<text x="16" y="20" text-anchor="middle" style="font-size:10px;fill:#FFFFFF;">' + text + '</text>'
  //    + '</svg>';
  //var imgSrc = 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg);

  var iconObj = {
    size: new google.maps.Size(32, 43),
    url: imgSrc,
    scaledSize: new google.maps.Size(32, 43)
  };

  return iconObj;
};
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Your Custom Marker </title>
  <style>
    /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
    #map {
      height: 100%;
    }
    /* Optional: Makes the sample page fill the window. */
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
  </style>
</head>

<body>
  <div id="map"></div>
    <script src="https://canvg.github.io/canvg/canvg.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script async defer src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
</body>

</html>


-4

Вам потрібно пройти optimized: false.

Напр

var img = { url: 'img/puff.svg', scaledSide: new google.maps.Size(5, 5) };
new google.maps.Marker({position: this.mapOptions.center, map: this.map, icon: img, optimized: false,});

Не минаючи optimized: false, мій svg вийшов у вигляді статичного зображення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.