javascript - 如何从地图外部将对象拖放到 Mapbox 地图中?
问题描述
如何在Mapbox 地图对象之外创建可以拖入其中的元素?例如,假设我想在页面上呈现位置列表。每个位置都是一个带有自定义标记或图标的 React 组件。
这个位置列表旁边是一个 Mapbox 地图。位置列表不会在地图内呈现。虽然我知道可以使这些单独的位置组件可拖动,但是否可以将它们拖放到 Mapbox 地图中并将其识别为地图上具有纬度/经度坐标的实际标记?如果是这样,我该怎么做?
以下是我尝试过的代码中的相关源文件:
index.js
import dynamic from "next/dynamic";
import { useSelector } from "react-redux";
import Plant from "../../components/Plant";
const MapboxMap = dynamic(() => import("../../components/MapboxGLMap"), {
ssr: false,
});
const Blueprint = () => {
const plants = useSelector((state) => state.plants);
const showPlants = () => {
return (
<React.Fragment>
{plants.map((plant) => (
<Plant plant={plant} />
))}
</React.Fragment>
);
};
return (
<React.Fragment>
<div className="ui container centered grid blueprint">
<div className="three wide column scrollable">
<div className="ui link one cards">{showPlants()}</div>
</div>
<div className="twelve wide column">
<MapboxMap />
</div>
<style jsx>{`
.scrollable {
height: calc(100vh);
overflow-x: auto;
}
`}</style>
</React.Fragment>
);
};
export default Blueprint;
植物.jsx
import React from "react";
import { useDrag } from "react-dnd";
const ItemTypes = {
PLANT: "plant",
};
const Plant = ({ plant }) => {
const [{ isDragging }, drag] = useDrag({
item: { type: ItemTypes.PLANT },
collect: (monitor) => ({
isDragging: !!monitor.isDragging(),
}),
});
return (
<div
ref={drag}
style={{
opacity: isDragging ? 0.1 : 1,
cursor: "move",
}}
key={plant.id}
className="card"
>
<div className="image">
<img src="/white-image.png" />
</div>
<div className="content">
<div className="center aligned">{plant.common_name}</div>
</div>
</div>
);
};
export default Plant;
MapboxGLMap.jsx
import React, { useEffect, useRef, useState } from "react";
import mapboxgl from "mapbox-gl";
import MapboxGeocoder from "@mapbox/mapbox-gl-geocoder";
import MapboxDraw from "@mapbox/mapbox-gl-draw";
const MAPBOX_TOKEN = "xxx";
const styles = {
width: "100%",
height: "100%",
position: "absolute",
};
const MapboxGLMap = () => {
const [map, setMap] = useState(null);
const [lng, setLng] = useState(null);
const [lat, setLat] = useState(null);
const [plant, setPlant] = useState(null);
const mapContainer = useRef(null);
useEffect(() => {
mapboxgl.accessToken = MAPBOX_TOKEN;
const initializeMap = ({ setMap, mapContainer }) => {
const map = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/satellite-v9", // stylesheet location
center: [0, 0],
zoom: 5,
});
map.on("load", () => {
setMap(map);
map.resize();
});
map.on("click", (e) => {});
map.addControl(
new MapboxGeocoder({
accessToken: MAPBOX_TOKEN,
mapboxgl: mapboxgl,
})
);
const draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
polygon: true,
trash: true,
},
});
map.addControl(draw);
map.on("draw.create", (e) => {
console.log("e =>", e);
console.log("draw.getAll()", draw.getAll());
});
map.on("mousemove", (e) => {
// console.log(e.point);
setLng(e.lngLat.wrap().lng);
setLat(e.lngLat.wrap().lat);
});
};
if (!map) initializeMap({ setMap, mapContainer });
}, [map]);
return <div ref={(el) => (mapContainer.current = el)} style={styles} />;
};
export default MapboxGLMap;
解决方案
实际上,根据您的相关标签,我想您想将诸如图钉之类的东西从外部拖放到地图区域。你使用reactjs
标签,这意味着你想通过使用 ReactJS 来做到这一点。
为此,您应该通过 npm 或 yarn 安装 Mapbox:
npm install mapbox-gl --save
或者
yarn add mapbox-gl
然后你应该将 Mapbox 区域包裹在一个放置区中。为此,您可以使用react-dropzone
. 通过以下命令安装它:
npm install react-dropzone --save
或者
yarn add react-dropzone
将以下行添加到 HTML 模板:
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css' rel='stylesheet' />
然后像下面这样使用它:
import React from 'react';
import Dropzone from 'react-dropzone';
import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'MAPBOX_ACCESS_TOKEN';
class MapComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
lng: 5,
lat: 34,
zoom: 2,
};
}
componentDidMount() {
const map = new mapboxgl.Map({
container: this.mapContainer,
style: 'mapbox://styles/mapbox/streets-v11',
center: [this.state.lng, this.state.lat],
zoom: this.state.zoom,
});
map.on('move', () => {
this.setState({
lng: map.getCenter().lng.toFixed(4),
lat: map.getCenter().lat.toFixed(4),
zoom: map.getZoom().toFixed(2),
});
});
}
render() {
return (
<Dropzone>
{({ getRootProps, getInputProps }) => (
<section>
<div {...getRootProps()}>
<input {...getInputProps()} />
<div
ref={el => {
this.mapContainer = el;
}}
/>
</div>
</section>
)}
</Dropzone>
);
}
}
通过使用此方法,您可以放置一些图像并获取它,并根据放置位置将其显示在地图上。
注意:将捕获的文件类型减少为图像文件类型,如jpg
/png
推荐阅读
- docker - 尝试使用网关安全令牌向 Hawkbit 服务器发出 GET 请求时出现 401 错误
- python - 如何在pycharm中加载pcd文件
- alexa - 使用文档中的 JSON 对 Alexa AddOrUpdateReport 的 400 错误请求
- ssh - ssh 无法连接但 scp 在 gitlab-ci 中工作
- java - 使用 Jpype 在 Python 中使用 Java 类时出错
- python - 从Django中的父级继承模板块
- python - 使用 Python 从网页中检索 XMLHttpRequest (XHR) 响应
- javascript - 如何使用javascript为表格中的输入赋值?
- c++ - 应该包含的标头中如何缺少 SSE2 函数?
- c# - 在一次调用中接收按文档类型分组的搜索结果(NEST、AWS Elasticsearch)