在画布上面画实心圆,然后沿8个方向移动,每个圆颜色随机,要做边界检测。如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>canvas</title>
<style>
#canvas {
border: 1px solid #f00;
background: #eee;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<button id="btn">run</button>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const btn = document.getElementById("btn");
const CANVAS_WIDTH = (canvas.width = 500);
const CANVAS_HEIGHT = (canvas.height = 500);
console.log("----CANVAS_WIDTH--: ", CANVAS_WIDTH);
console.log("----CANVAS_HEIGHT--: ", CANVAS_HEIGHT);
const ROOT_OF_TWO_OVER_TWO = Math.sqrt(2) / 2; // 根号2/2 约等于 0.707
// step 在各个方向上面移动的距离都应该是圆半径的倍数
const STEP = 10;
const DOT_RADIUS = 10;
// 上 上右 右 。。。
const DIRECTIONS = [1, 2, 3, 4, 5, 6, 7, 8];
const getRandomDirection = () => {
const index = Math.floor(Math.random() * DIRECTIONS.length);
return DIRECTIONS[index];
};
const getRandomColor = () => {
return `rgb(${Math.random() * 255}, ${Math.random() * 255}, ${
Math.random() * 255
})`;
};
class Dot {
#active = true;
constructor(x, y, r = DOT_RADIUS, color = "#f00") {
this.x = x;
this.y = y;
this.r = DOT_RADIUS;
}
move() {
const direction = getRandomDirection();
console.log("--this---move: ", this);
switch (direction) {
case 1:
// up
if (this.y - this.r <= 0) {
// return;
break;
}
this.y -= STEP;
break;
case 2:
if (
this.y - this.r <= 0 ||
this.x + this.r >= canvas.width
) {
// return;
break;
}
this.y -= STEP * ROOT_OF_TWO_OVER_TWO;
this.x += STEP * ROOT_OF_TWO_OVER_TWO;
break;
case 3:
//right
if (this.x + this.r >= canvas.width) {
// return;
break;
}
this.x += STEP;
break;
case 4:
if (
this.y + this.r >= CANVAS_HEIGHT ||
this.x + this.r >= canvas.width
) {
// return;
break;
}
this.x += STEP * ROOT_OF_TWO_OVER_TWO;
this.y += STEP * ROOT_OF_TWO_OVER_TWO;
break;
case 5:
// down
if (this.y + this.r >= CANVAS_HEIGHT) {
// return;
break;
}
this.y += STEP;
break;
case 6:
if (
this.y + this.r >= CANVAS_HEIGHT ||
this.x - this.r <= 0
) {
// return;
break;
}
this.y += STEP * ROOT_OF_TWO_OVER_TWO;
this.x -= STEP * ROOT_OF_TWO_OVER_TWO;
break;
case 7:
// left
if (this.x - this.r <= 0) {
// return;
break;
}
this.x -= STEP;
break;
case 8:
if (this.y - this.r <= 0 || this.x - this.r <= 0) {
// return;
break;
}
this.x -= STEP * ROOT_OF_TWO_OVER_TWO;
this.y -= STEP * ROOT_OF_TWO_OVER_TWO;
break;
default:
break;
}
// moveObj[direction]();
this.drawDot();
if (this.#active) {
requestAnimationFrame(this.move.bind(this));
}
}
drawDot() {
console.log("--ctx--drawDot: ", ctx);
console.log("--ctx--drawDot this: ", this);
ctx.fillStyle = getRandomColor();
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, false);
ctx.fill();
console.log("--ctx---end--drawDot: ");
}
}
const onClick = (e) => {
console.log(e);
const x = e.offsetX;
const y = e.offsetY;
// drawDot(x, y);
const dot = new Dot(x, y);
dot.move();
// ctx.fillStyle = getRandomColor();
// ctx.beginPath();
// ctx.arc(150, 100, 10, 0, Math.PI * 2, false);
// ctx.fill();
};
// btn.addEventListener("click", onClick);
canvas.addEventListener("click", onClick);
</script>
</body>
</html>
实际写完后注意到如下问题: 1 因为我做前端 5年多,也较少手写 canvas 的题目,所以没有一下子写出来。
2 画布的宽高应该用 js 设置,不能用css 设置
3 点击事件的坐标 offsetX offsetY 是相对点击元素的位置。
4 对 dom 元素的各种距离 screenX, screenY, pageX, pageY, left top right bottom , 以及 鼠标点击事件对象里面 的各种距离需要 回头做个总结,画个图