Add interactions to a Mapbox Standard Style
This example demonstrates how to use addInteraction
with Mapbox Standard Style's built-in Featuresets and configuration properties. It shows how to:
- Highlight place labels on hover using the
highlight
feature state andcolorPlaceLabelHighlight
configuration property - Select place labels on click using the
select
feature state andcolorPlaceLabelSelect
configuration property
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Add interactions to a Mapbox Standard Style</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v3.10.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.10.0/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<style>
.map-overlay {
position: absolute;
right: 0;
top: 0;
width: 230px;
padding: 10px;
color: #1a2224;
font: 12px/20px sans-serif;
display: none;
}
.map-overlay-inner {
background: #fff;
padding: 10px;
border-radius: 3px;
}
</style>
<div id="map"></div>
<div class="map-overlay" id="properties"></div>
<script>
// TO MAKE THE MAP APPEAR YOU MUST
// ADD YOUR ACCESS TOKEN FROM
// https://account.mapbox.com
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
const map = new mapboxgl.Map({
container: 'map',
center: [-74, 40.72],
zoom: 12,
bearing: 30,
style: 'mapbox://styles/mapbox/standard',
config: {
// Mapbox Standard offers a set of configuration properties that can be used to change the appearance of the basemap.
// The configuration can be updated in runtime using `setConfigProperty` or by providing the `config` object during map initialization.
// See the full list of available properties in the Mapbox Standard style documentation: https://docs.mapbox.com/mapbox-gl-js/guides/styles/#mapbox-standard-1
'basemap': {
'colorPlaceLabelHighlight': 'red',
'colorPlaceLabelSelect': 'blue'
}
}
});
let selectedPlace;
let hoveredPlace;
const card = document.getElementById('properties');
const showCard = (feature) => {
const state = Object.entries(map.getFeatureState(feature))
.map(([key, value]) => `<li><b>${key}</b>: ${value}</li>`)
.join('');
const properties = Object.entries(feature.properties)
.map(([key, value]) => `<li><b>${key}</b>: ${value}</li>`)
.join('');
card.innerHTML = `
`;
card.style.display = 'block';
};
// Place Click Interaction:
// Uses 'select' feature state to persistently highlight selected place
// Selected color controlled by `colorPlaceLabelSelect` configuration property
map.addInteraction('place-click', {
type: 'click',
target: { featuresetId: 'place-labels', importId: 'basemap' },
handler: ({ feature }) => {
if (selectedPlace) {
map.setFeatureState(selectedPlace, { select: false });
}
selectedPlace = feature;
map.setFeatureState(feature, { select: true });
showCard(feature);
}
});
// Place Hover Interaction:
// Uses `highlight` feature state for temporary hover effect
// Highlight color controlled by `colorPlaceLabelHighlight` configuration property
map.addInteraction('place-mouseenter', {
type: 'mouseenter',
target: { featuresetId: 'place-labels', importId: 'basemap' },
handler: ({ feature }) => {
if (hoveredPlace && hoveredPlace.id === feature.id) return;
if (hoveredPlace) {
map.setFeatureState(hoveredPlace, { highlight: false });
}
hoveredPlace = feature;
map.setFeatureState(feature, { highlight: true });
map.getCanvas().style.cursor = 'pointer';
if (!selectedPlace) {
showCard(feature);
}
}
});
// Place Hover Interaction:
// Removes `highlight` feature state when mouse leaves place label
map.addInteraction('place-mouseleave', {
type: 'mouseleave',
target: { featuresetId: 'place-labels', importId: 'basemap' },
handler: () => {
if (hoveredPlace) {
map.setFeatureState(hoveredPlace, { highlight: false });
hoveredPlace = null;
}
if (!selectedPlace) {
card.style.display = 'none';
}
map.getCanvas().style.cursor = '';
return false;
}
});
// Map Click Interaction:
// Clears 'select' feature state when clicking on map background
map.addInteraction('map-click', {
type: 'click',
handler: () => {
if (selectedPlace) {
map.setFeatureState(selectedPlace, { select: false });
selectedPlace = null;
}
card.style.display = 'none';
return false;
}
});
</script>
</body>
</html>
このコードスニペットは、
YOUR_MAPBOX_ACCESS_TOKEN
をあなたのMapboxアカウントのアクセストークンに置き換えるまで、期待通りに動作しません。import React, { useState, useEffect, useRef } from 'react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
const MapboxExample = () => {
const mapContainerRef = useRef(null);
const mapRef = useRef(null);
// State
const [selectedPlace, setSelectedPlace] = useState(null);
const [hoveredPlace, setHoveredPlace] = useState(null);
// Refs to track the latest state values
const selectedPlaceRef = useRef(null);
const hoveredPlaceRef = useRef(null);
useEffect(() => {
// TO MAKE THE MAP APPEAR YOU MUST
// ADD YOUR ACCESS TOKEN FROM
// https://account.mapbox.com
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
const map = (mapRef.current = new mapboxgl.Map({
container: mapContainerRef.current,
center: [-74, 40.72],
zoom: 12,
bearing: 30,
style: 'mapbox://styles/mapbox/standard',
config: {
basemap: {
colorPlaceLabelHighlight: 'red',
colorPlaceLabelSelect: 'blue'
}
}
}));
map.addInteraction('place-click', {
type: 'click',
target: { featuresetId: 'place-labels', importId: 'basemap' },
handler: ({ feature }) => {
if (selectedPlaceRef.current) {
map.setFeatureState(selectedPlaceRef.current, { select: false });
}
map.setFeatureState(feature, { select: true });
setSelectedPlace(feature);
}
});
map.addInteraction('place-mouseenter', {
type: 'mouseenter',
target: { featuresetId: 'place-labels', importId: 'basemap' },
handler: ({ feature }) => {
if (
hoveredPlaceRef.current &&
hoveredPlaceRef.current.id === feature.id
)
return;
if (hoveredPlaceRef.current) {
map.setFeatureState(hoveredPlaceRef.current, { highlight: false });
}
map.getCanvas().style.cursor = 'pointer';
map.setFeatureState(feature, { highlight: true });
setHoveredPlace(feature);
}
});
map.addInteraction('place-mouseleave', {
type: 'mouseleave',
target: { featuresetId: 'place-labels', importId: 'basemap' },
handler: () => {
if (hoveredPlaceRef.current) {
map.setFeatureState(hoveredPlaceRef.current, { highlight: false });
setHoveredPlace(null);
}
map.getCanvas().style.cursor = '';
}
});
map.addInteraction('map-click', {
type: 'click',
handler: () => {
if (selectedPlaceRef.current) {
map.setFeatureState(selectedPlaceRef.current, { select: false });
setSelectedPlace(null);
}
}
});
return () => map.remove();
}, []);
// Sync Refs with State
useEffect(() => {
selectedPlaceRef.current = selectedPlace;
}, [selectedPlace]);
useEffect(() => {
hoveredPlaceRef.current = hoveredPlace;
}, [hoveredPlace]);
const displayFeature = selectedPlace || hoveredPlace;
return (
<div style={{ position: 'relative', width: '100%', height: '100vh' }}>
<div ref={mapContainerRef} style={{ width: '100%', height: '100%' }} />
<div
className="map-overlay"
style={{
position: 'absolute',
right: 0,
top: 0,
width: '230px',
padding: '10px',
color: '#1a2224',
fontSize: '12px',
lineHeight: '20px',
fontFamily: 'sans-serif'
}}
>
{displayFeature && (
<div
className="map-overlay-inner"
style={{
background: '#fff',
padding: '10px',
borderRadius: '3px'
}}
>
<b>featureset</b>: <code>{displayFeature.target.featuresetId}</code>
<br />
<b>feature state</b>:{' '}
<code>
{Object.entries(
mapRef.current.getFeatureState(displayFeature)
).map(([key, value]) => (
<li>
<b>{key}</b>: {value.toString()}
</li>
))}
</code>
<hr />
<b>properties</b>
{Object.entries(displayFeature.properties).map(([key, value]) => (
<li>
<b>{key}</b>: {value.toString()}
</li>
))}
</div>
)}
</div>
</div>
);
};
export default MapboxExample;
このコードスニペットは、
YOUR_MAPBOX_ACCESS_TOKEN
をあなたのMapboxアカウントのアクセストークンに置き換えるまで、期待通りに動作しません。このexampleは役に立ちましたか?