canvas 視覺化操作-拖拽&縮放&移動
阿新 • • 發佈:2021-11-22
canvas拖拽的實現
/* canvas 視覺化操作-拖拽&縮放&移動 */ const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const stautsConfig = { //拖拽開始 IDLE: 0, //拖拽中 DRAG_START: 1, //拖拽結束 DRAGGING: 2 } //畫布資訊 const canvasInfo = { status: stautsConfig.IDLE, //拖拽狀態 dragTarget: null, //拖拽物件 lastEvtPos: { x: null, y: null }, //計算偏移量座標 offsetEvtPos: { x: null, y: null } //偏移事件位置 } const cirlces = [];//畫布圓的資訊 //畫圓 const drawCircle = (ctx, cx, cy, r) => { ctx.save(); ctx.beginPath(); ctx.strokeStyle = 'blue'; ctx.arc(cx, cy, r, 0, Math.PI*2); ctx.stroke(); ctx.closePath(); ctx.restore(); } //檢視層繪製 drawCircle(ctx, 100, 100, 20); //資料層記錄 cirlces.push({ x: 100, y: 100, r: 20 }) drawCircle(ctx, 200, 200, 30); cirlces.push({ x: 200, y: 200, r: 30 }) /*————————————————拖拽———————————————————*/ //畫布位置 const getCanvasPosition = e => { return { x: e.offsetX, y: e.offsetY } } //獲取距離 const getDistance = (p1, p2) => { return Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2); } //判斷是否在圓內 const ifInCirlce = (pos) => { for (let i = 0; i < cirlces.length; i++) { //如果兩個距離小於半徑就返回 if (getDistance(cirlces[i], pos) < cirlces[i].r) { return cirlces[i] } } return false; } //滑鼠按下 canvas.addEventListener('mousedown', e => { const canvasPosition = getCanvasPosition(e); const cirlceRef = ifInCirlce(canvasPosition); //如果拖拽物件條件成立,系統進入拖拽狀態 if (cirlceRef) { //記錄拖拽目標、狀態、偏移量位置、偏移事件位置 canvasInfo.dragTarget = cirlceRef; canvasInfo.status = stautsConfig.DRAG_START; canvasInfo.lastEvtPos = canvasPosition; canvasInfo.offsetEvtPos = canvasPosition; } }) //滑鼠移動 canvas.addEventListener('mousemove', e => { const canvasPosition = getCanvasPosition(e); //如果在某個圓內,修改拖動中的滑鼠樣式 if (ifInCirlce(canvasPosition)) { canvas.style.cursor = 'all-scroll'; } else { canvas.style.cursor = '' } //如果第一次距離和第二次之間大於5,代表真正的拖動(防止抖動,一按下就移動的問題) if (canvasInfo.status === stautsConfig.DRAG_START && getDistance(canvasPosition, canvasInfo.lastEvtPos) > 5) { console.log('try'); canvasInfo.status = stautsConfig.DRAGGING; //更新偏移事件位置 canvasInfo.offsetEvtPos = canvasPosition; } else if (canvasInfo.status === stautsConfig.DRAGGING){ console.log('拖拽中'); const { dragTarget } = canvasInfo; dragTarget.x += (canvasPosition.x - canvasInfo.offsetEvtPos.x); dragTarget.y += (canvasPosition.y - canvasInfo.offsetEvtPos.y); //拖拽時候清空並重繪圓圈 ctx.clearRect(0, 0, canvas.width, canvas.height); cirlces.forEach(item => drawCircle(ctx, item.x, item.y, item.r)); canvasInfo.offsetEvtPos = canvasPosition; } }) //滑鼠抬起 canvas.addEventListener('mouseup', e => { if (canvasInfo.status === stautsConfig.DRAGGING) canvasInfo.status = stautsConfig.IDLE; })