Canvas进阶-4、边界检测(流光,鼠标拖尾)

1. 什么是边界检测?

在之前的开发中,物体在运动过程中一旦超出画布,就会消失,今天学习如何去检测是否碰到了边界,碰到边界后又会有哪些处理的办法。

边界检测,就是物体运动的限制范围。边界检测的范围,既可以是画布的某个区域,也可以是整个画布。

下面是一个代码示例:


html 复制代码
 <canvas id="myCanvas"></canvas>
js 复制代码
 init() {
      //定义一个球
      class Ball {
        constructor(x, y) {
          this.x = x
          this.y = y
          this.radius = 10 //球的半径
          this.color = 'red' 
        }
        fill(context) {
          context.beginPath()
          context.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
          context.fillStyle = this.color
          context.fill()
          context.closePath()
        }
      }
      const cnv = document.getElementById('myCanvas')
      const cxt = cnv.getContext('2d')
      // 初始化一个小球
      const ball = new Ball(0, cnv.height / 2)
      const vx = 2

      ;(function frame() {
        window.requestAnimationFrame(frame)
        //绘制前一定要重置
        cxt.clearRect(0, 0, cnv.width, cnv.height)
        ball.x += vx
       
        if (ball.x > cnv.width + ball.radius) {
          // 完全超出右边界
          ball.x = -ball.radius
        }
        ball.fill(cxt)
      })()
    },

看图理解边界限制,什么是边界?

js 复制代码
        if (ball.x < ball.radius) {
          //半径大于圆心绘制点
          console.log('小球碰到了左边界')
        } else if (ball.x > cnv.width - ball.raduis) {
          //圆心绘制点大于canvas-半径(球的圆边)
          console.log('小球碰到了右边界')
        }
        if (ball.y < ball.radius) {
          console.log('小球碰到了上边界')
        } else if (ball.y > cnv.height - ball.raduis) {
          console.log('小球碰到了下边界')
        }
        if (ball.x < -ball.radius) {
          console.log('完全超出左边界')
        } else if (ball.x > cnv.width + ball.radius) {
          console.log('完全超出右边界')
        }

        if (ball.y < -ball.radius) {
          console.log('完全超出上边界')
        } else if (ball.y > cnv.height + ball.radius) {
          console.log('完全超出下边界')
        }

2.如何利用边界?进阶应用

上图为超出边界线消失,下图只要我们稍稍调整,就成为一个简单的鼠标拖尾,就是如此简单

js 复制代码
 init1() {
      class Ball {
        constructor(x, y, color, radius) {
          this.x = x
          this.y = y
          this.radius = radius
          this.color = color
          this.vx = Math.random() * 3 - 1 // 添加随机速度
          this.vy = Math.random() * 3 - 1
          this.opacity = 1
          this.lifeTime = 400 // 添加生命周期属性(毫秒)
          this.birthTime = Date.now() // 记录小球创建的时间
        }
        fill(context) {
          context.save()
          context.globalAlpha = this.opacity
          context.beginPath()
          context.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
          context.fillStyle = this.color
          context.fill()
          context.closePath()
          context.restore()
        }
      }

      function getMouse(element) {
        let mouse = { x: 0, y: 0 }
        element.addEventListener('mousemove', e => {
          mouse.x = e.clientX - element.getBoundingClientRect().left // 使用clientX和getBoundingClientRect计算鼠标位置
          mouse.y = e.clientY - element.getBoundingClientRect().top
        })
        return mouse
      }

      var cnv = document.getElementById('myCanvas1')
      var ctx = cnv.getContext('2d')
      var mouse = getMouse(cnv)

      const getRandomColor = () => {
        return '#' + Math.floor(Math.random() * 16777215).toString(16)
      }

      let balls = []

      cnv.addEventListener('mousemove', () => {
        // 生成新小球
        const ball = new Ball(mouse.x, mouse.y, getRandomColor(), 2)
        balls.push(ball)
      })

      function frame() {
        window.requestAnimationFrame(frame)
        ctx.clearRect(0, 0, cnv.width, cnv.height)
        balls.forEach((ball, index) => {
          const remainingLifeTime = ball.lifeTime - (Date.now() - ball.birthTime)
          if (remainingLifeTime <= 0) {
            balls.splice(index, 1)
          } else {
            // 否则,根据剩余生命周期计算透明度
            ball.opacity = remainingLifeTime / ball.lifeTime
            ball.fill(ctx)
            ball.x += ball.vx
            ball.y += ball.vy
          }
        })
      }

      frame()
    }

到此canvas进阶边界检测学习结束,道阻且长,行则将至。与诸君共勉。 ⭐️

相关推荐
2501_944525542 分钟前
Flutter for OpenHarmony 个人理财管理App实战 - 支出分析页面
android·开发语言·前端·javascript·flutter
qq_4171292515 分钟前
C++中的桥接模式变体
开发语言·c++·算法
开源技术28 分钟前
如何将本地LLM模型与Ollama和Python集成
开发语言·python
Hello World . .33 分钟前
数据结构:队列
c语言·开发语言·数据结构·vim
jin12332240 分钟前
React Native鸿蒙跨平台完成剧本杀组队详情页面,可以复用桌游、团建、赛事等各类组队详情页开发
javascript·react native·react.js·ecmascript·harmonyos
李白你好42 分钟前
Burp Suite插件用于自动检测Web应用程序中的未授权访问漏洞
前端
clever1011 小时前
在QtCreator 4.10.2中调试qt程序qDebug()输出中文为乱码问题的解决
开发语言·qt
测试开发Kevin1 小时前
小tip:换行符CRLF 和 LF 的区别以及二者在实际项目中的影响
java·开发语言·python
经年未远2 小时前
vue3中实现耳机和扬声器切换方案
javascript·学习·vue
松☆2 小时前
Dart 核心语法精讲:从空安全到流程控制(3)
android·java·开发语言