简介
实现功能,在画布上绘制矩形,移动矩形。
在线演示
绘制矩形
实现代码
<!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.devicePixelRatio
cvs.height=h*window.devicePixelRatio
cvs.style.width=w+'px'
cvs.style.height=h+'px'
}
//存储图形数组
const shapes = []
//矩形类
class Rectangle{
constructor(color,startX,startY){
//矩形颜色
this.color = color
//矩形起始坐标
this.startX = startX
this.startY = startY
//矩形结束坐标
this.endX = startX
this.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.color
ctx.fill()
ctx.strokeStyle='#fff'
ctx.lineGap='square'
ctx.lineWidth=3*window.devicePixelRatio
ctx.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.offsetX
const mouseY=e.offsetY
window.onmousemove=(e)=>{
const disX=e.clientX-bouding.left-mouseX
const disY=e.clientY-bouding.top-mouseY
shape.startX=startX+disX
shape.startY=startY+disY
shape.endX=endX+disX
shape.endY=endY+disY
}
}else{
//新增绘制矩形
shapes.push(rect)
window.onmousemove=(e)=>{
rect.endX=e.clientX-bouding.left
rect.endY=e.clientY-bouding.top
}
}
window.onmouseup=()=>{
window.onmousemove=null
window.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>