canvas识别路线

视频说明

前言

效果一

技术栈

  • html
  • javascript
  • css
  • canvas

项目主要功能上传一张地图,或者迷宫地图,通过canvas的一系列操作,并指定一个起点和终点,并找到到达终点最近的路线

迷宫找出口效果

正文

加载图像

首先是加载图像,选择一张图,最好是底色是相同的 或者说底色的色差不是很大,你也可以在网上找一张迷宫的图片

javascript 复制代码
var imgObj = new Image();
imgObj.src = "../img/floor.jpg";

//待图片加载完后,将其显示在canvas上
imgObj.onload = function () {
    drawImg(this)
}

通过new Image构造一个图像,等价于document.createElement("img"),这张图在onload调用后会得到图片的尺寸,和具体的图像信息,创建实例为HTMLImageElement

这样我们就得到了一个图像,接下来就是将图像通过canvas分析,得到每个像素点的色值

获取色值信息

ini 复制代码
ImageData ctx.getImageData(sx, sy, sw, sh);

getImageData接受的参数一共4个,两个为一组,第一组是获取图片信息的起始点,一般都填写0,0,如果你的图像需要识别切边以后的数据,可以根据实际情况调整,第二组为识别区域的结束图标,通常为图像的宽度和高度。

这就是获取到的图像信息Uint8ClampedArray,由取值范围在0和255之间的无符号整数组成,其中包含了字节长度,和色值。在图像中每个像素用4个1bytes 值(按照红、绿、蓝和透明值的顺序;这就是"RGBA"格式)来代表。

顺序分别是图像的第一行第一个像素色值到第一行最后一个像素的色值,再从第二行第一个像素色值到最后一个像素的色值,这样Z字形排列,直到最后一行。

行和列的数量我们晓得了,就是图像的宽高,接下来就是遍历Uint8ClampedArray提供的字节信息,得到每一个像素点的色值

javascript 复制代码
for (let i = 0; i < (pixelData.length / limit); i++) {
        const r = pixelData[i * limit + 0]
        const g = pixelData[i * limit + 1]
        const b = pixelData[i * limit + 2]
        const diff = distance([r, g, b])
        const flag = diff <= colorDeff // 可通行标志
        col++
        if (i % accuracy === 0) {
            flagCol++
        }
        if (i % width === 0) { // 折行
            col = 0
            row++

            flagCol = 0
            if (i % accuracy === 0) {
                // flagCol++
                flagRow++ // 数据数组加一行
            }
        }

在此之前需要先知道几个常量和方法:

  1. distance用来计算两个颜色之间色差的方法,
  2. standardColor底色(视为可行走范围的颜色),
  3. colorDeff色差范围,像素颜色和规定底色色差小于这个值,则视为可行走范围,而超过这范围视作色差太大, 不符合可行走范围的色值;

在循环中,得到像素点的rgb,通过像素点上的色值,通过distance方法和standardColor对比色差,如果色差小于规定的色差值colorDeff,则被视为可行走路线

标记行走范围

typescript 复制代码
if (flag) {
    if (!runFlag[flagCol] && !runFlag[flagCol] !== 0) runFlag[flagCol] = [];
    if (!runFlag[flagCol][flagRow] && runFlag[flagCol][flagRow] !== 0) runFlag[flagCol][flagRow] = 1
                // drawRect(col, row)
} else {
    if (!runFlag[flagCol]) runFlag[flagCol] = [];
    if (!runFlag[flagCol][flagRow]) runFlag[flagCol][flagRow] = 0

}
if (!points[flagCol]) points[flagCol] = [];
if (!points[flagCol][flagRow]) {
    points[flagCol][flagRow] = {
        x: col, y: row
    }
}

当循环完毕,根据色值对比的flag判断当前像素是否为可通行状态(像素色值和底色色值小于等于色差范围);

当flag为true的时候runFlag数组添加一个为1的标记,如果为false则添加一个为0的标记, 通过计算得到runFlag二维数组数组,

drawRect(col, row, 2, 2, 'green')方法将可行走的位置在canvas上标记出来:

寻路

有了这些点位,在确定起点和终点的时候后,就可以执行寻路算法了,

首先假定起点为1和3 const start = [1, 3],终点为某处的随机点位

typescript 复制代码
const randomX =  getRandomInt(ex / 2, ex)
const randomY = getRandomInt(ey / 2, ey)

确定两个点位以后,执行astar算法

typescript 复制代码
if (runFlag) runPoints = astarCreate(start, end, runFlag)
console.log(runPoints);

寻路算法计算出的可行走路线

从这种图上可以看到,终点的随机位置为不可通过的点位,这时候可以设置astar的属性 { closest: true } 即可找到目标点位最近的可通过路线。

astar

关于astar的详细介绍可以翻阅历史文章 # Astar算法基础使用------寻路

历史文章

# threejs渲染高级感可视化涡轮模型

# 写一个高德地图巡航功能的小DEMO

# threejs 打造 world.ipanda.com 同款3D首页

源码git地址

canvas-astar

相关推荐
apcipot_rain1 小时前
【应用密码学】实验五 公钥密码2——ECC
前端·数据库·python
ShallowLin1 小时前
vue3学习——组合式 API:生命周期钩子
前端·javascript·vue.js
Nejosi_念旧2 小时前
Vue API 、element-plus自动导入插件
前端·javascript·vue.js
互联网搬砖老肖2 小时前
Web 架构之攻击应急方案
前端·架构
pixle02 小时前
Vue3 Echarts 3D饼图(3D环形图)实现讲解附带源码
前端·3d·echarts
麻芝汤圆3 小时前
MapReduce 入门实战:WordCount 程序
大数据·前端·javascript·ajax·spark·mapreduce
juruiyuan1115 小时前
FFmpeg3.4 libavcodec协议框架增加新的decode协议
前端
Peter 谭5 小时前
React Hooks 实现原理深度解析:从基础到源码级理解
前端·javascript·react.js·前端框架·ecmascript
LuckyLay6 小时前
React百日学习计划——Deepseek版
前端·学习·react.js
gxn_mmf7 小时前
典籍知识问答重新生成和消息修改Bug修改
前端·bug