繁体   English   中英

如何绘制一个保持在 leaflet.js map 中心的圆

[英]How to draw a circle that stays in the center of a leaflet.js map

如何绘制一个位于 leaflet.js map 中心的圆? 例如,圆的半径为 1 公里。 无论用户如何平移,我都希望绘制圆圈并保持在图像的中心。 如果用户缩放,圆圈应该相应地改变大小。

我想知道我是否必须在 leaflet 之外执行此操作并创建另一个 canvas 还是有简单的方法来完成此操作?

监听 map 上的move事件。

var circle = L.circleMarker(mymap.getCenter(), {
  radius: 50,
  color: 'red',
  fillOpacity: 0.2,
}).addTo(mymap);


mymap.on('move',function(e){
  circle.setLatLng(mymap.getCenter());
  mymap._renderer._update();
});

您也可以添加scrollWheelZoom: 'center'以始终按圆圈缩放。

L.map('mapid',{scrollWheelZoom: 'center'})

示例: https://jsfiddle.net/falkedesign/q2mdow5c/

Falke Design 接受的答案很好而且非常直接,但它使用 L.Map 私有方法(未记录)。

更通用的解决方案是:

  1. 在 map 上方创建一个 div 以保持您的圆圈。 The position and the size of the div will be recalculated each time the map is zoomed (you need to use leaflet map functions for these calculations).
  2. 此 div 捕获的鼠标事件需要发送到 map(它们不会冒泡,因为中心 div 不是 map div 的子级)

这是一个示例: https://yafred.github.io/leaflet-tests/20200412-draw-circle-in-the-middle-of-the-map/

这是代码:

<!DOCTYPE html>
<html>
<head>

    <title>Quick Start - Leaflet</title>

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />

    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.2/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.0.2/dist/leaflet.js"></script>

    <style>
    #center {
        visibility: hidden;
        top: -215px; 
        left: 285px;
        height: 30px;
        width: 30px;
        border-radius: 50%;
        opacity: 0.4;
        background-color: blue;
        z-index: 650;
        position: relative;
    }
    </style>
</head>
<body>


<div style="width: 600px; height: 400px; overflow: hidden">
<div id="map" style="width: 600px; height: 400px;"></div>
<div id="center"></div>
</div>
<p>Zoom in or out.</p>
<p>The circle is redrawn to have a 1km diameter.</p>
<div id="events">
</div>

<script>

    var map = L.map('map').setView([48.858475, 2.338285], 13);

    L.tileLayer('//a.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="//www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(map);
    L.control.scale().addTo(map);

    // Map event handlers
    function zoomEnd(e) {
        var widthMeters = map.distance(map.getBounds().getNorthWest(), map.getBounds().getNorthEast());
        var widthPixels = map.getSize().x;
        var heightPixels = map.getSize().y; 
        var radiusPixels = Math.round(1000 * widthPixels / widthMeters);

        // change style
        document.getElementById('center').style.height = 2*radiusPixels + 'px';
        document.getElementById('center').style.width = 2*radiusPixels + 'px';
        document.getElementById('center').style.left = (Math.round(widthPixels/2) - radiusPixels) + 'px';
        document.getElementById('center').style.top = '-' + (Math.round(heightPixels/2) + radiusPixels) + 'px';
        document.getElementById('center').style.visibility = "visible";

        // log
        document.getElementById('events').innerHTML += 'zoom ' + map.getZoom() + '<br/>'; 
        document.getElementById('events').innerHTML += 'width in meters ' + Math.round(widthMeters) + '<br/>'; 
        document.getElementById('events').innerHTML += 'width in pixels ' + widthPixels + '<br/>'; 
        document.getElementById('events').innerHTML += 'radiusPixels ' + radiusPixels + '<br/>'; 
        document.getElementById('events').innerHTML += 'top ' + (0 - Math.round(heightPixels/2) + radiusPixels) + '<br/>'; 
    }
    function zoomStart(e) {
        document.getElementById('events').innerHTML = '';
        document.getElementById('center').style.visibility = "hidden"; 
    }

    map.on('zoomstart', zoomStart);
    map.on('zoomend', zoomEnd);

    centerEventDispatcher = function(e) {
        new_e = new e.constructor(e.type, e);
        document.getElementById("map").dispatchEvent(new_e);
    }
    document.getElementById("center").addEventListener("mousedown", centerEventDispatcher);
    document.getElementById("center").addEventListener("mouseup", centerEventDispatcher);
    document.getElementById("center").addEventListener("mousemove", centerEventDispatcher);

    // initial circle
    zoomEnd();
</script>


    <!-- analytics -->
    <script>
if(window.location.hostname != "localhost") {
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-21317761-7', 'auto');
ga('send', 'pageview');
}
    </script>
</body>
</html>

YaFred 的方法很好,但是通过使用新的pointer-events: none; 圆圈上的 css 属性。

所以基本上:

  • 画出你的 map
  • 在其下方添加一个圆形 div,使用 css 之类的...
    .radius-circle {
        border-radius: 50%;
        opacity: 0.4;
        background-color: blue;
        z-index: 650;
        position: relative;
        height: 160px;
        width: 158px;
        left: 220px;
        top: -280px;
        pointer-events: none;    
    }

注意负上边距将其拉到 map 上方,并设置指针事件以使鼠标事件通过。

这基本上就是您需要做的所有事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM