我有问题,我用他的图层和标记创建了一个地图。我已经完成了可拖动标记。
我正在使用react-map-gl和打字稿。
我的问题是,当我将标记从一个点更改为另一点时,用鼠标滚轮或放大标记“移动”。
我希望在更改缩放时继续在图层上移动,而在增加缩放时不退出图层。
我已经读过有关捕捉的信息,但我不知道该怎么做。
但是,不能用react map gl修复它吗?
这是我的代码:
export class SettingsMap extends React.PureComponent<
Readonly<
ISettingsMapProps &
InteractiveMapProps &
WrappedComponentProps & { children?: ReactNode }
>,
ISettingsMapState
> {
mapRef: React.RefObject<InteractiveMap> = React.createRef<InteractiveMap>();
timeout: ReturnType<typeof setTimeout> = setTimeout(() => "", 1000);
constructor(
props: Readonly<
ISettingsMapProps &
InteractiveMapProps &
WrappedComponentProps & { children?: ReactNode }
>
) {
super(props);
this.state = {
viewport: {
width: 100,
height: 100,
latitude: 39.46096,
longitude: -0.40212,
zoom: 12,
pitch: 0,
},
mapGL: undefined,
interactiveLayers: [TITLE_PIPE_LAYER, TITLE_POINT_LAYER],
dragging: false,
selectedFlowmeter: undefined,
};
}
componentDidUpdate(prevProps: ISettingsMapProps) {
if (prevProps.showModal !== this.props.showModal) {
const { mapGL } = this.state;
mapGL?.getMap().on("moveend", () => {
this.updateViewportOnFinishFly(mapGL);
});
}
}
componentWillUnmount(): void {
clearTimeout(this.timeout);
const { mapGL } = this.state;
if (mapGL) {
mapGL?.getMap().off("moveend");
}
}
updateViewportOnFinishFly = (mapGL: any) => {
const { viewport } = this.state;
mapGL.getMap().off("moveend");
const center: Center = mapGL
?.getMap()
.getCenter()
.wrap();
const zoom: number = mapGL?.getMap().getZoom();
const updatedViewport = Object.assign({}, viewport, {
latitude: center.lat,
longitude: center.lng,
zoom: zoom,
});
this.setState({ viewport: updatedViewport });
};
onClickedMap = (): void => {
const { flowmeters, setFlowMeters } = this.props;
const newArray: Array<IFlowMeter> = disableMenuAllFlowMeters(
flowmeters
);
setFlowMeters(newArray);
};
handleLoad = (event: MapLoadEvent): void => {
const loaded: boolean = event.target.loaded();
const mapGL = this.mapRef.current;
if (this.props.onSetLoaded) {
this.props.onSetLoaded(loaded, mapGL);
}
if (mapGL !== null) {
this.setState({ mapGL: mapGL });
}
};
onClickedFlowmeter = (flowmeter: IFlowMeter): void => {
const { flowmeters, setFlowMeters } = this.props;
const newArray: Array<IFlowMeter> = updateFlowMeterMenu(
flowmeter,
flowmeters,
true
);
setFlowMeters(newArray);
};
onDragStart = (flowmeter: IFlowMeter) => {
this.setState({ dragging: true, selectedFlowmeter: flowmeter });
};
onDragEnd = (): void => {
this.setState({ dragging: false });
};
handleMouseMove = (event: any) => {
const { dragging, selectedFlowmeter, mapGL } = this.state;
const { flowmeters, setFlowMeters } = this.props;
if (!dragging && selectedFlowmeter) {
const features = mapGL.getMap().queryRenderedFeatures(event.point);
let existFeature = false;
features.forEach((feature: any) => {
if (
feature.layer.id.startsWith(TITLE_PIPE_LAYER) ||
feature.layer.id.startsWith(TITLE_POINT_LAYER)
) {
existFeature = true;
}
});
if (existFeature) {
const lngLat: number[] = event.lngLat;
const newArray: Array<IFlowMeter> = flowMeterUpdatePosition(
lngLat,
selectedFlowmeter,
flowmeters
);
setFlowMeters(newArray);
}
this.setState({ selectedFlowmeter: undefined });
} else if (!dragging && !selectedFlowmeter) {
return;
}
};
renderMarker = (flowmeter: IFlowMeter, index: number) => {
const { flowmeters, setFlowMeters } = this.props;
const { showUpdateModal } = this.props;
return (
<div
className="flowmeter-marker-compose"
key={index}
onMouseUp={() => {
if (showUpdateModal) return;
this.onClickedFlowmeter(flowmeter);
}}
>
<Marker
className={`flowmeter-marker ${
showUpdateModal ? "--disabled" : "--enabled"
}`}
offsetLeft={-30}
offsetTop={-30}
draggable={flowmeter.draggable}
latitude={flowmeter.latitude}
longitude={flowmeter.longitude}
onDragStart={() => {
if (showUpdateModal) return;
this.onDragStart(flowmeter);
}}
onDragEnd={() => {
if (showUpdateModal) return;
this.onDragEnd();
}}
>
{flowmeter && flowmeter.menu && (
<FlowMeterMenu
flowmeter={flowmeter}
flowmeters={flowmeters}
updateFlowMeters={setFlowMeters}
/>
)}
{!flowmeter.locked ? <FlowMiter /> : <FlowMiterLocked />}
</Marker>
</div>
);
};
onWheel = (event: any) => {
// SNAPPING
// console.log("event: ", event);
// update marker to line
// npm install @turf/nearest-point-on-line
const { flowmeters, geojson } = this.props;
flowmeters.forEach( (flowmeter: IFlowMeter) => {
const targetPoint = point([flowmeter.longitude, flowmeter.latitude]);
const nearest = nearestPoint(targetPoint, geojson);
console.log("nearest point: ", nearest);
})
};
renderPipeLayer = (
features:
| string
| GeoJSON.Feature<GeoJSON.Geometry, GeoJSON.GeoJsonProperties>
| GeoJSON.FeatureCollection<
GeoJSON.Geometry,
GeoJSON.GeoJsonProperties
>
| undefined
) => {
return <GeojsonPipieLayer data={features} />;
};
renderPointsLayer = (
features:
| string
| GeoJSON.Feature<GeoJSON.Geometry, GeoJSON.GeoJsonProperties>
| GeoJSON.FeatureCollection<
GeoJSON.Geometry,
GeoJSON.GeoJsonProperties
>
| undefined
) => {
return <GeojsonPointLayer data={features} />;
};
render() {
const { theme, children, showModal, flowmeters } = this.props;
const { width, height, geojson } = this.props;
const { viewport, interactiveLayers } = this.state;
const mapStyle: string =
theme === mapThemes.DARK ? darkTheme : lightTheme;
return (
<div className="dma-map__wrapper">
<InteractiveMap
{...viewport}
ref={this.mapRef}
className="mapbox"
width={width}
height={height}
mapStyle={mapStyle}
attributionControl={false}
onLoad={this.handleLoad}
onClick={this.onClickedMap}
onWheel={this.onWheel}
onMouseMove={this.handleMouseMove}
onViewportChange={(viewport: ViewportProps) => {
viewport.width = 100;
viewport.height = 100;
this.setState({ viewport });
}}
interactiveLayerIds={geojson ? interactiveLayers : []}
>
{!showModal && children}
{!showModal && geojson && this.renderPipeLayer(geojson)}
{!showModal && geojson && this.renderPointsLayer(geojson)}
{!showModal &&
flowmeters &&
flowmeters.length > 0 &&
flowmeters.map(this.renderMarker)}
</InteractiveMap>
</div>
);
}
}
export default injectIntl(SettingsMap);
我有一种解决方案,可以在更改缩放比例时正确显示标记:D
我正在使用一种称为捕捉的技术,或者我不知道我是否正在使用该技术。
希望您喜欢它或为您服务:D
我已经添加了这种方法,并且已经使用草皮库来解决它。
onWheel = () => {
this.snapping();
};
snapping = () => {
this.isSnapping = true;
const { flowmeters, setFlowMeters } = this.props;
flowmeters.forEach((flowmeter: IFlowMeter, index: number) => {
if (!flowmeter) return;
if (flowmeter && !flowmeter.feature) return;
const coordinates = flowmeter.feature.geometry.coordinates;
const line = lineString(coordinates);
const pt = point([flowmeter.longitude, flowmeter.latitude]);
const nearest = nearestPointOnLine(line, pt);
const lngLat: Array<number> = [
nearest.geometry.coordinates[0],
nearest.geometry.coordinates[1],
];
setFlowMeters(
flowMeterUpdatePosition(lngLat, flowmeter, flowmeters)
);
});
this.isSnapping = false;
};
并且在componentDidUpdate中,我已经添加了这个:
const { viewport } = this.state;
if ( prevState.viewport.zoom !== viewport.zoom && prevState.viewport.zoom < viewport.zoom && !this.isSnapping ) {
this.snapping();
}