马黑黑 发表于 2022-8-25 13:43

canvas画布中的元素响应鼠标交互

canvas画布中可以拥有很多绘制的元素,掌握这些元素响应鼠标的动作交互很有意义,是画布深入开发的必备基础。

本帖以画布中的矩形为例,初探画布上的元素响应鼠标动作交互的实现机制,意在举一反三。矩形是最简单的,尤其是在判断指针是否经过它时。

预想是,画布上绘制的小矩形图像,能够发现鼠标经过它,并作出响应动作。响应方式我们尽量简化:鼠标指针变为手型、自身颜色发生变化。

准备工作:在页面上布局画布。CSS和HTML代码如下:

<style>
        #canv { margin: auto; display: block; position: relative; border: 1px solid; }
</style>

<canvas id="canv"></canvas>


开始用JS脚本去实现预设功能。先声明相关变量:

let ctx = canv.getContext('2d'), //画笔
        w = canv.width = 740, //画布宽度
        h = canv.height = 460, //画布高度
        box = { x: 10, y: 10, width: 60, height: 40, color: 'olive' }; //矩形实体化对象


给 box 对象添加一个绘制函数,方便反复调用:

box.draw = function() {
        ctx.fillStyle = this.color; //填充颜色
        ctx.fillRect(this.x, this.y, this.width, this.height); //画矩形
}


然后运行一次上述函数(也可以稍后一点再运行),让矩形在打开页面时在画布上出现:

box.draw();

接着是重点问题,写一个函数判断鼠标在画布上移动时是否经过上述矩形,函数依然属于 box 对象的一个方法:

box.isBox = function(x,y) {
        return (this.x <= x && this.x + this.width >= x && this.y <= y && this.y + this.height >= y);
}


上面的函数需要两个参数,x和y,这两个参数指向鼠标指针移动时的实时xy坐标值,然后拿这个坐标值分别与矩形的xy坐标以及xy坐标+宽、高的和进行比较,返回如下的比较结果:矩形的X坐标值小于等于x、并且矩形的X坐标值+其宽度大于等于x、并且矩形的Y坐标小于等于y、并且矩形的Y坐标值+其高度等于等于y。这个比较结果如果一齐成立,则鼠标指针在矩形范围里,否则不是。

最后编写监听画布上鼠标移动的函数,它将调用上面的判断鼠标指针是否在矩形之上的函数:

canv.addEventListener('mousemove', function(e) {
        let ex = e.offsetX, ey = e.offsetY; //获取鼠标xy坐标并赋值给变量 ex、ey
        if (box.isBox(ex,ey)) { //调用判断函数,如果函数返回真,则——
                this.style.cursor = 'pointer'; //鼠标指针为手型
                box.color = 'red'; //矩形填充色为红色
                box.draw(); //重新绘制矩形
       } else { //否则——
               this.style.cursor = 'default'; //鼠标指针为默认
               box.color = 'olive'; //颜色回到初始色
               box.draw(); //重新绘制矩形
       }
});


这是监听整个画布的鼠标移动事件,或许我们需要一个处理机制,以避免过渡的矩形重绘,作为初探,这里就不整那么复杂的了。

实现了上述响应功能,可扩展的机会也就有了,画布上基于响应机制的更为丰富的功能也就有了实现的可能。

马黑黑 发表于 2022-8-25 13:45

<style>
        #canv { margin: auto; display: block; position: relative; border: 1px solid; }
</style>

<canvas id="canv"></canvas>

<script>

let ctx = canv.getContext('2d'),
        w = canv.width = 740,
        h = canv.height = 460,
        box = { x: 10, y: 10, width: 60, height: 40, color: 'olive' };

box.draw = function() {
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.width, this.height);
}

box.draw();

box.isBox = function(x,y) {
        return (this.x <= x && this.x + this.width >= x && this.y <= y && this.y + this.height >= y);
}

canv.addEventListener('mousemove', function(e) {
        let ex = e.offsetX, ey = e.offsetY;
        if (box.isBox(ex,ey)) {
                this.style.cursor = 'pointer';
                box.color = 'red';
                box.draw();
       } else {
               this.style.cursor = 'default';
               box.color = 'olive';
               box.draw();
       }
});

</script>

马黑黑 发表于 2022-8-25 13:45

二楼代码:
<style>
        #canv { margin: auto; display: block; position: relative; border: 1px solid; }
</style>

<canvas id="canv"></canvas>

<script>

let ctx = canv.getContext('2d'),
        w = canv.width = 740,
        h = canv.height = 460,
        box = { x: 10, y: 10, width: 60, height: 40, color: 'olive' };

box.draw = function() {
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.width, this.height);
}

box.draw();

box.isBox = function(x,y) {
        return (this.x <= x && this.x + this.width >= x && this.y <= y && this.y + this.height >= y);
}

canv.addEventListener('mousemove', function(e) {
        let ex = e.offsetX, ey = e.offsetY;
        if (box.isBox(ex,ey)) {
                this.style.cursor = 'pointer';
                box.color = 'red';
                box.draw();
       } else {
               this.style.cursor = 'default';
               box.color = 'olive';
               box.draw();
       }
});

</script>


红影 发表于 2022-8-25 14:18

这个主要还是那句判断鼠标是否在矩形区域内,通过4个条件的满足,可以知道鼠标是否在,并根据结果,做相应操作。学习了{:4_187:}

红影 发表于 2022-8-25 14:18

这个反应还是挺快的呢,鼠标上去就看到变化发生{:4_173:}

小辣椒 发表于 2022-8-25 15:08

看看黑黑的文字说明似乎懂了,但实际操作肯定不行,感觉必须有系统性学习和实践相结合,小辣椒就等黑黑的教程分享吧{:4_189:}

马黑黑 发表于 2022-8-25 19:01

小辣椒 发表于 2022-8-25 15:08
看看黑黑的文字说明似乎懂了,但实际操作肯定不行,感觉必须有系统性学习和实践相结合,小辣椒就等黑黑的教 ...

这个就是教程

马黑黑 发表于 2022-8-25 19:24

红影 发表于 2022-8-25 14:18
这个主要还是那句判断鼠标是否在矩形区域内,通过4个条件的满足,可以知道鼠标是否在,并根据结果,做相应 ...

理解到位

马黑黑 发表于 2022-8-25 19:25

红影 发表于 2022-8-25 14:18
这个反应还是挺快的呢,鼠标上去就看到变化发生

它和元素的鼠标相似事件的反应能力是一样的

红影 发表于 2022-8-25 21:04

马黑黑 发表于 2022-8-25 19:24
理解到位

计算机的判断真是快呢。

红影 发表于 2022-8-25 21:04

马黑黑 发表于 2022-8-25 19:25
它和元素的鼠标相似事件的反应能力是一样的

是的,非常快。

马黑黑 发表于 2022-8-25 22:19

红影 发表于 2022-8-25 21:04
是的,非常快。

属于正常范围

马黑黑 发表于 2022-8-25 22:19

红影 发表于 2022-8-25 21:04
计算机的判断真是快呢。

瞬间

加林森 发表于 2022-8-26 09:09

来学习!

红影 发表于 2022-8-26 19:38

马黑黑 发表于 2022-8-25 22:19
属于正常范围

比人的反应快许多。

红影 发表于 2022-8-26 19:39

马黑黑 发表于 2022-8-25 22:19
瞬间

是啊,那些前一步的判断和后一步的变化,都是瞬间就完成了。

马黑黑 发表于 2022-8-26 20:15

红影 发表于 2022-8-26 19:39
是啊,那些前一步的判断和后一步的变化,都是瞬间就完成了。

这就是计算机,它只计算,没有情绪

马黑黑 发表于 2022-8-26 20:15

红影 发表于 2022-8-26 19:38
比人的反应快许多。

人不能与之相比

红影 发表于 2022-8-27 19:26

马黑黑 发表于 2022-8-26 20:15
这就是计算机,它只计算,没有情绪

而且永不疲倦,也不抱怨{:4_173:}

红影 发表于 2022-8-27 19:28

马黑黑 发表于 2022-8-26 20:15
人不能与之相比

人的大脑逻辑判断可能不如计算机,但生物神经传递比计算机还快,被烫的瞬间我们就会缩手,要让计算机去操控设备动作,肯定没这个快。
页: [1] 2 3
查看完整版本: canvas画布中的元素响应鼠标交互