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)  //基于偏移
    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中实现画布内元素的拖拽

下一篇将在此基础上实现,仅能在画布区域内移动。

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现画布动组件并保存,需要以下步骤: 1. 在画布上绘制组件,并给每个组件一个唯一的ID。 2. 给每个组件添加鼠标事件监听器,用于动组件。 3. 在动组件时,更新组件的位置信息,并重新绘制画布。 4. 将画布上所有组件的位置信息保存到数据库。 下面是一个简单的示例代码,使用 layui 和 canvas 实现画布动组件并保存。 HTML 代码: ```html <div class="canvas-container"> <canvas id="canvas"></canvas> </div> ``` CSS 代码: ```css .canvas-container { position: relative; width: 800px; height: 600px; border: 1px solid #ccc; } .canvas-container canvas { position: absolute; top: 0; left: 0; } ``` JavaScript 代码: ```javascript // 组件列表 var components = [ { id: 'component1', x: 100, y: 100, width: 100, height: 50, color: '#f00' }, { id: 'component2', x: 300, y: 200, width: 100, height: 50, color: '#0f0' }, { id: 'component3', x: 500, y: 300, width: 100, height: 50, color: '#00f' }, ]; // 初始化画布 var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); canvas.width = 800; canvas.height = 600; // 绘制组件 function drawComponent(component) { ctx.fillStyle = component.color; ctx.fillRect(component.x, component.y, component.width, component.height); } // 绘制所有组件 function drawAllComponents() { ctx.clearRect(0, 0, canvas.width, canvas.height); for (var i = 0; i < components.length; i++) { drawComponent(components[i]); } } // 找到当前鼠标位置下的组件 function findComponent(x, y) { for (var i = components.length - 1; i >= 0; i--) { var component = components[i]; if (x >= component.x && x <= component.x + component.width && y >= component.y && y <= component.y + component.height) { return component; } } return null; } // 动组件 var dragging = false; var dragComponent = null; var dragOffsetX = 0; var dragOffsetY = 0; canvas.addEventListener('mousedown', function(event) { var x = event.offsetX; var y = event.offsetY; dragComponent = findComponent(x, y); if (dragComponent) { dragging = true; dragOffsetX = x - dragComponent.x; dragOffsetY = y - dragComponent.y; } }); canvas.addEventListener('mousemove', function(event) { if (dragging) { var x = event.offsetX; var y = event.offsetY; dragComponent.x = x - dragOffsetX; dragComponent.y = y - dragOffsetY; drawAllComponents(); } }); canvas.addEventListener('mouseup', function(event) { dragging = false; }); // 保存组件位置 function saveComponentPosition() { // 将所有组件的位置信息保存到数据库 } // 页面加载完成后绘制所有组件 layui.use('form', function() { drawAllComponents(); }); ``` 在这个示例,我们使用了一个 components 数组来存储所有组件的信息,包括组件的位置、大小和颜色等。在页面加载完成后,我们会调用 drawAllComponents() 函数来绘制所有组件,并给每个组件添加鼠标事件监听器来实现动功能。当用户动某个组件时,我们会更新该组件的位置信息,并重新绘制画布。最后,我们可以调用 saveComponentPosition() 函数将所有组件的位置信息保存到数据库

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值