canvas中实现画布内元素的拖拽(下)

在上篇实现基础上,实现仅能在画布区域内移动

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.DRAGSTART
    canvasInfo.lastEvtPos = canvasPostion
    canvasInfo.offsetEvtPos = canvasPostion
  }
})

// 鼠标移动
canvas.addEventListener('mousemove', e => {
  const canvasPostion = getCanvasPostion(e)
  const {dragTarget} = canvasInfo
  if (ifInCirlce(canvasPostion)) {
    canvas.style.cursor = 'all-scroll'
  }else {
    canvas.style.cursor = ''
  }
  if (!dragTarget) return
  if (canvasInfo.status === statusConfig.DRAGSTART && getInstance(canvasPostion, canvasInfo.lastEvtPos) > 5) {
    console.log('try to drag');
    canvasInfo.status = statusConfig.DRAGGING
    canvasInfo.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.IDLE
  canvas.style.cursor = ''
})


canvas中实现画布内元素的拖拽(不可拖拽出画布区域)

至此,现现画布内元素的拖拽就完结了。

你可能感兴趣的:(canvas,前端,javascript,canvas)