const shapes = [];
var animate
// 画布初始化
export const canvasInit = () => {
const cvs = document.querySelector('canvas');
const ctx = cvs.getContext('2d');
const w = 500, h = 300;
cvs.width = w * devicePixelRatio;
cvs.height = h * devicePixelRatio; // set canvas size
cvs.style.width = w + 'px'; // add width and height to the style attribute of the html element
cvs.style.height = h + 'px'; // add width and height to the style attribute of the html element
cvs.onmousedown = (e) => {
canvasDraw(ctx)
const rect = cvs.getBoundingClientRect(); // get the dimensions of the canvas element.
const clickX = e.clientX - rect.left; // get the x-coordinate of the mouse-click.
const clickY = e.clientY - rect.top; // get the y-coordinate of the mouse-click.
const shape = getShape(clickX, clickY)
if(shape){
const { startX, startY, endX, endY } = shape
window.onmousemove = (e) => {
const disX = e.clientX - rect.left - clickX
const disY = e.clientY - rect.top - clickY
// 禁止移动到边界
if(e.clientX - rect.left <= 0 || e.clientX - rect.left >= w || e.clientY - rect.top <= 0 || e.clientY - rect.top >= h) {
window.onmousemove = null; // stop the mouse-movement from triggering a callback function.
cancelAnimationFrame(animate)
}
shape.startX = startX + disX// set the startX value.
shape.endX = endX + disX
shape.startY = startY + disY
shape.endY = endY + disY
// shape.startX = (startX + disX) <= 0 ? 0 : (startX + disX) > w ? w: startX + disX; // set the startX value.
// shape.endX = (endX + disX) > w ? w: (endX + disX)
// shape.startY = (startY + disY) < 0? 0: (startY + disY)
// shape.endY = (endY + disY) > h? h: (endY + disY)
} // on mouse move event.
}else {
const shape = new Rectangle(ctx, 'blue', clickX, clickY); // create a rectangle with the specified color and dimensions and draw it.
shapes.push(shape)
window.onmousemove = (e) => {
shape.endX = e.clientX - rect.left; // get the x-coordinate of the mouse-click.
shape.endY = e.clientY - rect.top; // get the y-coordinate of the mouse-click.
}
}
window.onmouseup = (e) => {
console.log(shapes)
window.onmousemove = null; // stop the mouse-movement from triggering a callback function.
window.onmouseup = null; // stop the mouse-click from triggering a callback function.
cancelAnimationFrame(animate)
} // on mouse move, update the location of the shape.
}
}
// 绘制方法
const canvasDraw = (ctx) => {
animate = requestAnimationFrame(() => {
canvasDraw(ctx)
});
ctx.clearRect(0, 0, canvas.width, canvas.height); // clear the canvas before starting to draw the lines.
for (const s of shapes) {
s.draw(); // draw the lines of the shape.
}
}
// 获取当前鼠标点击到的图形
const getShape = (x, y) => {
for(let i = shapes.length-1; i>=0; i--){
const s = shapes[i]
if(s.isInside(x, y)){
return s
}
}
return null
}
// 绘制矩形实例
class Rectangle {
constructor(ctx, color, startX, startY){
this.ctx = ctx;
this.color = color;
this.startX = startX; // start x position of the rectangle
this.startY = startY; // start y position of the rectangle
this.endX = startX
this.endY = startY;
}
get minX(){
return Math.min(this.startX, this.endX)
}
get maxX(){ // get the minimum y position of the rectangle
return Math.max(this.startX, this.endX)
}
get minY(){
return Math.min(this.startY, this.endY)
}
get maxY(){ // get the minimum y position of the rectangle
return Math.max(this.startY, this.endY)
}
// 绘制矩形
draw(){
this.ctx.beginPath(); // start a new path
this.ctx.moveTo(this.minX * devicePixelRatio, this.minY * devicePixelRatio)
this.ctx.lineTo(this.maxX * devicePixelRatio, this.minY * devicePixelRatio) // draw a line from the max x point of the rectangle to max y point
this.ctx.lineTo(this.maxX * devicePixelRatio, this.maxY * devicePixelRatio) // draw a line
this.ctx.lineTo(this.minX * devicePixelRatio, this.maxY * devicePixelRatio) // draw a line from the min x point of the rectangle to max y point
this.ctx.lineTo(this.minX * devicePixelRatio, this.minY * devicePixelRatio); // close the path of the rectangle
this.ctx.fillStyle = this.color; // set fill style of the path to the color specified in the constructor and draw the path in the
this.ctx.fill(); // fill the path of the rectangle with the fill style specified in the constructor and draw the path in the ctx.
this.ctx.lineCaps = 'square'; // set line caps of the path to round and draw the path in the ctx.
this.ctx.strokeStyle = '#fff'; // set stroke style of the path to the color specified in the constructor and draw the path in the ctx.
this.ctx.lineWidth = 3 * devicePixelRatio
this.ctx.stroke() // stroke the path of the rectangle with the stroke style specified in the constructor and draw the path in the ctx.
}
// 判断鼠标点击区域是否在绘制图形内
isInside(x, y){
return x >=this.minX && x<=this.maxX && y>=this.minY && y<=this.maxY ;
}
}
export default Rectangle