<template>
<div @click="createBall($event)" class="box">
<canvas ref="canvas"></canvas>
</div>
</template>
<script>
export default {
mounted() {
// 获取画布
const canvas = this.$refs.canvas;
// 获取画布的 2D 上下文对象。
const ctx = canvas.getContext("2d");
// 存储生成的小球对象的数组。
const ballList = [];
const colorList = ["red", "green", "yellow", "blue", "black", "#ccc"];
// 创建小球对象的构造函数
// 设置了小球的初始位置、颜色、速度、透明度和半径。其中,透明度和半径都是随机生成的。
function Ball(x, y) {
this.x = x;
this.y = y;
this.color = colorList[Math.floor(this.mathRandom(0, 6))];
this.xv = this.mathRandom(-3, 3);
this.yv = this.mathRandom(-3, 3);
this.Alpha1 = 1;
this.Alpha2 = 0.95;
this.radius = this.mathRandom(5, 10); // 设置最小半径和最大半径
}
// 更新小球的绘制样式
Ball.prototype.update = function () {
ctx.save();
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
ctx.fill();
ctx.closePath();
};
// 更新小球的位置和透明度,并处理小球碰壁的情况。
Ball.prototype.move = function () {
this.Alpha1 *= this.Alpha2;
ctx.globalAlpha = this.Alpha1;
this.x += this.xv;
this.y += this.yv;
if (this.x < 0 || this.x > canvas.width) {
this.xv *= -1;
}
if (this.y < 0 || this.y > canvas.height) {
this.yv *= -1;
}
};
// 生成一个指定范围内的随机数
Ball.prototype.mathRandom = function (min, max) {
return (max - min) * Math.random() + min;
};
// 执行动画的函数,清空画布、更新小球位置和绘制小球。
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ballList.forEach((item) => {
item.update();
item.move();
});
requestAnimationFrame(animate);
}
// 设置画布的宽度和高度为窗口的宽度和高度,并调用 animate() 函数开始动画。
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
animate();
// 在点击事件中生成小球。获取鼠标点击的坐标,创建并添加多个小球对象到 ballList 数组中。
this.createBall = function (event) {
const x = event.clientX;
const y = event.clientY;
for (let i = 0; i < 10; i++) {
ballList.push(new Ball(x, y));
}
};
// 监听窗口大小变化事件,调整画布的宽度和高度。
window.addEventListener("resize", () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
},
};
</script>
<style>
.box
{
width: 100%;
height: 100%;
margin: 0;
overflow: hidden;
}
canvas {
position: absolute;
}
</style>
把小球换成正方形
function Ball(x, y) {
this.x = x
this.y = y
this.color = colorList[Math.floor(Math.random() * 6)]
this.xv = Math.random() * 6 - 3
this.yv = Math.random() * 6 - 3
this.Alpha1 = 1
this.Alpha2 = 0.95
this.sideLength = Math.random() * 6 + 5 // 正方形的边长
}
Ball.prototype.update = function () {
ctx.save()
ctx.fillStyle = this.color
ctx.fillRect(this.x, this.y, this.sideLength, this.sideLength)
}
换成心形
function Ball(x, y) {
this.x = x
this.y = y
this.color = colorList[Math.floor(Math.random() * 6)] // 随机选择小球的颜色
this.xv = Math.random() * 6 - 3 // 随机生成小球在 x 轴方向的速度
this.yv = Math.random() * 6 - 3 // 随机生成小球在 y 轴方向的速度
this.Alpha1 = 1
this.Alpha2 = 0.95
this.sideLength = Math.random() * 6 + 5 // 心形的尺寸大小
}
Ball.prototype.update = function () {
ctx.save()
ctx.fillStyle = this.color // 设置填充颜色为小球的颜色
// 根据小球的形状选择不同的绘制方式
// 这里使用了现成的心形路径来绘制心形
ctx.beginPath()
ctx.moveTo(this.x, this.y + this.sideLength / 2)
//bezierCurveTo 方法绘制两条贝塞尔曲线,用于定义心形的外轮廓。
ctx.bezierCurveTo(
this.x + this.sideLength / 4,
this.y - this.sideLength / 2,
this.x - this.sideLength,
this.y - this.sideLength / 4,
this.x,
this.y + this.sideLength
)
ctx.bezierCurveTo(
this.x + this.sideLength,
this.y - this.sideLength / 4,
this.x - this.sideLength / 4,
this.y - this.sideLength / 2,
this.x,
this.y + this.sideLength / 2
)
ctx.closePath() // 封闭路径
ctx.fill() // 填充心形
ctx.restore() // 恢复画布状态
}