[google-maps] Google Maps API v3에서 SVG 마커를 사용하는 방법

변환 된 image.svg를 Google지도 아이콘으로 사용할 수 있습니까? 내 png 이미지를 svg로 변환하고 회전 할 수있는 Google지도 기호처럼 사용하고 싶습니다. 나는 이미 구글지도 기호를 사용하려고했지만 자동차, 사람 등과 같은 아이콘을 갖고 싶습니다. 그래서이 예제 사이트와 마찬가지로 일부 png 파일을 svg로 변환했습니다 . http : / /www.goprotravelling.com/



답변

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가 필요하고 클라이언트 측에서 수정할 수 있도록하려면 (예 : 텍스트 변경, 세부 정보 숨기기 등) 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 마커를 지원하려면 여기에 설명 된대로 두 가지 작은 조정이 필요합니다 . IE의 SVG 마커 . IE를 지원하도록 예제 코드를 업데이트했습니다.


답변

나는이 포스트가 조금 오래되었다는 것을 알고있다. 그러나 나는 비명을지를 수있을 정도로 이것에 대한 나쁜 정보를 너무 많이 보았다. 그래서 저는 제가 아는 완전히 다른 접근 방식으로 2 센트를 투자해야합니다. 많은지도에서 안정적으로 사용하기 때문입니다. 그 외에도 OP는 화살표 마커가지도에서 가리키는 위치를 변경하는 자체 x, y 축을 중심으로 아이콘을 회전하는 것과는 다른지도 지점을 중심으로 화살표 마커를 회전하는 기능을 원한다고 생각합니다.

첫째, Google지도와 SVG를 가지고 놀기 때문에 Google이 마커 (또는 실제로 기호)에 대한 SVG 구현을 배포하는 방식을 수용해야합니다. Google은 SVG 마커 이미지의 앵커를 SVG viewBox의 왼쪽 상단 모서리가 아닌 0,0으로 설정합니다. 이 문제를 해결하려면 SVG 이미지를 약간 다르게 그려서 Google이 원하는 것을 제공해야합니다. 예, 대답은 SVG 편집기 (Illustrator, Inkscape 등)에서 실제로 SVG 경로를 만드는 방식에 있습니다. .).

첫 번째 단계는 viewBox를 제거하는 것입니다. 이것은 XML의 viewBox를 0으로 설정하여 수행 할 수 있습니다 … 맞습니다. viewBox에 대한 일반적인 4 개의 인수 대신 0이 하나뿐입니다. 그러면보기 상자가 꺼집니다 (예, 의미 상 정확함). 이 작업을 수행하면 이미지의 크기가 즉시 점프하는 것을 알 수 있습니다. 이는 svg에 더 이상 이미지 크기를 조정할 기본 (viewBox)이 없기 때문입니다. 따라서 SVG 편집기의 XML 편집기에 이미지를 넣을 실제 픽셀 수로 너비와 높이를 설정하여 해당 참조를 직접 만듭니다.

XML 편집기에서 svg 이미지의 너비와 높이를 설정하여 이미지 크기 조정을위한 기준선을 만들고이 크기는 기본적으로 마커 크기 속성의 값 1이됩니다. 마커의 동적 크기 조정에 대한 이점을 확인할 수 있습니다.

이제 이미지 크기가 조정되었으므로 앵커로 사용하려는 이미지 부분이 svg 편집기의 0,0 좌표 위에 올 때까지 이미지를 이동합니다. 이 작업을 마치면 svg 경로 의 d 속성 값을 복사합니다 . 숫자의 약 절반이 음수임을 알 수 있습니다. 이는 viewBox 대신 이미지의 0,0에 대한 앵커 포인트를 정렬 한 결과입니다.

이 기술을 사용하면지도의 위도 및 경도 지점을 중심으로 마커를 올바르게 회전 할 수 있습니다. 이것은 원하는 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>

이것이 바로 Maps API의 SYMBOL 클래스에서 사용할 수있는 몇 가지 기호에 대해 Google이 수행하는 작업이므로 확신 할 수없는 경우 … 어쨌든 이것이 SVG 마커를 올바르게 만들고 설정하는 데 도움이되기를 바랍니다. 귀하의 Google지도는 노력합니다.


답변

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


답변

상황이 더 나아지고 있습니다. 이제 SVG 파일을 사용할 수 있습니다.

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


답변

이 스레드의 다른 사람들이 언급했듯이 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 조작이 도움이되지 않습니다.

(일부 댓글에 언급 된 것을 알고 있지만 놓치기 쉽습니다.이 정보는 다양한 경우에 도움이되었습니다)


답변

확인! 내 웹에서 곧이 작업을 수행했습니다. 사용자 지정 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>