Google Maps API v3'te SVG işaretçileri nasıl kullanılır?


91

Dönüştürülmüş image.svg'mi google harita simgesi olarak kullanabilir miyim? PNG resmimi svg'ye dönüştürüyordum ve bunu döndürülebilen google harita sembolü gibi kullanmak istiyorum. Zaten google harita sembolünü kullanmayı denedim ama araba, adam gibi bir ikona sahip olmak istiyorum ... Bu yüzden bazı png dosyalarımı svg'ye dönüştürdüm, tıpkı bu örnek sitede olduğu gibi bu http: / /www.goprotravelling.com/


1
Bu benzer soruyu arayanlar için: burada kısmi bir IE 9+ uyumlu çözüm: stackoverflow.com/a/30890373/634386 , tuval yerine DOM'a bir SVG yerleştirir, böylece daha sonra CSS3 ile işleyebilirsiniz. bu öğeyi özellikle anında döndürmek istiyor).
Mike Kormendy

Yanıtlar:


146

Simgenizi SVG Yolu gösterimini kullanarak oluşturabilirsiniz .

Daha fazla bilgi için Google belgelerine bakın .

İşte temel bir örnek:

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
});

Bir işaretçi SVG simgesinin nasıl görüntüleneceği ve ölçekleneceği ile ilgili çalışan bir örnek:

JSFiddle demosu

Düzenle:

Burada karmaşık bir simgeye sahip başka bir örnek:

JSFiddle demosu

Düzenleme 2:

Ve bir SVG dosyasına nasıl sahip olabileceğiniz aşağıda açıklanmıştır:

JSFiddle demosu


, araba svg yapmak çok zor.
jemz

İstediğiniz arabanın SVG resmi var mı? Sonra bir metin düzenleyiciyle açın ve içindeki yolu bulun!
MrUpsidown

3
SVG genellikle simgeler ve diğer semboller için kullanılır. Tek renk. Yazı tipindeki bir harf gibi sadece bir yol. Avantajları, kaliteyi kaybetmeden kolayca ölçeklendirebilmeniz, döndürebilmeniz ve rengini değiştirebilmenizdir. Bu bir vektör şekli.
MrUpsidown

1
Bu yıl okuduğum en yararlı şeylerden biri buydu! Çok teşekkürler
Jonathan La'Fey

2
@MrUpsidown Ama tabii ki SVG haritaların dışında iyi çalışıyor - orada hiç sorun yaşamadım. Bunun, Google'ın tuval oluşturmada SVG desteğindeki bir aksaklıkla ilgisi vardır - bu, SVG'lerin bunun yerine DOM'a eklenebilmesi için kapatılabilir. Daha sonra, boyutu zorlayabilen harita işaretçileri için uygulamada birkaç özellik bulunan işaretleyicilerin hesaplanmış boyutlarıyla ilgili sorun var. Burada kısmi bir çözüm buldum: stackoverflow.com/a/30890373/634386
Mike Kormendy

68

Yalnızca bir yol değil tam bir svg'ye ihtiyacınız varsa ve bunun istemci tarafında değiştirilebilir olmasını istiyorsanız (örn. Metni değiştirme, ayrıntıları gizleme, ...) svg dahil alternatif bir veri 'URL' kullanabilirsiniz:

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 (), SVG metninden base64 kodlamasını almak için kullanılır. Temel veri URL'leri oluşturmak için http://dopiaza.org/tools/datauri/index.php'yi de kullanabilirsiniz .

İşte tam bir örnek 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>

Ek Bilgiler burada bulunabilir .

Base64 kodlamasından kaçının:

Base64 kodlamasından kaçınmak için 'data:image/svg+xml;charset=UTF-8;base64,' + btoa(svg)şununla değiştirebilirsiniz:'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg)

Bu, IE9'a kadar modern tarayıcılarla çalışmalıdır. Bunun avantajı, encodeURIComponentvarsayılan bir js işlevi olması ve tüm modern tarayıcılarda mevcut olmasıdır. Daha küçük bağlantılar da alabilirsiniz, ancak bunu test etmeniz ve svg'niz 'yerine kullanmayı düşünmeniz gerekir ".

Ayrıca ek bilgi için veri URI'lerinde SVG'leri optimize etme konusuna bakın .

IE desteği: IE'de SVG İşaretleyicileri desteklemek için burada açıklandığı gibi iki küçük uyarlamaya ihtiyaç vardır: IE'de SVG İşaretleyicileri . IE'yi desteklemek için örnek kodu güncelledim.


3
İyi bilgi, ancak base64 kodlamasının aslında gerekli veya arzu edilmediğini unutmayın. Bunun yerine svg kodlamasını doğrudan veri URI'sinde kullanabilirsiniz data:image/svg+xml;utf8,. Daha fazla bilgi: css-tricks.com/probably-dont-base64-svg
Josh

Haklısın, base64 kodlamasını önleyebilseydik harika olurdu. Nasıl yaptın bir örnek verebilir misin? Svg kodunu URI'ye eklersem, #URL kodlamasını kullandığınız gibi bazı karakterlerle çalışmaz mı?
Tom

Utf8 kodlu olduğunu belirtmeliyim; svg, formattır. Sağlanan bağlantının birkaç örneği vardır.
Qaribou'dan Josh

1
Bunu kullanarak döndürme svg resmi nasıl kullanılır?
Somnath Kharat

IE'yi hepimiz sevmiyor muyuz;) Her zamanki gibi tüm tarayıcılarda çalışması için biraz ek çalışma gerektirir. Örneği IE'yi desteklemek için uyarladım, umarım bu yardımcı olur.
Tom

31

Bu yazının biraz eski olduğunu biliyorum, ancak bu konuda o kadar kötü bilgi gördüm ki, SO'da çığlık atabilirim. Bu yüzden, birçok haritada güvenilir bir şekilde kullandığım için işe yaradığını bildiğim tamamen farklı bir yaklaşımla iki sentimi atmalıyım. Bunun yanı sıra, OP'nin ok işaretini harita noktasının etrafında da döndürme yeteneğini istediğine inanıyorum ki bu, simgeyi kendi x, y ekseni etrafında döndürmekten farklı olarak ok işaretinin haritada gösterdiği yeri değiştirecektir.

Öncelikle, Google haritaları ve SVG ile oynadığımızı unutmayın; bu nedenle, Google'ın işaretçiler (veya gerçekte semboller) için SVG uygulamasını dağıtma yöntemine uyum sağlamalıyız. Google, SVG işaretleyici resmi için bağlantısını, SVG viewBox'ın sol üst köşesi OLMAYAN 0,0 olarak ayarlar. Bunu aşmak için, Google'a istediğini vermek için SVG resminizi biraz farklı bir şekilde çizmelisiniz ... evet yanıt, SVG düzenleyicinizde (Illustrator, Inkscape, vb.) SVG yolunu gerçekte oluşturma şeklinizdedir. .).

İlk adım, viewBox'tan kurtulmaktır. Bu, XML'inizdeki viewBox'ı 0 olarak ayarlayarak yapılabilir ... bu doğru, viewBox için olağan dört bağımsız değişken yerine sadece bir sıfır. Bu, görünüm kutusunu kapatır (ve evet, bu anlamsal olarak doğrudur). Bunu yaptığınızda, muhtemelen görüntünüzün boyutunun hemen atladığını fark edeceksiniz ve bunun nedeni, svg'nin artık görüntüyü ölçeklemek için bir tabanı (viewBox) olmamasıdır. Bu nedenle, genişliğini ve yüksekliğini, resminizin SVG düzenleyicinizin XML düzenleyicisinde olmasını istediğiniz gerçek piksel sayısına ayarlayarak doğrudan bu referansı oluşturuyoruz.

XML düzenleyicide svg görüntüsünün genişliğini ve yüksekliğini ayarlayarak görüntünün ölçeklenmesi için bir temel oluşturursunuz ve bu boyut, varsayılan olarak işaretçi ölçek özellikleri için 1 değeri olur. Markörün dinamik ölçeklendirilmesi için bunun avantajını görebilirsiniz.

Artık resminizi boyutlandırdığınıza göre, görüntüyü, çapa svg düzenleyicinin 0,0 koordinatlarının üzerinde olduğundan, görüntünün olmasını istediğiniz kısmı kadar hareket ettirin. Bunu yaptıktan sonra , svg yolunun d özniteliğinin değerini kopyalayın . Sayıların yaklaşık yarısının negatif olduğunu fark edeceksiniz, bu da bağlantı noktanızı viewBox yerine görüntünün 0,0'ı ile hizalamanın sonucudur.

Bu tekniği kullanmak, haritadaki enlem ve boylam noktaları çevresinde işaretçiyi doğru şekilde döndürmenize olanak sağlar. Bu, svg işaretçisi üzerindeki noktayı işaretçi konumunun enlem ve boylamına bağlamanın tek güvenilir yoludur.

Bunun için bir JSFiddle yapmaya çalıştım , ancak orada uygulamada bazı hatalar var, yeniden yorumlanmış koddan çok hoşlanmamamın nedenlerinden biri. Bunun yerine, deneyebileceğiniz, uyarlayabileceğiniz ve referans olarak kullanabileceğiniz tamamen bağımsız bir örneği aşağıya ekledim. Bu, JSFiddle'da denediğim ve başarısız olan kodun aynısı, ancak Firebug üzerinden sızlanmadan ilerliyor.

    <!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>

Bu tam olarak Google'ın Maps API SYMBOL sınıfında bulunan kendi birkaç sembolü için yaptığı şeydir, bu yüzden bu sizi ikna etmezse ... Her neyse, umarım bu sizin için doğru bir SVG işaretçisi oluşturmanıza ve ayarlamanıza yardımcı olur Google haritalarınız sona erer.


2
Güzel cevap, insanların jsfiddle.net/v2pjfp7r
Rob Schmuecker

"<3" Bu, Google dokümanlarının bir parçası olması gereken temel bilgidir.
user7653815

12

Evet, simge için .png veya başka bir görüntü dosyası biçiminde olduğu gibi bir .svg dosyası kullanabilirsiniz. Simgenin url'sini .svg dosyasının bulunduğu dizine ayarlayın. Örneğin:

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
Gösterdiğiniz simge nesnesi bir SVG işaretçisi değil, standart bir işaretçi içindir. Bir svg işaretçisi, sembol sınıfının özelliklerini kullanır ve bunlar daha sonra işaretçi sınıfının simge özelliği olarak atanır. (Doğru referans için MrUpsidown simge nesnesine bakın ...)
Epiphany

2
Bu ayrıca, SVG'nin birden fazla 'd' yolu varsa (genellikle svg görüntüsünde birden fazla katmanla ilişkilendirilir) bozulur.
Yortu

2
Svg dosyanızın simgenin boyutlarını açıkça şu şekilde ayarlaması gerektiğini unutmayın: width="33px" height="50px"- bkz. Stackoverflow.com/a/21783089/165673
Yarin

9

İşler daha iyi gidiyor, şu anda SVG dosyalarını kullanabilirsiniz.

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

1
rotasyona izin vermiyor
Matt Westlake

6

Bu konu başlığında başkaları tarafından belirtildiği gibi, svg'deki genişlik ve yükseklik özelliklerini şu şekilde açıkça ayarlamayı unutmayın :

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

Bunu yapmazsanız, hiçbir js manipülasyonu size yardımcı olamaz, çünkü boşluklar bir referans çerçevesine sahip olmayacak ve her zaman standart bir boyut kullanacaktır.

(Bazı yorumlarda bahsedildiğini biliyorum, ancak gözden kaçması kolay. Bu bilgi çeşitli durumlarda bana yardımcı oldu)


1

TAMAM! Bunu kısa süre içinde web'imde yaptım, özel google harita işaretleyicisini oluşturmak için iki yol deniyorum, bu çalıştırma kodu tarayıcı için en iyi uyumluluk canvg.js'dir. Yorumlanan Kod şu anda IE11'i desteklemiyor.

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

Geçmen gerek optimized: false .

Örneğin

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,});

Geçen olmadan optimized: false, benim svg statik bir resim olarak ortaya çıktı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.