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进阶边界检测学习结束,道阻且长,行则将至。与诸君共勉。 ⭐️

相关推荐
沐墨染1 小时前
敏感词智能检索前端组件设计:树形组织过滤与多维数据分析
前端·javascript·vue.js·ui·数据挖掘·数据分析
隐退山林1 小时前
JavaEE:多线程初阶(二)
java·开发语言·jvm
Kagol1 小时前
🎉TinyPro v1.4.0 正式发布:支持 Spring Boot、移动端适配、新增卡片列表和高级表单页面
前端·typescript·开源
乌暮1 小时前
JavaEE初阶---《JUC 并发编程完全指南:组件用法、原理剖析与面试应答》
java·开发语言·后端·学习·面试·java-ee
李少兄1 小时前
B/S 架构:现代 Web 应用的核心架构模式
前端·架构·b/s
为自己_带盐1 小时前
在 Blazor Server 中集成 docx-preview.js 实现高保真 Word 预览
javascript·c#·word
CCPC不拿奖不改名1 小时前
计算机网络:电脑访问网站的完整流程详解+面试习题
开发语言·python·学习·计算机网络·面试·职场和发展
wanderist.2 小时前
C++输入输出的一些问题
开发语言·c++·图论
PXM的算法星球2 小时前
用 semaphore 限制 Go 项目单机并发数的一次流量控制优化实践
开发语言·后端·golang
鹏程十八少2 小时前
破解Android悬浮窗遮挡无障碍服务难题:我在可见即可说上踩过的坑
android·前端·面试