Canvas 鼠标移动炫彩小球

10次阅读
没有评论

简介

一个使用 HTML5 Canvas 实现的轻量级粒子特效:当鼠标在画布上移动时,会生成带有随机颜色与方向的小球,随后小球逐渐缩小并消失,形成绚丽的拖尾效果。纯原生 JavaScript,无任何第三方依赖,适合作为入门 Canvas 动画 / 粒子系统的示例代码。

演示页面

Canvas 鼠标移动炫彩小球

功能特性

  • 随机色彩:每个小球创建时都会赋予随机 RGB 颜色。
  • 轻量无依赖:仅一个 index.html 文件,开箱即用。
  • 动画更新:小球具有随机速度与衰减(半径逐帧减小)。
  • 可拓展性强:易于调整大小、速度、刷新频率等参数。

目录结构

index.html   # Demo 页面与核心脚本(内联)

快速开始

你可以直接双击打开,或通过本地静态服务器访问(推荐)。

  • 方式一:直接打开

    • 双击 index.html,用浏览器打开即可预览。
  • 方式二:使用 Python 简易服务器(macOS 已内置 Python3)

    # 在项目目录下运行
    python3 -m http.server 8080
    # 浏览器访问
    open http://localhost:8080/index.html
  • 方式三:使用 Node http-server(需已安装 Node.js)

    # 全局安装一次(如未安装)npm install -g http-server
    # 在项目目录下启动
    yarn global add http-server  # 若你使用 yarn,也可用此命令
    http-server -p 8080
    open http://localhost:8080/index.html

运行说明

  • 打开页面后,将鼠标在画布上移动即可产生彩色小球。
  • 画布大小默认 1000x600,带有 1px 边框(便于观察)。

关键实现与可调整项

以下参数均可在 index.html<script> 中调整:

  • 画布尺寸:
    • 通过 <canvas id="mycanvas" width="1000" height="600"></canvas> 控制。
  • 初始半径:
    • onmousemove 中创建小球:new Circle(event.clientX, event.clientY, 30, "orange"),将 30 改为需要的初始半径。
  • 随机颜色:
    • 构造函数内:this.color = "rgb(" + randR + "," + randG + ",203)",可替换固定的 203 或改为完全随机。
  • 速度范围:
    • this.dx = Math.random() * 12 - 7;
    • this.dy = Math.random() * 12 - 7;
    • 调整常量可改变速度区间与方向分布。
  • 衰减速度:
    • this.r--; 每帧半径减 1,可改为 this.r -= 0.5 等更平滑的衰减。
  • 刷新间隔:
    • setInterval(..., 20) 控制帧间隔,建议替换为 requestAnimationFrame 以获得更平滑的动画。

注意事项与小贴士

  • 坐标系:当前使用 event.clientX / clientY,为相对视口坐标。如果画布不在页面左上角 (0,0),可改为:
    const rect = mycanvas.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;
    new Circle(x, y, 30, "orange");
  • 性能建议:
    • 高频移动会创建很多粒子,可考虑:
      • 限制 circleArr 最大长度;
      • 使用 requestAnimationFrame 替代 setInterval
      • 降低初始半径或减小生成频率。
  • 移动端支持:
    • 可监听 touchmove 事件以支持触摸:canvas.ontouchmove = (e) => {...}

兼容性

  • 现代浏览器均支持 Canvas 2D API。建议使用最新版本的 Chrome / Edge / Safari 进行预览。

可能的改进方向

  • 使用 requestAnimationFrame 实现更平滑的渲染循环。
  • 将脚本拆分为独立文件并模块化(ES Modules)。
  • 引入粒子池(对象复用)优化 GC 压力。
  • 支持透明背景、混合模式、更多形状 / 渐变 / 尾迹。
  • 封装为可复用的类 / 组件,支持参数化初始化。

源码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">

<title>Canvas_鼠标移动炫彩小球 </title>
    <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        img{border:0;}
        ol, ul ,li{list-style: none;}
        canvas{border: 1px solid #000;}
    </style>
</head>
<body>
    <canvas id="mycanvas" width="1000" height="600"></canvas>
    <script type="text/javascript">

        var mycanvas = document.getElementById("mycanvas");
        var ctx = mycanvas.getContext("2d");
        // 圆形类
         function Circle(x,y,r,color){
            this.x = x;
            this.y = y;
            this.r = r;
            // 颜色的取值范围
            this.color = "rgb("+ (parseInt(Math.random() * 240 ) + 9) + ","+ (parseInt(Math.random() * 220 )+18) +",203)";

            // 随机方向
            this.dx = Math.random() * 12 - 7;
            this.dy = Math.random() * 12 - 7;
            // 往数组中 push 自己
            circleArr.push(this);
         }

         // 渲染
         Circle.prototype.render = function(){
            // 新建一条路径
            ctx.beginPath();
            // 创建一个圆
            ctx.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
            // 设置样式颜色
            ctx.fillStyle = this.color;
            // 通过填充路径的内容区域生成实心的图形
            ctx.fill();}

         // 更新
         Circle.prototype.update = function(){
            this.x += this.dx;
            this.y += this.dy;
            this.r--;
            if(this.r < 0){for (var i = 0; i < circleArr.length; i++) {if (circleArr[i] === this) {circleArr.splice(i,1);
                    };
                }
                return false;
            }
            return true;
         }
         // 创建一个数组
         var circleArr = [];

         // 鼠标移动事件
         mycanvas.onmousemove = function(event){new Circle(event.clientX,event.clientY,30,"orange");
         }

         // 设置定时器每 20 毫秒更新和渲染
         setInterval(function(){ctx.clearRect(0, 0, 1000, 600)
            for (var i = 0; i < circleArr.length; i++) {circleArr[i].update() && circleArr[i].render();};
         },20);

    </script>
</body>
</html>

正文完
 0
评论(没有评论)