我现在想出了一些将自定义 JSX 渲染为 Marker 的工作代码。
这是https://jahed.io/2018/03/20/react-portals-and-leaflet/的 95% 副本和来自https://github.com/PaulLeCam/react-leaflet/blob/master的5% 灵感/src/Marker.js
我相信有些事情可以进一步优化。
import * as React from 'react';
import { createPortal } from "react-dom";
import { DivIcon, marker } from "leaflet";
import * as RL from "react-leaflet";
import { MapLayer } from "react-leaflet";
import { difference } from "lodash";
const CustomMarker = (RL as any).withLeaflet(class extends MapLayer<any> {
leafletElement: any;
contextValue: any;
createLeafletElement(props: any) {
const { map, layerContainer, position, ...rest } = props;
// when not providing className, the element's background is a white square
// when not providing iconSize, the element will be 12x12 pixels
const icon = new DivIcon({ ...rest, className: '', iconSize: undefined });
const el = marker(position, { icon: icon, ...rest });
this.contextValue = { ...props.leaflet, popupContainer: el };
return el;
}
updateLeafletElement(fromProps: any, toProps: any) {
const { position: fromPosition, zIndexOffset: fromZIndexOffset, opacity: fromOpacity, draggable: fromDraggable, className: fromClassName } = fromProps;
const { position: toPosition, zIndexOffset: toZIndexOffset, toOpacity, draggable: toDraggable, className: toClassName } = toProps;
if(toPosition !== fromPosition) {
this.leafletElement.setLatLng(toPosition);
}
if(toZIndexOffset !== fromZIndexOffset) {
this.leafletElement.setZIndexOffset(toZIndexOffset);
}
if(toOpacity !== fromOpacity) {
this.leafletElement.setOpacity(toOpacity);
}
if(toDraggable !== fromDraggable) {
if(toDraggable) {
this.leafletElement.dragging.enable();
} else {
this.leafletElement.dragging.disable();
}
}
if(toClassName !== fromClassName) {
const fromClasses = fromClassName.split(" ");
const toClasses = toClassName.split(" ");
this.leafletElement._icon.classList.remove(
...difference(fromClasses, toClasses)
);
this.leafletElement._icon.classList.add(
...difference(toClasses, fromClasses)
);
}
}
componentWillMount() {
if(super.componentWillMount) {
super.componentWillMount();
}
this.leafletElement = this.createLeafletElement(this.props);
this.leafletElement.on("add", () => this.forceUpdate());
}
componentDidUpdate(fromProps: any) {
this.updateLeafletElement(fromProps, this.props);
}
render() {
const { children } = this.props;
const container = this.leafletElement._icon;
if(!container) {
return null;
}
const portal = createPortal(children, container);
const LeafletProvider = (RL as any).LeafletProvider;
return children == null || portal == null || this.contextValue == null ? null : (
<LeafletProvider value={this.contextValue}>{portal}</LeafletProvider>
)
}
});
然后像这样在你的组件中使用它:
<Map ...>
<CustomMarker position={[50, 10]}>
<Tooltip>
tooltip
</Tooltip>
<Popup>
popup
</Popup>
<div style={{ backgroundColor: 'red' }} onClick={() => console.log("CLICK")}>
CUSTOM MARKER CONTENT
</div>
MORE CONTENT
</CustomMarker>
</Map>
如果你不使用 TypeScript。只需删除as any
和: any
东西。
编辑:某些东西会自动设置width: 12px;
和height: 12px;
. 我还不确定,如何防止这种情况。其他一切似乎都很好!
EDIT2:修复它!使用iconSize: undefined
EDIT3:还有这个:https ://github.com/OpenGov/react-leaflet-marker-layer
没有测试过,但示例代码看起来不错。