如何使用 turfjs 和 mapbox js select 并突出显示方形网格中的单元格?
How to select and highlight a cell from a square grid using turfjs and mapbox js?
我正在尝试 select 来自我已添加到我的 mapbox js 地图的方形网格层的单元格。
这是我的代码:
import React, { useRef, useEffect, useState } from 'react';
import './App.css';
import mapboxgl from '!mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax
import * as turf from '@turf/turf'
mapboxgl.accessToken = 'MY_TOKEN';
function App() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-82.659521999370077); // eslint-disable-line no-unused-vars
const [lat, setLat] = useState(9.628698847753714); // eslint-disable-line no-unused-vars
const [zoom, setZoom] = useState(17); // eslint-disable-line no-unused-vars
useEffect(() => {
if (map.current) return;
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/USER/MAP_ID',
center: [lng, lat],
zoom: zoom,
scrollZoom: true
});
const bounds = map.current.getBounds();
console.log(`bounds:`, bounds);
const NE = bounds.getNorthEast();
const SW = bounds.getSouthWest();
var cellSide = 0.02;
var grid = turf.squareGrid([SW.lng, SW.lat, NE.lng, NE.lat], cellSide, 'kilometers');
console.log(`squareGrid - before:`, grid);
// Set all features to highlighted == 'No'
for (let i = 0; i < grid.features.length; i++) {
grid.features[i].properties.highlighted = 'No';
}
console.log(`squareGrid - after:`, grid);
map.current.on('load', () => {
console.log(`-- Loaded --`);
map.current.addSource('grid-source', {
'type': "geojson",
'data': grid,
'generateId': true
});
map.current.addLayer(
{
'id': 'grid-layer',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': 'rgba(0,0,0,0.1)',
'fill-color': 'rgba(0,0,0,0.1)'
}
}
);
map.current.addLayer(
{
'id': 'grid-layer-highlighted',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': '#484896',
'fill-color': '#6e599f',
'fill-opacity': 0.75
},
'filter': ['==', ['get', 'highlighted'], 'Yes']
}
);
map.current.on('click', 'grid-layer', function (e) {
e.features[0].properties.highlighted = 'Yes';
console.log(`feature:`, e.features[0]);
const filter = ['match', ['get', 'highlighted'], ['Yes', 'No'], true, false];
map.current.setFilter('grid-layer-highlighted', filter);
});
});
// Clean up on unmount
return () => map.current.remove();
});
return (
<div>
<div className="sidebar">
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom}
</div>
<div ref={mapContainer} className="map-container" />
</div>
);
}
export default App;
目前,每次我点击一个单元格时,所有层 'grid-layer-highlighted' 都可见,而我只想突出显示我点击的单元格。
请问有什么帮助吗?
试试这个(我使用索引):
import React, { useRef, useEffect, useState } from 'react';
import mapboxgl from 'mapbox-gl';
import * as turf from '@turf/turf'
mapboxgl.accessToken = 'TOKEN!';
function Mapbox() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-82.659521999370077); // eslint-disable-line no-unused-vars
const [lat, setLat] = useState(9.628698847753714); // eslint-disable-line no-unused-vars
const [zoom, setZoom] = useState(17); // eslint-disable-line no-unused-vars
const [flag, setFlag] = useState(false); // eslint-disable-line no-unused-vars
useEffect(() => {
if (map.current) return;
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/outdoors-v11',
center: [lng, lat],
zoom: zoom,
scrollZoom: true
});
const bounds = map.current.getBounds();
console.log(`bounds:`, bounds);
const NE = bounds.getNorthEast();
const SW = bounds.getSouthWest();
var cellSide = 0.01;
var grid = turf.squareGrid([SW.lng, SW.lat, NE.lng, NE.lat], cellSide, 'kilometers');
console.log(`squareGrid - before:`, grid);
// Set all features to highlighted == 'No'
for (let i = 0; i < grid.features.length; i++) {
grid.features[i].properties.highlighted = 'No';
grid.features[i].properties.id = i;
}
console.log(`squareGrid - after:`, grid);
map.current.on('load', () => {
console.log(`-- Loaded --`);
map.current.addSource('grid-source', {
'type': "geojson",
'data': grid,
'generateId': true
});
map.current.addLayer(
{
'id': 'grid-layer',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': 'rgba(0,0,0,0.1)',
'fill-color': 'rgba(0,0,0,0.1)'
}
}
);
map.current.addLayer(
{
'id': 'grid-layer-highlighted',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': '#484896',
'fill-color': '#6e599f',
'fill-opacity': 0.75
},
//'filter': ['==', ['get', 'highlighted'], 'Yes']
'filter': ['==', ['get', 'id'], -1]
}
);
//click action
map.current.on('click', 'grid-layer', function (e) {
var selectIndex = e.features[0].id;
grid.features[e.features[0].id].properties.highlighted = 'Yes';
console.log(`highlighted before:`, e.features[0].properties.highlighted);
e.features[0].properties.highlighted = 'Yes';
console.log(`feature:`, e.features[0]);
console.log(`selectIndex:`, selectIndex);
console.log(`highlighted after:`, e.features[0].properties.highlighted);
//this! 무야호!
const filter = ['==', ['number', ['get', 'id']], selectIndex];
map.current.setFilter('grid-layer-highlighted', filter);
});
});
// Clean up on unmount
return () => map.current.remove();
});
return (
<div>
<div className="sidebar">
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom} | click : {flag == true}
</div>
<div ref={mapContainer} className="map-container" />
</div>
);
}
export default Mapbox;
结果:
我正在尝试 select 来自我已添加到我的 mapbox js 地图的方形网格层的单元格。
这是我的代码:
import React, { useRef, useEffect, useState } from 'react';
import './App.css';
import mapboxgl from '!mapbox-gl'; // eslint-disable-line import/no-webpack-loader-syntax
import * as turf from '@turf/turf'
mapboxgl.accessToken = 'MY_TOKEN';
function App() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-82.659521999370077); // eslint-disable-line no-unused-vars
const [lat, setLat] = useState(9.628698847753714); // eslint-disable-line no-unused-vars
const [zoom, setZoom] = useState(17); // eslint-disable-line no-unused-vars
useEffect(() => {
if (map.current) return;
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/USER/MAP_ID',
center: [lng, lat],
zoom: zoom,
scrollZoom: true
});
const bounds = map.current.getBounds();
console.log(`bounds:`, bounds);
const NE = bounds.getNorthEast();
const SW = bounds.getSouthWest();
var cellSide = 0.02;
var grid = turf.squareGrid([SW.lng, SW.lat, NE.lng, NE.lat], cellSide, 'kilometers');
console.log(`squareGrid - before:`, grid);
// Set all features to highlighted == 'No'
for (let i = 0; i < grid.features.length; i++) {
grid.features[i].properties.highlighted = 'No';
}
console.log(`squareGrid - after:`, grid);
map.current.on('load', () => {
console.log(`-- Loaded --`);
map.current.addSource('grid-source', {
'type': "geojson",
'data': grid,
'generateId': true
});
map.current.addLayer(
{
'id': 'grid-layer',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': 'rgba(0,0,0,0.1)',
'fill-color': 'rgba(0,0,0,0.1)'
}
}
);
map.current.addLayer(
{
'id': 'grid-layer-highlighted',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': '#484896',
'fill-color': '#6e599f',
'fill-opacity': 0.75
},
'filter': ['==', ['get', 'highlighted'], 'Yes']
}
);
map.current.on('click', 'grid-layer', function (e) {
e.features[0].properties.highlighted = 'Yes';
console.log(`feature:`, e.features[0]);
const filter = ['match', ['get', 'highlighted'], ['Yes', 'No'], true, false];
map.current.setFilter('grid-layer-highlighted', filter);
});
});
// Clean up on unmount
return () => map.current.remove();
});
return (
<div>
<div className="sidebar">
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom}
</div>
<div ref={mapContainer} className="map-container" />
</div>
);
}
export default App;
目前,每次我点击一个单元格时,所有层 'grid-layer-highlighted' 都可见,而我只想突出显示我点击的单元格。
请问有什么帮助吗?
试试这个(我使用索引):
import React, { useRef, useEffect, useState } from 'react';
import mapboxgl from 'mapbox-gl';
import * as turf from '@turf/turf'
mapboxgl.accessToken = 'TOKEN!';
function Mapbox() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(-82.659521999370077); // eslint-disable-line no-unused-vars
const [lat, setLat] = useState(9.628698847753714); // eslint-disable-line no-unused-vars
const [zoom, setZoom] = useState(17); // eslint-disable-line no-unused-vars
const [flag, setFlag] = useState(false); // eslint-disable-line no-unused-vars
useEffect(() => {
if (map.current) return;
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/outdoors-v11',
center: [lng, lat],
zoom: zoom,
scrollZoom: true
});
const bounds = map.current.getBounds();
console.log(`bounds:`, bounds);
const NE = bounds.getNorthEast();
const SW = bounds.getSouthWest();
var cellSide = 0.01;
var grid = turf.squareGrid([SW.lng, SW.lat, NE.lng, NE.lat], cellSide, 'kilometers');
console.log(`squareGrid - before:`, grid);
// Set all features to highlighted == 'No'
for (let i = 0; i < grid.features.length; i++) {
grid.features[i].properties.highlighted = 'No';
grid.features[i].properties.id = i;
}
console.log(`squareGrid - after:`, grid);
map.current.on('load', () => {
console.log(`-- Loaded --`);
map.current.addSource('grid-source', {
'type': "geojson",
'data': grid,
'generateId': true
});
map.current.addLayer(
{
'id': 'grid-layer',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': 'rgba(0,0,0,0.1)',
'fill-color': 'rgba(0,0,0,0.1)'
}
}
);
map.current.addLayer(
{
'id': 'grid-layer-highlighted',
'type': 'fill',
'source': 'grid-source',
'paint': {
'fill-outline-color': '#484896',
'fill-color': '#6e599f',
'fill-opacity': 0.75
},
//'filter': ['==', ['get', 'highlighted'], 'Yes']
'filter': ['==', ['get', 'id'], -1]
}
);
//click action
map.current.on('click', 'grid-layer', function (e) {
var selectIndex = e.features[0].id;
grid.features[e.features[0].id].properties.highlighted = 'Yes';
console.log(`highlighted before:`, e.features[0].properties.highlighted);
e.features[0].properties.highlighted = 'Yes';
console.log(`feature:`, e.features[0]);
console.log(`selectIndex:`, selectIndex);
console.log(`highlighted after:`, e.features[0].properties.highlighted);
//this! 무야호!
const filter = ['==', ['number', ['get', 'id']], selectIndex];
map.current.setFilter('grid-layer-highlighted', filter);
});
});
// Clean up on unmount
return () => map.current.remove();
});
return (
<div>
<div className="sidebar">
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom} | click : {flag == true}
</div>
<div ref={mapContainer} className="map-container" />
</div>
);
}
export default Mapbox;
结果: