Google Maps API v3でSVGマーカーを使用する方法


91

変換したimage.svgをgoogleマップアイコンとして使用できますか?私は自分のpng画像をsvgに変換していましたが、これを回転できるgoogleマップシンボルのように使用したいと思います。私はすでにグーグルマップシンボルを使用しようとしましたが、車や男などのアイコンを使用したいので、このサンプルサイトのように、いくつかのpngファイルをsvgに変換しました。 /www.goprotravelling.com/


1
この同様の質問を検索する人のために:IE 9+互換の部分的なソリューション:stackoverflow.com/a/30890373/634386は、キャンバスではなくDOMにSVGを配置するため、後でCSS3を操作できます(特にその場でその要素を回転させようとしています)。
マイクコルメンディ2016

回答:


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 14年

欲しい車のSVG画像はありますか?次に、テキストエディターで開き、パスを見つけます。
MrUpsidown 14年

3
SVGは通常、アイコンやその他の記号に使用されます。ワンカラー。フォントの文字のような単なるパスです。利点は、品質を失うことなく、簡単に拡大縮小、回転、色を変更できることです。それはベクトルの形です。
MrUpsidown 14年

1
それは今年私が読んだ中で最も有用なものの1つでした!どうもありがとう
Jonathan La'Fey

2
@MrUpsidownしかし、もちろんSVGはマップ以外でも問題なく機能しています。問題はありませんでした。これは、キャンバスレンダリングでのGoogleによるSVGのサポートの不具合に関係しています。これをオフにすると、代わりにSVGがDOMに挿入されます。次に、マーカーの計算されたサイズに問題があります。これは、サイズを強制できるマップマーカーの実装にいくつかのプロパティがあります。ここで部分的な解決策を見つけました:stackoverflow.com/a/30890373/634386
Mike Kormendy

68

パスだけでなく完全なsvgが必要で、クライアント側で変更可能にしたい場合(テキストの変更、詳細の非表示など)、svgが含まれている代替データ「URL」を使用できます。

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テキストからbase64エンコーディングを取得するために使用されます。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のます。

データURIでのSVGの最適化も参照してくださいでのください。

IEのサポート:IEで SVGマーカーをサポートするには、ここで説明する2つの小さな適応が必要です:IEでのSVGマーカー。IEをサポートするようにサンプルコードを更新しました。


3
良い情報ですが、base64エンコーディングは実際には必要でも望ましいものでもありません。代わりに、データURIで直接svgエンコーディングを使用できますdata:image/svg+xml;utf8,。詳細:css-tricks.com/probably-dont-base64-svg
Josh、2015年

base64エンコーディングを回避できればすばらしいと思います。どのようにそれを行うことができましたか?URIにsvgコードを追加しただけでは、#URLエンコーディングを使用したような一部の文字では機能しませんか?
トム

utf8でエンコードされていることに言及する必要があります。svgはフォーマットです。提供されているリンクにはいくつかの例があります。
Josh、Qaribouから

1
これを使用してsvg画像を回転させる方法は?
Somnath Kharat 2016

私たちは皆、IEが好きではありません;)いつものように、すべてのブラウザで動作させるには、追加の作業が必要です。この例をIEをサポートするように変更しました。これが役立つことを願っています。
トム

30

私はこの投稿が少し古いことを知っていますが、SOでこれに関する多くの悪い情報を見たので、悲鳴を上げることができました。だから私は多くのマップで確実に使用するので、私はうまくいくことがわかっているまったく異なるアプローチで私の2セントを投入しなければなりません。その上、私はOPが矢印マーカーをマップポイントを中心に回転する機能も欲しかったと思います。これは、アイコンをそれ自身のX、Y軸を中心に回転させるのとは異なり、矢印マーカーがマップ上のどこを指すかを変更します。

まず、GoogleマップとSVGで遊んでいることを思い出してください。そのため、Googleがマーカー(または実際にはシンボル)用のSVGの実装をデプロイする方法に対応する必要があります。GoogleはSVGマーカー画像のアンカーを0,0に設定しますが、これはSVGビューボックスの左上隅ではありません。これを回避するには、SVG画像を少し異なる方法で描画して、Googleに必要なものを提供する必要があります...はい、答えは、SVGエディター(Illustrator、Inkscapeなど)で実際にSVGパスを作成する方法です。 。)。

最初のステップは、viewBoxを取り除くことです。これは、XMLのviewBoxを0に設定することで実行できます。そうです、viewBoxの通常の4つの引数の代わりに、1つのゼロだけです。これはビューボックスをオフにします(そして、はい、これは意味的に正しいです)。これを行うと、画像のサイズがすぐにジャンプすることに気付くでしょう。これは、svgに画像をスケーリングするためのベース(viewBox)がなくなったためです。そのため、SVGエディターのXMLエディターで画像を表示したい実際のピクセル数に幅と高さを設定することで、その参照を直接作成します。

XMLエディターでsvg画像の幅と高さを設定することにより、画像のスケーリングのベースラインを作成します。このサイズは、デフォルトでマーカースケールプロパティの値1になります。これには、マーカーの動的なスケーリングに関する利点があります。

画像のサイズを変更したので、アンカーとして使用したい画像の部分がsvgエディターの0,0座標上になるまで画像を移動します。これを実行したら、dの値をコピーします、svgパスの属性の。数値の約半分が負であることがわかります。これは、viewBoxではなく画像の0,0にアンカーポイントを合わせた結果です。

この手法を使用すると、マップ上の緯度と経度のポイントを中心にしてマーカーを正しく回転させることができます。これは、SVGマーカー上のポイントをマーカー位置の緯度と経度にバインドする唯一の信頼できる方法です。

私はこのためにJSFiddleを作成しようとしましたが、実装にいくつかのバグがあります。これは、再解釈されたコードがあまり好きではない理由の1つです。そのため、代わりに、完全に自己完結型の例を以下に含めました。これらを試して、適応し、参照として使用できます。これは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がMaps APIのSYMBOLクラスで使用できるいくつかのシンボルに対して行っていることとまったく同じです。したがって、それが納得できない場合は...とにかく、これがSVGマーカーを正しく作成および設定するのに役立つことを願っていますあなたのグーグルマップの努力。



「<3」これは、Googleドキュメントの一部である必要がある重要な情報です。
user7653815

12

はい。.pngや他の画像ファイル形式と同じように、アイコンに.svgファイルを使用できます。アイコンの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アイコンオブジェクトを参照してください...)
Epiphany

2
これは、SVGに複数の「d」パス(通常はsvgイメージの複数のレイヤーに関連付けられている)がある場合にも機能しません。
エピファニー2015年

2
svgファイルでは、アイコンのサイズを次のように明示的に設定する必要があることに注意してください。width="33px" height="50px"- stackoverflow.com
a/

10

状況は良くなり、現在はSVGファイルを使用できます。

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

1
ローテーションは許可されていません
Matt Westlake

5

このスレッドの他の人が述べたように、次のように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">

gmapsは参照フレームを持たず、常に標準サイズを使用するため、これを行わないとjs操作は役に立ちません。

(一部のコメントで言及されていることは承知していますが、見落としがちです。この情報は、さまざまな場合に役立ちました)


1

OK!私はすぐにWebでこれを行いました。カスタムのGoogleマップマーカーを作成する2つの方法を試します。この実行コードは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は静的画像として表示されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.