从DOM中的SVG创建Google Maps MarkerImage

时间:2014-06-27 15:33:35

标签: jquery node.js google-maps d3.js leaflet

我正在尝试在Google地图中创建一个动态SVG标记(基本上每个标记的SVG更改的文本部分),但我正在努力应对它的动态方面。正如您在下面的代码中看到的,我可以使用静态网址中的new google.maps.MarkerImage()创建SVG标记。

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()将SVG DOM元素的内部html作为其第一个参数 - 它总是在寻找一个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中做到这一点(但最终失败了) - 为每个id创建一个新的SVG(甚至创建SVG,然后保存为PNG) - 但我认为在上面做所有事情会更有效率客户端。我愿意接受使用node.js或客户端代码的建议。

4 个答案:

答案 0 :(得分:0)

地图v3中已弃用

MarkerImage

无论如何,请查看Symbols from the Developers Guide,然后查看this example

根据该示例,试试这个:

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路径(文本等)中获得所有你想要的东西,但这应该可以让你在那里大部分时间。 Google Maps API中还有其他方法可以将文本放在首位,而不会有太多麻烦。

答案 1 :(得分:0)

在使用谷歌地图遇到上述问题之后,我决定开始使用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()
    })
})

答案 2 :(得分:0)

我能想到的唯一解决方法是,必须创建两个标记,一个带有图像,另一个带有文本,并在与图像标记相同的锚点上添加文本标记,但在其上方有一层。如果你想让标记可以拖动,这将需要一些绑定两个标记的函数(一个事件监听器,它可以监听一个标记,获取它的坐标,并将坐标分配给第二个标记,以便它也可以移动。整个,但是可能的。

答案 3 :(得分:0)

在这种情况下,有一种解决方案可能会有所帮助。

您可以使用带有base64编码的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生成基本数据网址。

以下是完整示例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的其他信息和其他解决方案here

虽然这个答案对你来说可能为时已晚,但它可能会帮助其他人寻找同一问题的解决方案。