import React, { useState, useEffect } from "react"; import { useMap } from "../MapComponent"; import TileLayer from "ol/layer/Tile.js"; import XYZ from "ol/source/XYZ.js"; import mapboxOutdoors from "@assets/map/layers/mapbox-outdoors.png"; import mapboxLight from "@assets/map/layers/mapbox-light.png"; import mapboxSatellite from "@assets/map/layers/mapbox-satellite.png"; import mapboxSatelliteStreet from "@assets/map/layers/mapbox-satellite-streets.png"; import mapboxStreets from "@assets/map/layers/mapbox-streets.png"; import clsx from "clsx"; import Group from "ol/layer/Group"; import { MAPBOX_TOKEN } from "@config/config"; import { TIANDITU_TOKEN } from "@config/config"; const INITIAL_LAYER = "mapbox-light"; const streetsLayer = new TileLayer({ source: new XYZ({ url: `https://api.mapbox.com/styles/v1/mapbox/streets-v12/tiles/256/{z}/{x}/{y}@2x?access_token=${MAPBOX_TOKEN}`, tileSize: 512, maxZoom: 20, projection: "EPSG:3857", attributions: '数据来源:Mapbox & OpenStreetMap', }), }); const lightMapLayer = new TileLayer({ source: new XYZ({ url: `https://api.mapbox.com/styles/v1/mapbox/light-v11/tiles/256/{z}/{x}/{y}@2x?access_token=${MAPBOX_TOKEN}`, tileSize: 512, maxZoom: 20, projection: "EPSG:3857", attributions: '数据来源:Mapbox & OpenStreetMap', }), }); const satelliteLayer = new TileLayer({ source: new XYZ({ url: `https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/256/{z}/{x}/{y}@2x?access_token=${MAPBOX_TOKEN}`, tileSize: 512, maxZoom: 20, projection: "EPSG:3857", attributions: '数据来源:Mapbox & OpenStreetMap', }), }); const satelliteStreetsLayer = new TileLayer({ source: new XYZ({ url: `https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v12/tiles/256/{z}/{x}/{y}@2x?access_token=${MAPBOX_TOKEN}`, tileSize: 512, maxZoom: 20, projection: "EPSG:3857", attributions: '数据来源:Mapbox & OpenStreetMap', }), }); const tiandituVectorLayer = new TileLayer({ source: new XYZ({ url: `https://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIANDITU_TOKEN}`, projection: "EPSG:3857", attributions: '数据来源:天地图', }), }); const tiandituVectorAnnotationLayer = new TileLayer({ source: new XYZ({ url: `https://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIANDITU_TOKEN}`, projection: "EPSG:3857", attributions: '数据来源:天地图', }), }); const tiandituImageLayer = new TileLayer({ source: new XYZ({ url: `https://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIANDITU_TOKEN}`, projection: "EPSG:3857", attributions: '数据来源:天地图', }), }); const tiandituImageAnnotationLayer = new TileLayer({ source: new XYZ({ url: `https://t0.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIANDITU_TOKEN}`, projection: "EPSG:3857", attributions: '数据来源:天地图', }), }); const tiandituVectorLayerGroup = new Group({ layers: [tiandituVectorLayer, tiandituVectorAnnotationLayer], }); const tiandituImageLayerGroup = new Group({ layers: [tiandituImageLayer, tiandituImageAnnotationLayer], }); const baseLayers = [ { id: "mapbox-light", name: "默认地图", layer: lightMapLayer, // layer: tiandituVectorLayerGroup, img: mapboxLight.src, }, { id: "mapbox-satellite", name: "卫星地图", layer: satelliteLayer, // layer: tiandituImageLayerGroup, img: mapboxSatellite.src, }, { id: "mapbox-satellite-streets", name: "卫星街道地图", layer: satelliteStreetsLayer, img: mapboxSatelliteStreet.src, }, { id: "mapbox-streets", name: "街道地图", layer: streetsLayer, img: mapboxStreets.src, }, ]; const BaseLayers: React.FC = () => { const map = useMap(); // 切换底图选项展开,控制显示和卸载 const [isShow, setShow] = useState(false); const [isExpanded, setExpanded] = useState(false); // 快速切换底图 const [activeId, setActiveId] = useState(INITIAL_LAYER); // 初始化默认底图 useEffect(() => { if (!map) return; // 添加所有底图至地图并根据 activeId 控制可见性 baseLayers.forEach((layerInfo) => { const layers = map.getLayers().getArray(); if (!layers.includes(layerInfo.layer)) { map.getLayers().insertAt(0, layerInfo.layer); } layerInfo.layer.setVisible(layerInfo.id === activeId); }); }, [map]); const changeMapLayers = (id: string) => { if (map) { // 根据 id 设置每个图层的可见性 baseLayers.forEach(({ id: lid, layer }) => { layer.setVisible(lid === id); }); } }; const handleQuickSwitch = () => { const nextId = activeId === baseLayers[0].id ? baseLayers[1].id : baseLayers[0].id; setActiveId(nextId); handleMapLayers(nextId); }; const handleMapLayers = (id: string) => { setActiveId(id); changeMapLayers(id); }; // 记录定时器,避免多次触发 const hideTimer = React.useRef(null); const handleEnter = () => { if (hideTimer.current) { clearTimeout(hideTimer.current); hideTimer.current = null; } setShow(true); setExpanded(true); }; const handleLeave = () => { setShow(false); hideTimer.current = setTimeout(() => { setExpanded(false); }, 300); }; return (
{isExpanded && (
{baseLayers.map((item) => ( ))}
)}
); }; export default BaseLayers;