核心内容摘要
520886.com:解锁美国互联网新大陆的数字密码
点赞 关注 收藏 学会了本文简介在 Web 应用和游戏中路径规划是一个核心功能无论是在地图导航、策略游戏的单位移动还是虚拟现实中的导航辅助都离不开高效的路径查找算法。
在一个 Web 项目中路径规划通常是放在后端做的。
但其实前端也可以实现这个功能。
在前端实现还可以降低服务器压力。
PathFinding.js作为一个基于网格的纯前端路径规划工具其轻量级、易于集成和强大的功能是「纯前端」实现路径规划的一个不错选择。
本文将探讨PathFinding.js的基础
使用方法。
在学习PathFinding.js之前可以先体验一下它的能力。
体验地址https://qiao.github.io/PathFinding.js/visual/PathFinding.js仓库https://github.com/qiao/PathFinding.js安装使用 npm 的方式将PathFinding.js安装到项目中npminstallpathfinding基础用法我用ReactPathFinding.js举例说明。
使用PathFinding.js实现路径规划需要做以下几步引入PathFinding.js。
创建网格地图有地图才有路嘛。
设置路障哪里不可以走。
设置起点和终点调用路径规划算法将可行路径规划出来。
一步步来先看看这些功能要调哪些API。
引入 PathFinding.js在使用PathFinding.js之前需要将其引入。
importPFfrompathfinding
创建网格 (Grid)PF.Grid是PathFinding.js库中的一个核心组件它用于创建和表示一个二维网格这个网格是路径查找算法的基础。
constgridnewPF.Grid(width,height)width 和 height 是网格的宽和高。
每个网格点初始化为通行 (
。
举个例子。
// 创建一个 10x10 的网格constgridnewPF.Grid(10,
console.log(grid)在控制台可以看到这个地图其实就是一个二维数组长和宽都是10个元素。
设置路障通过grid.setWalkableAt()方法可以设置指定节点的状态。
通过grid.isWalkableAt()可以检查指定节点是否可通行。
grid.setWalkableAt(x,y,walkable)grid.isWalkableAt(x,y)setWalkableAt(x, y, walkable)设置某点是否可通行。
isWalkableAt(x, y)检查某点是否可通行。
举个例子。
// 设置 (5,
为不可通行grid.setWalkableAt(5,5,false)// 检查 (5,
是否可通行console.log(grid.isWalkableAt(5,
)// false
查找路径PathFinding.js提供了很多种查找路径的算法我们先试试PF.AStarFinder算法。
查找路径具体用法如下constfindernewPF.AStarFinder(options);constpathfinder.findPath(startX,startY,endX,endY,grid);options配置寻路算法的选项如是否允许对角移动。
findPath(startX, startY, endX, endY, grid)寻找从起点到终点的路径。
startX和startY起点坐标。
endX和endY终点坐标。
grid网格地图。
返回值是路径点数组[ [x1, y1], [x2, y2], ... ]。
举个例子。
constfindernewPF.AStarFinder();constpathfinder.findPath(0,0,9,9,grid.clone());console.log(path);除了AStarFinderPathFinding.js提供了多种算法BreadthFirstFinderDijkstraFinderBiAStarFinderBiBreadthFirstFinderBiDijkstraFinderIDAStarFinderJumpPointFinder用法类似只需替换AStarFinder即可。
在React里使用// 导入 React 和 useState 钩子importReact,{useState}fromreact;// 导入路径寻找库importPFfrompathfinding;// 定义路径寻找应用组件constPathFindingApp(){// 初始化状态网格、路径、起点和终点const[grid,setGrid]useState(newPF.Grid(10,
);// 创建 10x10 的网格console.log(grid)const[path,setPath]useState([]);// 存储找到的路径const[start,setStart]useState([0,0]);// 起点坐标const[end,setEnd]useState([9,9]);// 终点坐标// 切换网格单元的可行走状态consttoggleWalkable(x,y){constnewGridgrid.clone();// 克隆当前网格newGrid.setWalkableAt(x,y,!newGrid.isWalkableAt(x,y));// 切换可行走状态setGrid(newGrid);// 更新网格状态};// 寻找路径的函数constfindPath(){constfindernewPF.AStarFinder();// 创建 A* 寻路算法实例constnewGridgrid.clone();// 克隆当前网格constnewPathfinder.findPath(start[0],start[1],end[0],end[1],newGrid);// 寻找路径setPath(newPath);// 更新路径状态};return(div{/* h1PathFinding.js in React/h1 */}div style{/* 渲染网格 */}{[...Array(
].map((_,y)[...Array(
].map((_,x){constisWalkablegrid.isWalkableAt(x,y);// 判断当前单元是否可行走constisPathpath.some(([px,py])pxxpyy);// 判断当前单元是否在路径上constisStartxstart[0]ystart[1];// 判断当前单元是否为起点constisEndxend[0]yend[1];// 判断当前单元是否为终点return(div key{${x}-${y}}onClick{()toggleWalkable(x,y)}// 点击切换可行走状态style/);}))}/divbutton onClick{findPath}Find Path/button{/* 寻找路径按钮 */}/div);};// 导出组件exportdefaultPathFindingApp;结合代码注释和前面的 API 讲解应该看得懂我上面写的这份代码。
用了 100 个 div 创建了一个网格地图绿色点是起点红色点是终点黑点是不可走的地方黄线是最终规划出来的录像。
但在实际项目中我们不可能用那么多个 div 元素来规划地图性能是很差的。
通常会在canvas里绘制地图。
下面是canvas版本的代码importReact,{useState,useRef,useEffect}fromreact;importPFfrompathfinding;// PathFindingApp 组件constPathFindingApp(){// 使用状态钩子管理网格、路径、起点和终点const[grid,setGrid]useState(newPF.Grid(10,
);// 创建一个 10x10 的网格const[path,setPath]useState([]);// 存储找到的路径const[start,setStart]useState([0,0]);// 起点坐标const[end,setEnd]useState([9,9]);// 终点坐标constcanvasRefuseRef(null);// 引用画布元素// 切换网格单元的可行走状态consttoggleWalkable(x,y){constnewGridgrid.clone();// 克隆当前网格newGrid.setWalkableAt(x,y,!newGrid.isWalkableAt(x,y));// 切换可行走状态setGrid(newGrid);// 更新网格状态};// 寻找路径constfindPath(){constfindernewPF.AStarFinder();// 创建 A* 寻路算法实例constnewGridgrid.clone();// 克隆当前网格constnewPathfinder.findPath(start[0],start[1],end[0],end[1],newGrid);// 寻找路径setPath(newPath);// 更新路径状态};// 绘制网格constdrawGrid(){constcanvascanvasRef.current;// 获取画布引用constcontextcanvas.getContext(2d);// 获取绘图上下文constcellSize30;// 单元格大小// 清空画布context.clearRect(0,0,canvas.width,canvas.height);// 绘制网格for(lety0;y10;y){for(letx0;x10;x){constisWalkablegrid.isWalkableAt(x,y);// 判断单元格是否可行走constisPathpath.some(([px,py])pxxpyy);// 判断单元格是否在路径上constisStartxstart[0]ystart[1];// 判断单元格是否为起点constisEndxend[0]yend[1];// 判断单元格是否为终点// 设置单元格颜色context.fillStyleisStart?green:isEnd?red:isPath?yellow:isWalkable?white:black;context.fillRect(x*cellSize,y*cellSize,cellSize,cellSize);// 绘制单元格context.strokeStylegray;// 设置边框颜色context.strokeRect(x*cellSize,y*cellSize,cellSize,cellSize);// 绘制单元格边框}}};// 使用 effect 钩子在网格或路径变化时重新绘制网格useEffect((){drawGrid();},[grid,path]);// 处理画布点击事件consthandleCanvasClick(e){constrectcanvasRef.current.getBoundingClientRect();// 获取画布位置constxMath.floor((e.clientX-rect.left)/
;// 计算点击的网格 x 坐标constyMath.floor((e.clientY-rect.top)/
;// 计算点击的网格 y 坐标toggleWalkable(x,y);// 切换网格的可行走状态};// 组件返回的 JSXreturn(divcanvas ref{canvasRef}width{300}height{300}onClick{handleCanvasClick}/button onClick{findPath}Find Path/button{/* 寻找路径按钮 */}/div);};exportdefaultPathFindingApp;// 导出组件PathFinding.js 可实现纯前端网格路径规划降低服务器压力还支持多种算法适配不同场景。
落地时要考虑性能优化与快速集成问题不妨看看RollCode 低代码平台的私有化部署、自定义组件、静态页面发布SSG SEO能力。
以上就是本文的全部内容啦如果本文对你有帮助的话记得点赞 关注 收藏