如何在 mapbox 中为不同的数据集设置不同的标记
how to different markers for different data set in mapbox
我正在使用带有反应的地图框api,我从后端得到两种数据集,一种是自行车的停车点,另一种是事故发生地点的数据集,我想显示mapbox 中的两个数据集 markers/icons 不同,我应该怎么做?
目前我正在使用以下代码显示单个数据集。
import React, { useState, useEffect, useRef } from "react";
import { useDispatch, useSelector } from 'react-redux';
import mapboxgl from 'mapbox-gl';
import {getBikeInfo, mapDetails} from './features/counter/getInfo/getDetails.js'
<link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet"></link>
function App() {
const dispatch = useDispatch();
const [dataLoaded, setDataLoaded] = useState(false);
const dataToDisplay = useSelector(mapDetails);
mapboxgl.accessToken = 'pk.eyJ1IjoidmloYW5nMTYiLCJhIjoiY2ttOHowc2ZhMWN2OTJvcXJ0dGpiY21pNyJ9.hK5Wxwby89E7tKWoBoY5bg';
const mapContainer = useRef(null);
let styles = {
'display' : 'none'
}
useEffect(() => {
// dispatch(getBikeInfo())
var map = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/light-v10',
center: [-96, 37.8],
zoom: 3
});
map.on('load', function () {
// Add an image to use as a custom marker
map.loadImage(
'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png',
function (error, image) {
if (error) throw error;
map.addImage('custom-marker', image);
// Add a GeoJSON source with 2 points
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': dataToDisplay //list of all coordinates along require data
}
});
// Add a symbol layer
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': 'custom-marker',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
}
);
});
setDataLoaded(true);
}, [dataToDisplay]);
useEffect(() => {
dispatch(getBikeInfo())
},[])
return (
<div className="district-map-wrapper" style={dataLoaded ? undefined : {display: 'none'}}>
<div id="districtDetailMap" className="map">
<div style={{ height: "100%" }} ref={mapContainer}>
</div>
</div>
</div>
);
}
export default App;
下面是要填充的示例数据
type: "Feature",
geometry: {
type: "Point",
coordinates: [
-74.04281705617905,
40.71458403535893,
]
},
properties: {
title: 'some field'
}
解决方法:
根据@tylerban 的回答,我更新了我的代码:
map.on('load', function () {
// Add an image to use as a custom marker
loadDataFromPara( dataToDisplay, 'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png', 'bikeLocation', 'bikePoints', 'bike-marker')
loadDataFromPara( collisionInfo, marker, 'collisionLocation', 'collisionPoints', 'collision-marker')
});
setDataLoaded(true);
function loadDataFromPara( data, image1, sourceName, layerName, imageMarker ){
map.loadImage(
image1,
function (error, image) {
if (error) throw error;
map.addImage(imageMarker, image);
// Add a GeoJSON source with 2 points
map.addSource(sourceName, {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': data
}
});
// Add a symbol layer
map.addLayer({
'id': layerName,
'type': 'symbol',
'source': sourceName,
'icon-allow-overlap': true,
'layout': {
'icon-image': imageMarker,
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'icon-allow-overlap': true,
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
}
);
}
自行车停放点和事故地点是否包含在同一源(数据集)中,或者它们是否是您添加到地图的两个不同源和图层?
如果自行车停放和事故包含在同一源中,您可以使用 data driven styling in Mapbox 根据数据中的字段分配图标。因此,如果您在源中有一个字段可用于确定一个点是否代表自行车停车位或事故,您将关闭它。
下面是一些伪代码,说明了如何执行此操作。
map.addLayer({
id: 'points',
type: 'symbol',
source: 'points',
layout: {
'icon-image': [
'match',
[ 'get', 'type' ], // type corresponds to the field name you are keying off of
[ 'bike parking' ],
'custom-marker',
[ 'pedestrian' ],
'custom-marker-2',
'custom-marker' // fallback icon
],
// get the title name from the source's "title" property
'text-field': [ 'get', 'title' ],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [ 0, 1.25 ],
'text-anchor': 'top'
}
})
如果自行车停放和事故包含在两个不同的来源中,您只需为每个来源添加一个图层并在将图层添加到地图时指定一个图标。
这是一些伪代码
// Add a bike parking layer
map.addLayer({
'id': 'bike-parking',
'type': 'symbol',
'source': 'bike-parking-source',
'layout': {
'icon-image': 'custom-marker',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
// Add an accidents layer
map.addLayer({
'id': 'accidents',
'type': 'symbol',
'source': 'accidents-source',
'layout': {
'icon-image': 'custom-marker-2',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
我已经写了很多关于使用 React 和 Mapbox 的深入文章,如果你觉得它们有用,我会在下面 link 给它们。我也正在编写 Mapbox 开发者手册,其中包含如何构建强大的地图驱动应用程序的来龙去脉。
我正在使用带有反应的地图框api,我从后端得到两种数据集,一种是自行车的停车点,另一种是事故发生地点的数据集,我想显示mapbox 中的两个数据集 markers/icons 不同,我应该怎么做?
目前我正在使用以下代码显示单个数据集。
import React, { useState, useEffect, useRef } from "react";
import { useDispatch, useSelector } from 'react-redux';
import mapboxgl from 'mapbox-gl';
import {getBikeInfo, mapDetails} from './features/counter/getInfo/getDetails.js'
<link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet"></link>
function App() {
const dispatch = useDispatch();
const [dataLoaded, setDataLoaded] = useState(false);
const dataToDisplay = useSelector(mapDetails);
mapboxgl.accessToken = 'pk.eyJ1IjoidmloYW5nMTYiLCJhIjoiY2ttOHowc2ZhMWN2OTJvcXJ0dGpiY21pNyJ9.hK5Wxwby89E7tKWoBoY5bg';
const mapContainer = useRef(null);
let styles = {
'display' : 'none'
}
useEffect(() => {
// dispatch(getBikeInfo())
var map = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/light-v10',
center: [-96, 37.8],
zoom: 3
});
map.on('load', function () {
// Add an image to use as a custom marker
map.loadImage(
'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png',
function (error, image) {
if (error) throw error;
map.addImage('custom-marker', image);
// Add a GeoJSON source with 2 points
map.addSource('points', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': dataToDisplay //list of all coordinates along require data
}
});
// Add a symbol layer
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': 'custom-marker',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
}
);
});
setDataLoaded(true);
}, [dataToDisplay]);
useEffect(() => {
dispatch(getBikeInfo())
},[])
return (
<div className="district-map-wrapper" style={dataLoaded ? undefined : {display: 'none'}}>
<div id="districtDetailMap" className="map">
<div style={{ height: "100%" }} ref={mapContainer}>
</div>
</div>
</div>
);
}
export default App;
下面是要填充的示例数据
type: "Feature",
geometry: {
type: "Point",
coordinates: [
-74.04281705617905,
40.71458403535893,
]
},
properties: {
title: 'some field'
}
解决方法: 根据@tylerban 的回答,我更新了我的代码:
map.on('load', function () {
// Add an image to use as a custom marker
loadDataFromPara( dataToDisplay, 'https://docs.mapbox.com/mapbox-gl-js/assets/custom_marker.png', 'bikeLocation', 'bikePoints', 'bike-marker')
loadDataFromPara( collisionInfo, marker, 'collisionLocation', 'collisionPoints', 'collision-marker')
});
setDataLoaded(true);
function loadDataFromPara( data, image1, sourceName, layerName, imageMarker ){
map.loadImage(
image1,
function (error, image) {
if (error) throw error;
map.addImage(imageMarker, image);
// Add a GeoJSON source with 2 points
map.addSource(sourceName, {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': data
}
});
// Add a symbol layer
map.addLayer({
'id': layerName,
'type': 'symbol',
'source': sourceName,
'icon-allow-overlap': true,
'layout': {
'icon-image': imageMarker,
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'icon-allow-overlap': true,
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
}
);
}
自行车停放点和事故地点是否包含在同一源(数据集)中,或者它们是否是您添加到地图的两个不同源和图层?
如果自行车停放和事故包含在同一源中,您可以使用 data driven styling in Mapbox 根据数据中的字段分配图标。因此,如果您在源中有一个字段可用于确定一个点是否代表自行车停车位或事故,您将关闭它。
下面是一些伪代码,说明了如何执行此操作。
map.addLayer({
id: 'points',
type: 'symbol',
source: 'points',
layout: {
'icon-image': [
'match',
[ 'get', 'type' ], // type corresponds to the field name you are keying off of
[ 'bike parking' ],
'custom-marker',
[ 'pedestrian' ],
'custom-marker-2',
'custom-marker' // fallback icon
],
// get the title name from the source's "title" property
'text-field': [ 'get', 'title' ],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [ 0, 1.25 ],
'text-anchor': 'top'
}
})
如果自行车停放和事故包含在两个不同的来源中,您只需为每个来源添加一个图层并在将图层添加到地图时指定一个图标。
这是一些伪代码
// Add a bike parking layer
map.addLayer({
'id': 'bike-parking',
'type': 'symbol',
'source': 'bike-parking-source',
'layout': {
'icon-image': 'custom-marker',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
// Add an accidents layer
map.addLayer({
'id': 'accidents',
'type': 'symbol',
'source': 'accidents-source',
'layout': {
'icon-image': 'custom-marker-2',
// get the title name from the source's "title" property
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-offset': [0, 1.25],
'text-anchor': 'top'
}
});
我已经写了很多关于使用 React 和 Mapbox 的深入文章,如果你觉得它们有用,我会在下面 link 给它们。我也正在编写 Mapbox 开发者手册,其中包含如何构建强大的地图驱动应用程序的来龙去脉。