简介
实现功能,在画布上绘制矩形,移动矩形。
在线演示
绘制矩形
实现代码
<!DOCTYPE html><html><head>
<title>绘制矩形</title>
</head><body><div style="margin: 10px"><input type="color" />
</div><div style="background: #ccc;margin: 10px"><canvas></canvas>
</div><script>//获取调色板const colorPicker=document.querySelector('input')//获取画布const cvs=document.querySelector('canvas')//获取画布上下文const ctx=cvs.getContext('2d')init()//初始化画布function init(){const w = window.innerWidth-50,h=window.innerHeight-80//dpr保证高清屏绘制的清晰度cvs.width=w*window.devicePixelRatiocvs.height=h*window.devicePixelRatiocvs.style.width=w+'px'cvs.style.height=h+'px'}//存储图形数组const shapes = []//矩形类class Rectangle{constructor(color,startX,startY){//矩形颜色this.color = color//矩形起始坐标this.startX = startXthis.startY = startY//矩形结束坐标this.endX = startXthis.endY = startY}//get为访问器属性//矩形左上角坐标get minX(){return Math.min(this.startX,this.endX)}get minY(){return Math.min(this.startY,this.endY)}//矩形右下角坐标get maxX(){return Math.max(this.startX,this.endX)}get maxY(){return Math.max(this.startY,this.endY)}//绘制矩形draw(){//开启路径ctx.beginPath()//移动到左上角ctx.moveTo(this.minX*window.devicePixelRatio,this.minY*window.devicePixelRatio)//绘制直线到左上角ctx.lineTo(this.minX*window.devicePixelRatio,this.minY*window.devicePixelRatio)//绘制直线到右上角ctx.lineTo(this.maxX*window.devicePixelRatio,this.minY*window.devicePixelRatio)//绘制直线到右下角ctx.lineTo(this.maxX*window.devicePixelRatio,this.maxY*window.devicePixelRatio)//绘制直线到左下角ctx.lineTo(this.minX*window.devicePixelRatio,this.maxY*window.devicePixelRatio)//绘制直线到左上角ctx.lineTo(this.minX*window.devicePixelRatio,this.minY*window.devicePixelRatio)ctx.save()//设置填充颜色ctx.fillStyle=this.colorctx.fill()ctx.strokeStyle='#fff'ctx.lineGap='square'ctx.lineWidth=3*window.devicePixelRatioctx.stroke()ctx.restore()}}cvs.onmousedown = (e)=>{//画布左上角坐标const bouding = cvs.getBoundingClientRect()const rect=new Rectangle(colorPicker.value,e.offsetX,e.offsetY)const shape=getShape(e.offsetX,e.offsetY)if(shape){//拖动const {startX,startY,endX,endY}=shape//鼠标的坐标const mouseX=e.offsetXconst mouseY=e.offsetYwindow.onmousemove=(e)=>{const disX=e.clientX-bouding.left-mouseXconst disY=e.clientY-bouding.top-mouseYshape.startX=startX+disXshape.startY=startY+disYshape.endX=endX+disXshape.endY=endY+disY}}else{//新增绘制矩形shapes.push(rect)window.onmousemove=(e)=>{rect.endX=e.clientX-bouding.leftrect.endY=e.clientY-bouding.top}}window.onmouseup=()=>{window.onmousemove=nullwindow.onmouseup=null}}function getShape(x,y){//画布的绘制顺序倒着来循环,for(let i=shapes.length-1;i>=0;i--){if(x>=shapes[i].minX&&x<=shapes[i].maxX&&y>=shapes[i].minY&&y<=shapes[i].maxY){return shapes[i]}}
}function draw(){//每一帧注册绘制方法requestAnimationFrame(draw)//清空画布ctx.clearRect(0,0,cvs.width,cvs.height)for(const shape of shapes){shape.draw()}}draw()function emptyCanvas(){shapes = []
}
function undo(){shapes.pop()
}</script></body></html>