You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在react-leaflet中实现类似Ellipsis Drive的时间戳选择与地图居中组件

在React-Leaflet中实现时间戳选择与地图居中组件

1. 核心依赖准备

先安装必要的包:

npm install react-leaflet leaflet react-datepicker date-fns

2. 实现时间选择组件(支持单/范围切换)

自定义一个时间选择器,支持切换单时间戳和时间范围模式:

import React, { useState } from 'react';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';

const TimestampSelector = ({ onTimeChange }) => {
  const [isRange, setIsRange] = useState(false);
  const [selectedTime, setSelectedTime] = useState(new Date());
  const [timeRange, setTimeRange] = useState([null, null]);

  const handleTimeSelect = (value) => {
    if (isRange) {
      setTimeRange(value);
      onTimeChange({ type: 'range', value });
    } else {
      setSelectedTime(value);
      onTimeChange({ type: 'single', value });
    }
  };

  return (
    <div className="timestamp-selector" style={{ padding: '10px', background: 'white', borderRadius: '4px', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' }}>
      <div style={{ marginBottom: '8px' }}>
        <label>
          <input 
            type="checkbox" 
            checked={isRange} 
            onChange={(e) => setIsRange(e.target.checked)} 
          />
          启用时间范围选择
        </label>
      </div>
      {isRange ? (
        <DatePicker
          selectsRange
          startDate={timeRange[0]}
          endDate={timeRange[1]}
          onChange={handleTimeSelect}
          dateFormat="yyyy-MM-dd HH:mm"
          placeholderText="选择开始和结束时间"
        />
      ) : (
        <DatePicker
          selected={selectedTime}
          onChange={handleTimeSelect}
          dateFormat="yyyy-MM-dd HH:mm"
          showTimeSelect
          timeFormat="HH:mm"
          timeIntervals={15}
          placeholderText="选择时间戳"
        />
      )}
    </div>
  );
};

export default TimestampSelector;

3. 实现地图居中控制组件

利用React-Leaflet的useMap钩子获取地图实例,实现一键居中到目标区域:

import React from 'react';
import { useMap } from 'react-leaflet';

const MapCenterControl = ({ centerCoords = [51.505, -0.09], zoom = 13 }) => {
  const map = useMap();

  const handleCenterMap = () => {
    map.setView(centerCoords, zoom);
  };

  return (
    <button 
      onClick={handleCenterMap}
      style={{ 
        padding: '8px 12px', 
        margin: '10px', 
        background: 'white', 
        border: 'none', 
        borderRadius: '4px', 
        boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
        cursor: 'pointer'
      }}
    >
      重置地图居中
    </button>
  );
};

export default MapCenterControl;

4. 整合到React-Leaflet地图中

将两个组件与图层结合,根据选中的时间更新图层数据或参数:

import React, { useState } from 'react';
import { MapContainer, TileLayer, GeoJSON } from 'react-leaflet';
import TimestampSelector from './TimestampSelector';
import MapCenterControl from './MapCenterControl';
import 'leaflet/dist/leaflet.css';

// 模拟带时间维度的图层数据
const timeAwareGeoData = [
  {
    timestamp: new Date('2024-01-01'),
    features: [/* 替换为你的GeoJSON要素数据 */]
  },
  {
    timestamp: new Date('2024-01-02'),
    features: [/* 替换为你的GeoJSON要素数据 */]
  }
];

const TimeAwareMap = () => {
  const [currentLayerData, setCurrentLayerData] = useState(timeAwareGeoData[0].features);

  const handleTimeChange = (timeConfig) => {
    // 根据选中的时间过滤或切换图层数据
    let filteredData = [];
    if (timeConfig.type === 'single') {
      const match = timeAwareGeoData.find(item => 
        item.timestamp.toDateString() === timeConfig.value.toDateString()
      );
      filteredData = match?.features || [];
    } else {
      filteredData = timeAwareGeoData
        .filter(item => 
          item.timestamp >= timeConfig.value[0] && item.timestamp <= timeConfig.value[1]
        )
        .flatMap(item => item.features);
    }
    setCurrentLayerData(filteredData);
  };

  return (
    <div style={{ height: '100vh', width: '100%' }}>
      <MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: '100%', width: '100%' }}>
        <TileLayer
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        />
        <GeoJSON data={currentLayerData} />
        
        {/* 挂载时间选择组件到地图右上角 */}
        <div style={{ position: 'absolute', top: '10px', right: '10px', zIndex: 1000 }}>
          <TimestampSelector onTimeChange={handleTimeChange} />
        </div>
        
        {/* 挂载地图居中控件到地图左下角 */}
        <div style={{ position: 'absolute', bottom: '10px', left: '10px', zIndex: 1000 }}>
          <MapCenterControl />
        </div>
      </MapContainer>
    </div>
  );
};

export default TimeAwareMap;

关键说明

  • 时间选择逻辑:根据单时间/范围模式,过滤对应时间维度的图层数据,更新GeoJSON组件的data属性;如果是带时间参数的TileLayer(比如WMS服务),可以动态修改url中的时间参数实现图层切换。
  • 地图居中:通过useMap获取Leaflet原生地图实例,调用setView方法实现精准居中,可自定义默认中心点和缩放级别。
  • 样式自定义:可根据需求调整组件的位置、外观,匹配目标UI风格。

内容的提问来源于stack exchange,提问作者Mirza Zohaib Baig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:35:26