在上篇实现基础上,实现仅能在画布区域内移动
const canvas = document.createElement('canvas')
canvas.width = 400
canvas.height = 400
canvas.id = 'canvas'
document.body.appendChild(canvas)
let ctx = canvas.getContext('2d') //画笔// 状态标志
const statusConfig = {IDLE: 0, //DRAGSTART: 1, //鼠标按下DRAGGING: 2 //托拽中
}
// 画布信息
const canvasInfo = {status: statusConfig.IDLE, //状态dragTarget: null, //拖拽对象lastEvtPos: { //前一位置x: null, y: null},offsetEvtPos: { //前一偏移x: null,y: null}
}let circles = [] //存储画的圆// 画圆
const drawCircle = (ctx, cx, cy, r) => {ctx.save()ctx.beginPath() //开始画ctx.arc(cx, cy, r, 0, Math.PI * 2)ctx.strokeStyle = 'pink'ctx.fillStyle = 'pink'ctx.stroke() //描边模式ctx.fill()ctx.closePath() //结束ctx.restore()
}drawCircle(ctx, 100, 100, 10)
// 存储圆的位置
circles.push({x: 100,y: 100,r: 10
})
drawCircle(ctx, 200, 150, 20)
circles.push({x: 200,y: 150,r: 20
})// 元素拖拽 鼠标的画布坐标
const getCanvasPostion = e => {return {x: e.offsetX, //鼠标在页面中的位置的同时减去canvas元素本身的偏移量y: e.offsetY,}
}// 两点之间的距离
const getInstance = (p1, p2) => {// 指数运算符 **,它们分别对 (p1.x - p2.x) 和 (p1.y - p2.y) 进行自乘。return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2)// Math.pow 函数,它用于计算指定数字的指定次方。// return Math.sqrt(Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2))
}// 判断是否在圆内
const ifInCirlce = (pos) => {for (let i = 0; i < circles.length; i++) {if (getInstance(circles[i], pos) < circles[i].r) {return circles[i]}}return false
}// 鼠标按下监听
canvas.addEventListener('mousedown', e => {const canvasPostion = getCanvasPostion(e)const circleRef = ifInCirlce(canvasPostion)if (circleRef) {console.log(circleRef);canvasInfo.dragTarget = circleRef //拖拽对象canvasInfo.status = statusConfig.DRAGSTARTcanvasInfo.lastEvtPos = canvasPostioncanvasInfo.offsetEvtPos = canvasPostion}
})// 鼠标移动
canvas.addEventListener('mousemove', e => {const canvasPostion = getCanvasPostion(e)const {dragTarget} = canvasInfoif (ifInCirlce(canvasPostion)) {canvas.style.cursor = 'all-scroll'}else {canvas.style.cursor = ''}if (!dragTarget) returnif (canvasInfo.status === statusConfig.DRAGSTART && getInstance(canvasPostion, canvasInfo.lastEvtPos) > 5) {console.log('try to drag');canvasInfo.status = statusConfig.DRAGGINGcanvasInfo.offsetEvtPos = canvasPostion}else if(canvasInfo.status === statusConfig.DRAGGING){console.log('draging');dragTarget.x += (canvasPostion.x - canvasInfo.offsetEvtPos.x)dragTarget.y += (canvasPostion.y - canvasInfo.offsetEvtPos.y) //基于偏移// 新增控制在区域内拖动代码----开始if (dragTarget.x - dragTarget.r < 0) {dragTarget.x = 0 + dragTarget.r}else if (dragTarget.x + dragTarget.r > canvas.width) {dragTarget.x = canvas.width - dragTarget.r}if (dragTarget.y - dragTarget.r < 0) {dragTarget.y = 0 + dragTarget.r}else if (dragTarget.y + dragTarget.r > canvas.height) {dragTarget.y = canvas.height - dragTarget.r}// 新增控制在区域内拖动代码----结束ctx.clearRect(0,0, canvas.width, canvas.height) //清空画布circles.forEach(c => drawCircle(ctx, c.x, c.y, c.r))canvasInfo.offsetEvtPos = canvasPostion}
})canvas.addEventListener('mouseup', e => {canvasInfo.status = statusConfig.IDLE
})canvas.addEventListener('mouseleave', e => {canvasInfo.status = statusConfig.IDLEcanvas.style.cursor = ''
})
canvas中实现画布内元素的拖拽(不可拖拽出画布区域)
至此,现现画布内元素的拖拽就完结了。