react-leaflet - 如何在 react-leaflet v3 中扩展 TileLayer 组件?
问题描述
我正在尝试在“react-leaflet”v3 中扩展 TileLayer 组件。有必要重写此函数以提供自定义磁贴 URL 命名方案。我需要的一个例子,用基本的传单写成:
function initMap() {
L.TileLayer.WebGis = L.TileLayer.extend({
initialize: function (url, options) {
options = L.setOptions(this, options);
if (options.detectRetina && L.Browser.retina && options.maxZoom > 0) {
options.tileSize = Math.floor(options.tileSize / 2);
options.zoomOffset++;
if (options.minZoom > 0) {
options.minZoom--;
}
this.options.maxZoom--;
}
if (options.bounds) {
options.bounds = L.latLngBounds(options.bounds);
}
this._url = url + "/gis_render/{x}_{y}_{z}/" + options.userId + "/tile.png";
var subdomains = this.options.subdomains;
if (typeof subdomains === 'string') {
this.options.subdomains = subdomains.split('');
}
},
getTileUrl: function (tilePoint) {
return L.Util.template(this._url, L.extend({
s: this._getSubdomain(tilePoint),
z: 17 - this._map._zoom,
x: tilePoint.x,
y: tilePoint.y
}, this.options));
}
});
L.tileLayer.webGis = function (url, options) {
return new L.TileLayer.WebGis(url, options);
};
// create a map in the "map" div, set the view to a given place and zoom
var map = L.map('map').setView([53.9, 27.55], 10);
// add an Gurtam Maps tile layer
L.tileLayer.webGis(wialon.core.Session.getInstance().getBaseGisUrl('render'), {
attribution: 'Gurtam Maps',
minZoom: 4,
userId: wialon.core.Session.getInstance().getCurrUser().getId()
}).addTo(map);
}
如果我只是将 Gurtam 地图的 url 写入 TileLayer 组件的“url”道具,那么我的地图会错误地显示(缩放和平铺错误)。
我不知道要使用什么来正确显示:
- 使用 'useRef' 钩子获取当前 TileLayer 实例并扩展它。
- 使用包'react-leaflet/core'中的一些钩子(可能是createElementHook)并创建我自己的自定义组件
- 或者是其他东西
我将不胜感激任何解释。
解决方案
听起来您正在尝试在react-leaflet v3
. 如果你对 react-leaflet 不是很熟悉,这可能会让人望而生畏。编写自定义组件的文档有点难以理解。我发现这部分很有帮助:Element hook factory
因此,您需要从 2 个基本功能开始。一个函数来创建你的元素,一个函数来更新它。要创建它,
// Assuming you've already defined L.TileLayer.WebGis somewhere
// and attached it to the global L
const createWebGisLayer = (props, context) => {
const instance = L.tileLayer.webGis(props.url, {...props})
return { instance, context }
}
然后,您需要另一个函数来处理您想要渗透到组件中的任何更新。例如,如果您的组件的某个 prop 发生更改,您需要明确告诉 react-leaflet 更新该组件的底层传单实例:
const updateWebGisLayer = (instance, props, prevProps) => {
if (prevProps.url !== props.url) {
if (instance.setUrl) instance.setUrl(props.url)
}
if (prevProps.userId !== props.userId) {
if (instance.setUserId) instance.setUserId(props.userId)
}
}
你需要这些 setter 函数来告诉 react-leaflet 如果url
or userId
(或其他) prop 在 react 中发生变化,它需要重新渲染传单层。 setUrl
已存在于 上L.TileLayer
,但您需要定义一个setUserId
更新实例userId
选项的。L.TileLayer.WebGis
如果你不包含这些,当它的 props 改变时你的组件不会更新。
总而言之,您可以使用createLayerComponent
工厂功能:
const WebGisLayer = createLayerComponent(createWebGisLayer, updateWebGisLayer)
export WebGisLayer
WebGisLayer
现在是一个反应组件,您可以将其用作 a 的子组件MapContainer
const App = () => {
const [userId, setUserId] = useState('user123')
return (
<MapContainer center={center} zoom={zoom}>
<WebGisLayer
url="some_url"
userId={userId}
otherPropsYouNeed={otherProps} />
</MapContainer>
)
}
当组件加载时,它将运行您的传单代码并将传单组件添加到地图中。如果userId
由于某些 setstate 调用而发生更改,您的updateWebGisLayer
函数会告诉 react-leaflet 更新底层的传单组件。
有很多方法可以做到这一点,但这是我认为最简单的一种。我还没有机会测试此代码,因此您将不可避免地不得不使用它来使其正常工作,但这应该可以帮助您入门。
推荐阅读
- r - csv read 在 R.. 中向我加载的数据框插入一个“X”列?
- sql - SSIS 将数据从 SQL db 复制到同一 excel 目标上的多个选项卡
- powershell - 如何在组 AD PowerShell 中获取组的用户
- android - 如何在 Android Developer Console 崩溃报告中读取“OR 调用堆栈”?
- html - 引导元素未隐藏
- ios - 是否需要签署付费应用程序协议才能在 iOS 上启用初始 IAP 测试?
- ios - 在 Swift 4 IOS 中将 XML 数据转换为字符串
- c# - C# DataTable DataGrid 列名中的特殊字符“/”(斜杠)
- typescript - 在量角器中,很少有代码行没有间歇性地执行
- .net-core - 无法在 .net 核心中返回已完成的成功任务