繁体   English   中英

leaflet 内多边形显示的挑战

[英]Challenge for polygon display within leaflet

我们对 leaflet(最新版本)中的多边形显示有一个特定的设计挑战。

我们有用实心边框和半透明背景渲染的多边形。 我们正在寻找一种方法来绘制实心边界线以及更宽的“内联”边界并且没有背景。

注意:问题是针对不是矩形的多边形。 下面的图像和代码只是示例。

有什么办法可以做到这一点?

var polygon = L.polygon([
  [ 51.72872938200587, -2.415618896484375 ],
  [ 51.72872938200587, -2.080535888671875 ],
  [ 51.901918172561714, -2.080535888671875 ],
  [ 51.901918172561714, -2.415618896484375 ],
  [ 51.72872938200587, -2.415618896484375 ]

],{
 color:'#2F538F',
 fillOpacity: 0.9,
 fillColor: '#BFBFBF',
}).addTo(map);

在此处输入图像描述

这可以通过使用小册子的class 扩展系统来实现。

首先,可以参考传单的class 图以确定需要扩展的位置。 作为一般规则,首先尝试将类扩展到根目录,并且更喜欢L.Class.extend而不是L.Class.include

工作解决方案:

密码沙盒

一种方法是连接到渲染过程。 在以下示例中,将 L.Canvas 扩展为自定义 L.Canvas.WithExtraStyles class(传单的插件构建指南)。 然后将自定义渲染器提供给 map。

在这种方法中,请注意可以使用extraStyles配置提供多个边框和填充(插入和开始)。

extraStyle自定义属性接受PathOptions数组 使用额外的inset ,其值可以是正数或负数的像素,表示偏移形成主要几何图形的边界。 inset的负值会将边界置于原始多边形之外。

在实施此类自定义时,必须特别注意确保 leaflet 不会将添加的自定义视为单独的几何形状。 否则交互式功能,例如多边形编辑或 Leaflet Draw 将出现意外行为

 // CanvasWithExtraStyles.js // First step is to provide a special renderer which accept configuration for extra borders. // Here L.Canvas is extended using Leaflet's class system const styleProperties = ['stroke', 'color', 'weight', 'opacity', 'fill', 'fillColor', 'fillOpacity']; /* * @class Polygon.MultiStyle * @aka L.Polygon.MultiStyle * @inherits L.Polygon */ L.Canvas.WithExtraStyles = L.Canvas.extend({ _updatePoly: function(layer, closed) { const centerCoord = layer.getCenter(); const center = this._map.latLngToLayerPoint(centerCoord); const originalParts = layer._parts.slice(); // Draw extra styles if (Array.isArray(layer.options.extraStyles)) { const originalStyleProperties = styleProperties.reduce( (acc, cur) => ({...acc, [cur]: layer.options[cur] }), {} ); const cx = center.x; const cy = center.y; for (let eS of layer.options.extraStyles) { const i = eS.inset || 0; // For now, the algo doesn't support MultiPolygon // To have it support MultiPolygon, find centroid // of each MultiPolygon and perform the following layer._parts[0] = layer._parts[0].map(p => { return { x: px < cx? px + i: px - i, y: py < cy? py + i: py - i }; }); //Object.keys(eS).map(k => layer.options[k] = eS[k]); Object.keys(eS).map(k => (layer.options[k] = eS[k])); L.Canvas.prototype._updatePoly.call(this, layer, closed); } // Resetting original conf layer._parts = originalParts; Object.assign(layer.options, originalStyleProperties); } L.Canvas.prototype._updatePoly.call(this, layer, closed); } }); // Leaflet's conventions to also provide factory methods for classes L.Canvas.withExtraStyles = function(options) { return new L.Canvas.WithExtraStyles(options); }; // -------------------------------------------------------------- // map.js const map = L.map("map", { center: [52.5145206, 13.3499977], zoom: 18, renderer: new L.Canvas.WithExtraStyles() }); new L.tileLayer( "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_nolabels/{z}/{x}/{y}.png", { attribution: `attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attribution">CARTO</a>`, detectRetina: true } ).addTo(map); // Map center const { x, y } = map.getSize(); // Left Polygon const polyStyle1 = { color: '#2f528f', extraStyles: [ { color: 'transparent', weight: 10, fillColor: '#d9d9d9' } ] }; // Sudo coordinates are generated form map container pixels const polygonCoords1 = [ [0, 10], [300, 10], [300, 310], [0, 310] ].map(point => map.containerPointToLatLng(point)); const polygon1 = new L.Polygon(polygonCoords1, polyStyle1); polygon1.addTo(map); // Right Polygon const polyStyle2 = { fillColor: "transparent", color: '#2f528f', extraStyles: [ { inset: 6, color: '#d9d9d9', weight: 10 } ] }; const polygonCoords2 = [ [340, 10], [640, 10], [640, 310], [340, 310] ].map(point => map.containerPointToLatLng(point)); const polygon2 = new L.Polygon(polygonCoords2, polyStyle2); polygon2.addTo(map);
 <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script> <link href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" rel="stylesheet"/> <div id="map" style="width: 100vw; height: 100vw">0012</div>

理想解决方案:

  • 将插件实现为单独的 npm 模块。
  • 尝试扩展或挂钩到渲染器本身,而不是单独扩展 L.Canvas 和 L.SVG。
  • 将自定义连接到基本 class路径而不是单个形状:多边形、折线或圆形。

使用 Recatngle/Polygon 方法。

 // define rectangle geographical bounds var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]]; // create an orange rectangle L.rectangle(bounds, {}).addTo(map);

使用选项在线条上获得所需的效果。 选项继承自折线选项

在那里你可以调整coloropacityfillfillColorfillOpacityfillRule以获得所需的线条效果

暂无
暂无

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

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