🗺️ 第 8 节:路径规划与导航功能
1. 📢 引言:老曹的吐槽时间
各位朋友好,我是老曹。今天咱们来到第 8 节,路径规划与导航功能。说实话,做地图开发最怕啥?最怕老板突然走过来问:“老曹,为啥用户点击导航后,路线绕了个大圈?”这时候你不能说“算法就是这么算的”,你得说“马上优化”。
🌏路径规划这玩意儿,表面上看就是画条线,实际上背后全是钱和算力。用户才不管你用的是 Dijkstra 还是 A*,他们只关心能不能早点到家吃上热乎饭。所以今天这节课,咱们不整那些虚头巴脑的数学证明,直接上干货,怎么调 API,怎么渲染,怎么别让 traffic 流量把您的服务器搞崩。
咱们这节课的核心就几个词:步行、驾车、公交、多段路线、实时交通。别觉得简单,这里面的坑,比早高峰的环路还多。比如坐标系偏了怎么办?API 配额超了怎么办?路线画到海里去了怎么办?代码写好点,测试多跑点,别上线了再哭。
🔫 以前咱们讲过 marker,讲过polyline,今天就是把它们结合起来,赋予灵魂。一条没有导航功能的地图,就像是没有导航的手机,只能当砖头用。
好了,废话不多说,系好安全带,咱们准备发车。本节课内容略多,建议收藏慢慢看,别到时候找不到又得回来求我。
2. 🎯 学习目标:知道去哪,才知道怎么走
3. 🧠 思维导图:全景视角看导航
#mermaid-svg-rCXnUNfyl1tvzIcX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rCXnUNfyl1tvzIcX .error-icon{fill:#552222;}#mermaid-svg-rCXnUNfyl1tvzIcX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rCXnUNfyl1tvzIcX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rCXnUNfyl1tvzIcX .marker.cross{stroke:#333333;}#mermaid-svg-rCXnUNfyl1tvzIcX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rCXnUNfyl1tvzIcX p{margin:0;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge{stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .section–1 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section–1 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section–1 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section–1 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section–1 text{fill:#ffffff;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth–1{stroke-width:17;}#mermaid-svg-rCXnUNfyl1tvzIcX .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-0 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-0 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-0 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-0 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-0 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-0{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-0{stroke-width:14;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-1 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-1 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-1 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-1 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-1 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-1{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-1{stroke-width:11;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 text{fill:#ffffff;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-2{stroke-width:8;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-3 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-3 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-3 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-3 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-3 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-3{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-3{stroke-width:5;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-4 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-4 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-4 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-4 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-4 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-4{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-4{stroke-width:2;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-5 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-5 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-5 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-5 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-5 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-5{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-5{stroke-width:-1;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-6 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-6 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-6 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-6 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-6 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-6{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-6{stroke-width:-4;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-7 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-7 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-7 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-7 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-7 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-7{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-7{stroke-width:-7;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-8 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-8 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-8 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-8 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-8 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-8{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-8{stroke-width:-10;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-9 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-9 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-9 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-9 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-9 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-9{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-9{stroke-width:-13;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-10 rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-10 path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-10 circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-10 polygon,#mermaid-svg-rCXnUNfyl1tvzIcX .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-10 text{fill:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .node-icon-10{font-size:40px;color:black;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .edge-depth-10{stroke-width:-16;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled circle,#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:lightgray;}#mermaid-svg-rCXnUNfyl1tvzIcX .disabled text{fill:#efefef;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-root rect,#mermaid-svg-rCXnUNfyl1tvzIcX .section-root path,#mermaid-svg-rCXnUNfyl1tvzIcX .section-root circle,#mermaid-svg-rCXnUNfyl1tvzIcX .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-rCXnUNfyl1tvzIcX .section-root text{fill:#ffffff;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-root span{color:#ffffff;}#mermaid-svg-rCXnUNfyl1tvzIcX .section-2 span{color:#ffffff;}#mermaid-svg-rCXnUNfyl1tvzIcX .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-rCXnUNfyl1tvzIcX .edge{fill:none;}#mermaid-svg-rCXnUNfyl1tvzIcX .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-rCXnUNfyl1tvzIcX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
路径规划与导航
核心模式
驾车 Driving
步行 Walking
公交 Transit
骑行 Cycling
关键技术
地理编码转换
路径算法策略
实时路况 Traffic
多段路线拼接
渲染呈现
Polyline 绘制
Marker 起点终点
InfoWindow 详情
动画模拟
性能与优化
API 配额管理
缓存策略
异步加载
降级方案
4. ⚙️ 原理详解与流程图:黑盒子里的秘密
#mermaid-svg-kAoG60o2ixHaDbXd{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kAoG60o2ixHaDbXd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kAoG60o2ixHaDbXd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kAoG60o2ixHaDbXd .error-icon{fill:#552222;}#mermaid-svg-kAoG60o2ixHaDbXd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kAoG60o2ixHaDbXd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kAoG60o2ixHaDbXd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kAoG60o2ixHaDbXd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kAoG60o2ixHaDbXd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kAoG60o2ixHaDbXd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kAoG60o2ixHaDbXd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kAoG60o2ixHaDbXd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kAoG60o2ixHaDbXd .marker.cross{stroke:#333333;}#mermaid-svg-kAoG60o2ixHaDbXd svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kAoG60o2ixHaDbXd p{margin:0;}#mermaid-svg-kAoG60o2ixHaDbXd .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-kAoG60o2ixHaDbXd .cluster-label text{fill:#333;}#mermaid-svg-kAoG60o2ixHaDbXd .cluster-label span{color:#333;}#mermaid-svg-kAoG60o2ixHaDbXd .cluster-label span p{background-color:transparent;}#mermaid-svg-kAoG60o2ixHaDbXd .label text,#mermaid-svg-kAoG60o2ixHaDbXd span{fill:#333;color:#333;}#mermaid-svg-kAoG60o2ixHaDbXd .node rect,#mermaid-svg-kAoG60o2ixHaDbXd .node circle,#mermaid-svg-kAoG60o2ixHaDbXd .node ellipse,#mermaid-svg-kAoG60o2ixHaDbXd .node polygon,#mermaid-svg-kAoG60o2ixHaDbXd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kAoG60o2ixHaDbXd .rough-node .label text,#mermaid-svg-kAoG60o2ixHaDbXd .node .label text,#mermaid-svg-kAoG60o2ixHaDbXd .image-shape .label,#mermaid-svg-kAoG60o2ixHaDbXd .icon-shape .label{text-anchor:middle;}#mermaid-svg-kAoG60o2ixHaDbXd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kAoG60o2ixHaDbXd .rough-node .label,#mermaid-svg-kAoG60o2ixHaDbXd .node .label,#mermaid-svg-kAoG60o2ixHaDbXd .image-shape .label,#mermaid-svg-kAoG60o2ixHaDbXd .icon-shape .label{text-align:center;}#mermaid-svg-kAoG60o2ixHaDbXd .node.clickable{cursor:pointer;}#mermaid-svg-kAoG60o2ixHaDbXd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kAoG60o2ixHaDbXd .arrowheadPath{fill:#333333;}#mermaid-svg-kAoG60o2ixHaDbXd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kAoG60o2ixHaDbXd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kAoG60o2ixHaDbXd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kAoG60o2ixHaDbXd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kAoG60o2ixHaDbXd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kAoG60o2ixHaDbXd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kAoG60o2ixHaDbXd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kAoG60o2ixHaDbXd .cluster text{fill:#333;}#mermaid-svg-kAoG60o2ixHaDbXd .cluster span{color:#333;}#mermaid-svg-kAoG60o2ixHaDbXd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kAoG60o2ixHaDbXd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kAoG60o2ixHaDbXd rect.text{fill:none;stroke-width:0;}#mermaid-svg-kAoG60o2ixHaDbXd .icon-shape,#mermaid-svg-kAoG60o2ixHaDbXd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kAoG60o2ixHaDbXd .icon-shape p,#mermaid-svg-kAoG60o2ixHaDbXd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kAoG60o2ixHaDbXd .icon-shape rect,#mermaid-svg-kAoG60o2ixHaDbXd .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kAoG60o2ixHaDbXd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kAoG60o2ixHaDbXd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kAoG60o2ixHaDbXd :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
否
是
成功
失败
用户输入起终点
坐标是否有效?
调用地理编码转换
构建路径规划请求
发送 API 请求到地图服务器
服务器返回状态
解析路径数据 Steps
展示错误提示
清除旧路线
绘制新 Polyline
添加起点终点 Marker
调整地图视野 fitView
叠加实时交通图层
✅ 看图说话:首先,用户输入的可能是地址,也可能是坐标。如果是地址,必须先调地理编码(第 7
节内容),不然服务器听不懂。然后,构建请求时要注意策略,是“最快”还是“最短”。
✅ 拿到响应后,别急着画。先清除旧的路线,不然地图上全是线,跟蜘蛛网似的。画线的时候,注意坐标顺序,别画反了。最后,一定要 fitView,不然路线画到屏幕外去了,用户以为出 bug 了。
✅ 关于实时交通,这通常是独立的图层。你需要开启 traffic 选项,地图 SDK 会根据当前路况给道路着色。注意,这个功能在某些免费层级里可能是受限的,看清楚了文档再写代码。
5. 💻 代码实战:老曹的私房代码
光说不练假把式。下面这段代码是基于高德地图 JS API 2.0 的驾车路径规划示例。
// 1. 初始化地图实例
const map = new AMap.Map('container', {
zoom: 11,
center: [116.397428, 39.90923] // 北京中心
});
// 2. 初始化驾车路径规划实例
// 注意:policy 策略很重要,0 最快,1 最短路,2 避免收费
const driving = new AMap.Driving({
map: map,
panel: "panel", // 自动显示面板,生产环境建议自定义
policy: AMap.DrivingPolicy.LEAST_TIME
});
// 3. 定义搜索函数
function planRoute(start, end) {
// 4. 清空旧数据,防止内存泄漏
driving.clear();
// 5. 执行路径搜索
// 这里的 start 和 end 可以是坐标 [lng, lat] 也可以是地址字符串
driving.search(start, end, (status, result) => {
if (status === 'complete') {
console.log('路线规划成功', result);
// 6. 这里可以获取详细步骤 result.routes[0].steps
// 可以遍历 steps 做更精细的渲染或语音播报提示
} else {
console.error('路线规划失败:', status);
// 7. 友好提示用户,比如“终点 unreachable"
alert('无法规划路线,请检查起点终点是否合理');
}
});
}
// 8. 调用示例
planRoute('北京西站', '天安门');
6. 🎤 十大面试题:背下来能救命
- A: 肯定有。免费版通常每天几千次。超了会返回错误码。解决方案:前端做缓存,相同起点终点别重复请求;后端代理请求,统一管理 Key。
- A: 驾车走路网,考虑单行道、限速、拥堵;步行走小路,考虑台阶、禁止通行区域。权重计算模型完全不同。
- A: 监听用户实时位置,计算当前位置与规划路线的距离。超过阈值(如 50 米)触发重新 search。注意防抖,别动一下就重算。
- A: 检查输入坐标是 WGS84 还是 GCJ02。高德百度用 GCJ02/BD09,Google 用 WGS84。混用必偏,必须统一转换。
- A: 提取公共配置对象,或者封装一个 RouteRenderer 类,统一控制颜色、宽度、虚线样式。
- A: 难点在于换乘方案多,且涉及时刻表。前端通常只展示结果,复杂计算交给服务端。
- A: 遍历路径 steps,计算累积距离,在关键节点添加 Text 或 Marker 覆盖物。
- A: 起点终点相同、起点终点在禁区(如海里)、网络超时、Key 过期、配额用完。
- A: 使用 Canvas 层渲染而不是 DOM 层,减少覆盖物数量,采用聚合策略,或者只显示当前视口内的路线。
- A: 移除所有 Polyline 和 Marker,取消事件监听,清除定时器,防止内存泄漏导致页面卡顿。
7. 📊 总结表格:一图胜千言
| 驾车规划 | AMap.Driving | 注意单行道限制 | 中 | 优先选“最快”策略 |
| 步行规划 | AMap.Walking | 小路数据可能不准 | 低 | 适合最后一公里场景 |
| 公交规划 | AMap.Transit | 方案多,结构复杂 | 高 | 建议服务端处理逻辑 |
| 实时路况 | map.setFeatures | 消耗流量和 GPU | 高 | 低端机默认关闭 |
| 多段路线 | AMap.Polyline | 需手动管理数组 | 中 | 封装统一渲染器 |
| 坐标转换 | AMap.ConvertFrom | 耗时,需异步 | 低 | 输入前统一预处理 |
| 路径清除 | route.clear() | 易遗漏导致重影 | 无 | 每次搜索前必调用 |
| 视野调整 | map.fitView() | 可能缩放过度 | 无 | 加个 padding 更美观 |
| 错误处理 | status 判断 | 用户体验关键 | 无 | 别让用户看代码错误 |
| 配额管理 | 控制台查看 | 超量服务中断 | 无 | 建立监控报警机制 |
