canvas如何实现鼠标绘制图形以及拖拽
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