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

Next.js 13中Leaflet Routing Machine路线显示问题求助

在Next.js 13中使用Leaflet Routing Machine实现路线展示

你遇到的核心问题是没有正确封装Leaflet Routing Machine的控制组件,同时useMap的使用方式有误。下面是具体的解决步骤和修改后的代码:

步骤1:封装Leaflet Routing Machine组件

react-leaflet并未内置Leaflet Routing Machine的组件,需要用createControlComponent手动封装:

import { createControlComponent } from "@react-leaflet/core";
import L from "leaflet";
import "leaflet-routing-machine";

const createRoutingMachineLayer = (props) => {
  const instance = L.Routing.control({
    waypoints: [
      L.latLng(...props.start),
      L.latLng(...props.end),
    ],
    lineOptions: {
      styles: [{ color: "#6FA1EC", weight: 4 }]
    },
    show: false,
    addWaypoints: false,
    routeWhileDragging: true,
    draggableWaypoints: true,
    fitSelectedRoutes: true,
    showAlternatives: false
  });

  return instance;
};

const RoutingMachine = createControlComponent(createRoutingMachineLayer);

步骤2:修正代码中的无效逻辑

你的route函数对useMap的调用错误,且该函数本身无实际作用,封装完组件后可直接使用RoutingMachine组件替代。

步骤3:整合到你的Home组件中

修改后的完整代码如下:

import Image from 'next/image'
import 'leaflet/dist/leaflet.css'
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import { useState } from 'react';
import { Switch } from '@headlessui/react';
import bus from '../public/bus.jpg'
import { createControlComponent } from "@react-leaflet/core";
import L from "leaflet";
import "leaflet-routing-machine";

// 封装Routing Machine组件
const createRoutingMachineLayer = (props) => {
  const instance = L.Routing.control({
    waypoints: [
      L.latLng(...props.start),
      L.latLng(...props.end),
    ],
    lineOptions: {
      styles: [{ color: "#6FA1EC", weight: 4 }]
    },
    show: false,
    addWaypoints: false,
    routeWhileDragging: true,
    draggableWaypoints: true,
    fitSelectedRoutes: true,
    showAlternatives: false
  });

  return instance;
};

const RoutingMachine = createControlComponent(createRoutingMachineLayer);

const busStops: string[] = [
  "ATM/ LIBRARY",
  "ADMIN",
  "MURNI",
  "BW",
  "AMANAH",
  "DSS",
  "ILMU",
  "COE",
];

export default function Home() {
  const [show, setShow] = useState(false);
  // 替换为你实际的起点和终点坐标(对应地图上的两个Marker)
  const startPoint = [2.976644517019155, 101.73402673751899]; // 图书馆
  const endPoint = [2.9776400979295072, 101.73074640990319]; // Admin楼

  return (
    <div className='w-screen bg-red-500 h-screen flex'>
      <div className='w-[400px] bg-white flex flex-col '>
        <div className='w-full h-[80px]  flex justify-center items-center'>
          <h1 className=' text-black'>Route Infomation</h1>
        </div>
        <div className=' h-full bg-white justify-center items-center flex flex-col p-10 space-y-12'>
          {busStops.map(stop => (
            <div key={stop} className=' w-full bg-white  text-black text-center'>{stop}</div>
          ))}
        </div>
      </div>

      <MapContainer center={[2.976644517019155, 101.73402673751899]} zoom={16} scrollWheelZoom={true} className=' w-full h-full z-10'>
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />

        <Marker position={endPoint}>
          <Popup>
            UNITEN Admin Building<br />
          </Popup>
        </Marker>

        <Marker position={startPoint}>
          <Popup>
            <div className='w-[300px] h-[400px] flex flex-col rounded-lg'>
              <div className=' h-1/3 w-full bg-white ease-in-out'>
                <Image className='rounded-xl h-full' src={bus} alt='Bus' />
              </div>
              <div className='flex justify-between items-center px-5'>
                <div>Uniten Library</div>
                <p>ETA</p>
                <p>Arrival Status</p>
              </div>
              <div className='flex'>
                <div className=' h-1/3 w-full p-5'>Driver 1 </div>
                <div className=' h-1/3 w-full p-5'>ETA: 7:45 AM</div>
                <Switch
                  checked={show}
                  onChange={setShow}
                  className={`${show ? 'bg-green-500' : 'bg-gray-700'}
                    relative inline-flex h-[28px] w-[64px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75`}
                >
                  <span className="sr-only">Use setting</span>
                  <span
                    aria-hidden="true"
                    className={`${show ? 'translate-x-9' : 'translate-x-0'}
                      pointer-events-none inline-block h-[24px] w-[24px] transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out`}
                  />
                </Switch>
              </div>
            </div>
          </Popup>
        </Marker>

        {/* 渲染路线组件 */}
        <RoutingMachine start={startPoint} end={endPoint} />
      </MapContainer>
    </div>
  )
}

关键说明

  • 封装的RoutingMachine组件接收start和end属性,对应起点和终点的经纬度数组
  • 调整地图zoom值为16,避免层级过大导致的显示异常
  • 移除了无用的Google Maps相关导入,简化代码结构
  • 用map方法渲染公交站点列表,提升代码可维护性

内容的提问来源于stack exchange,提问作者Ibrahim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:59:57