【问题标题】:Create Google Maps MarkerImage from SVG in DOM在 DOM 中从 SVG 创建 Google Maps MarkerImage
【发布时间】:2015-07-10 18:09:46
【问题描述】:

我正在尝试在 Google 地图中创建一个动态 SVG 标记(基本上每个标记的 SVG 文本部分都会发生变化),但我正在努力解决它的动态方面。正如您在下面的代码中看到的,我可以使用来自静态 url 的 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 或客户端代码的建议。

【问题讨论】:

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


    【解决方案1】:

    MarkerImage 在地图 v3 中已被弃用。

    无论如何,请查看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 中还有其他方法可以轻松地将文本置于顶部。

    【讨论】:

    • 谢谢@TerryTate。我已经尝试过使用 SVG 的多边形部分的路径并且效果很好,但是在标记上获取我的动态文本是我没有成功的地方。
    • 没问题。如果 svg 部分正常工作,您可以发布您尝试添加文本的内容吗?
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        有一个解决方案可能对这种情况有所帮助。

        您可以使用带有 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 来生成基础数据 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;base64,' + btoa(svg) }
                      });
                </script>
            </body>
        </html>
        

        更多信息和使用InfoBox 的其他解决方案可以在here 找到。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-10
          • 1970-01-01
          • 2011-11-22
          • 2014-07-19
          • 2017-04-21
          • 1970-01-01
          相关资源
          最近更新 更多