console
<!--
* @Author: Wushun
* @Date: 2023-08-15
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<canvas id="canvas" style="background-color: #94e8ea"></canvas>
</div>
</body>
<script>
// 获取canvas
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 所有绘制的图形推入数组中。
let shapeCollection = []
// 设置宽高
const w = 1200, h = 800;
canvas.width = w * devicePixelRatio;
canvas.height = h * devicePixelRatio;
class RectFactory {
/**
* @startX:鼠标 点击时 的坐标轴 X 值
* @startY:鼠标 点击时 的坐标轴 Y 值
* @endX:鼠标 抬起时 的坐标轴 X 值
* @endY:鼠标 抬起时 的坐标轴 Y 值
* */
constructor(startX, startY, endX, endY) {
this.startX = startX;
this.startY = startY;
this.endX = endX;
this.endY = endY;
}
// 为了保持不同的鼠标绘制方向都能绘制出图形,对坐标进行处理。
get minX() {
return Math.min(this.startX, this.endX);
}
get maxX() {
return Math.max(this.startX, this.endX);
}
get minY() {
return Math.min(this.startY, this.endY);
}
get maxY() {
return Math.max(this.startY, this.endY);
}
// 获取文本文字
get lableY() {
return this.minY + (this.maxY - this.minY) + 20
}
draw() {
ctx.beginPath();
ctx.moveTo(this.minX * devicePixelRatio, this.minY * devicePixelRatio);
ctx.lineTo(this.maxX * devicePixelRatio, this.minY * devicePixelRatio);
ctx.lineTo(this.maxX * devicePixelRatio, this.maxY * devicePixelRatio);
ctx.lineTo(this.minX * devicePixelRatio, this.maxY * devicePixelRatio);
ctx.lineTo(this.minX * devicePixelRatio, this.minY * devicePixelRatio);
ctx.fillStyle = '#ffb60f';
ctx.fill();
ctx.strokeStyle = '#fff';
ctx.lineCap = 'square';
ctx.lineWidth = 1 * devicePixelRatio;
ctx.stroke();
// ctx.beginPath()
ctx.font = "20px Arial";
ctx.fillText(`${this.minX}/${this.minY}/${this.maxX}/${this.maxY}`, this.minX, this.lableY);
}
// 判断当前点击位置是否在图形内部
isInside(x, y) {
return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY
}
}
canvas.onmousedown = (e) => {
const rect = canvas.getBoundingClientRect();
const clickX = e.clientX - rect.left;
const clickY = e.clientY - rect.top;
const shape = getRect(clickX, clickY)
if (shape) {
moveRect(e, clickX, clickY, rect, shape)
} else {
drawRect(e, clickX, clickY, rect)
}
}
canvas.onmouseup = () => {
canvas.onmousemove = null;
window.onmousemove = null;
};
// 鼠标点击canvas查看是否点击到了已经绘制的路线,若是,则返回相关线的对象,若否,返回null
const getRect = (x, y) => {
for (let i = shapeCollection.length - 1; i >= 0; i--) {
const element = shapeCollection[i];
if (element.isInside(x, y)) {
return element;
}
}
return null
}
// 绘制矩形
const drawRect = (e, clickX, clickY, rect) => {
const shape = new RectFactory(clickX, clickY)
shapeCollection.push(shape)
window.onmousemove = (evt) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
shape.endX = evt.clientX - rect.left;
shape.endY = evt.clientY - rect.top;
}
}
// 移动矩形
const moveRect = (e, clickX, clickY, rect, shape) => {
const { startX, startY, endX, endY } = shape;
window.onmousemove = (evt) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const distanceX = evt.clientX - rect.left - clickX;
const distanceY = evt.clientY - rect.top - clickY;
shape.startX = startX + distanceX;
shape.startY = startY + distanceY;
shape.endX = endX + distanceX;
shape.endY = endY + distanceY;
}
};
const draw = () => {
requestAnimationFrame(draw)
// console.log(shapeCollection,'9000')
for (const pp of shapeCollection) {
pp.draw()
}
}
draw()
</script>
</html>