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

相关推荐
qq_3901617728 分钟前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test1 小时前
js下载excel示例demo
前端·javascript·excel
Yaml41 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事1 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro
哟哟耶耶1 小时前
js-将JavaScript对象或值转换为JSON字符串 JSON.stringify(this.SelectDataListCourse)
前端·javascript·json
getaxiosluo1 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v1 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
知孤云出岫1 小时前
web 渗透学习指南——初学者防入狱篇
前端·网络安全·渗透·web
贩卖纯净水.1 小时前
Chrome调试工具(查看CSS属性)
前端·chrome
栈老师不回家2 小时前
Vue 计算属性和监听器
前端·javascript·vue.js