html canvas 繪圖實現可拖拽矩形發(fā)生偏移
問題描述
前端在采樣canvas 繪制,可拖動矩形時,產生了一個bug,檢查了很久找不到原因,請求大佬們解惑;
bug 演示
當圖中有兩個可拖動塊時,拖動一個,另外一個 會發(fā)生小許的偏移
完整代碼
<!DOCTYPE?html> <html> <head> ????<meta?charset="UTF-8"> ????<title>繪制</title> </head> <body> <div?style="display:?flex"> ????<div?style="width:?200px;margin-top:?100px;margin-right:?20px;margin-left:?10px"> ????????<div?draggable="true"?id="box"?style="width:?200px;height:?50px;?background-color:?#409eff"></div> ????</div> ????<div?id="main"?style="display:?flex;justify-content:?center;margin-top:?100px"> ????</div> </div> <script> ????let?mainCard?=?document.getElementById("main"); ????mainCard.ondrop?=?function(e)?{ ????????e.preventDefault(); ????????console.log("進入"); ????????let?elementById?=?document.getElementById("main").querySelector("canvas"); ????????let?x?=?e.clientX?-?elementById.getBoundingClientRect().left; ????????let?y?=?e.clientY?-?elementById.getBoundingClientRect().top; ????????let?{?canvas,?ctx,?image?}?=?canvasData; ????????new?CreateBlank(canvas,?ctx,?{?x:?x,?y:?y,?width:?200,?height:?50,?image?}); ????}; ????mainCard.ondragover?=?function(e)?{ ????????e.preventDefault();//解禁當前元素為可放置被拖拽元素的區(qū)域,即允許在此放置物體 ????}; ????let?pathList?=?[]; ????class?CreateBlank?{ ????????constructor(canvas,?ctx,?area)?{ ????????????this.ctx?=?ctx; ????????????this.canvas?=?canvas; ????????????this.image?=?area.image; ????????????//創(chuàng)建滑塊 ????????????this.blob1?=?this.createBlob(area.x,?area.y,?area.width,?area.height,?"#409eff",?1); ????????????//繪制圓滑塊 ????????????this.DrawBlob(this.blob1); ????????????pathList.push(this.blob1); ????????????let?that?=?this; ????????????//鼠標按下,將鼠標按下坐標保存在x,y中 ????????????this.canvas.onmousedown?=?function(e)?{ ????????????????//記錄鼠標所在位置的坐標 ????????????????that.x?=?e.clientX?-?that.canvas.getBoundingClientRect().left; ????????????????that.y?=?e.clientY?-?that.canvas.getBoundingClientRect().top; ????????????????pathList.forEach((res)?=>?{ ????????????????????res.InnerWidth?=?that.x?-?res.x; ????????????????????res.InnerHeight?=?that.y?-?res.y; ????????????????????that.drag(res,?that.x,?that.y); ????????????????}); ????????????}; ????????} ????????//拖拽函數 ????????drag(blob,?x,?y)?{ ????????????//?判斷鼠標是否在檢測區(qū)域 ????????????let?bo?=?this.getBounds(blob); ????????????if?(this.containsPoint(bo,?x,?y))?{ ????????????????let?that?=?this; ????????????????//注冊鼠標移動事件 ????????????????this.canvas.onmousemove?=?function(e)?{ ????????????????????let?x?=?e.clientX?-?that.canvas.getBoundingClientRect().left; ????????????????????let?y?=?e.clientY?-?that.canvas.getBoundingClientRect().top; ????????????????????//清除畫布內容 ????????????????????that.ctx.clearRect(0,?0,?bo.width,?bo.height); ????????????????????that.ctx.drawImage(that.image,?0,?0); ????????????????????pathList.forEach(res?=>?{ ????????????????????????that.DrawBlob(res); ????????????????????????if?(bo.name?===?res.name)?{ ????????????????????????????//更新塊所在的位置 ????????????????????????????res.x?=?x?-?res.InnerWidth; ????????????????????????????res.y?=?y?-?res.InnerHeight; ????????????????????????} ????????????????????}); ????????????????}; ????????????????//注冊鼠標松開事件 ????????????????this.canvas.onmouseup?=?function()?{ ????????????????????this.onmousemove?=?null; ????????????????????this.onmouseup?=?null; ????????????????}; ????????????} ????????} ????????//創(chuàng)建圓滑塊 ????????createBlob(x,?y,?width,?height,?color,?alpha)?{ ????????????//定義對象 ????????????let?blob?=?{}; ????????????blob.alpha?=?alpha; ????????????blob.color?=?color; ????????????blob.x?=?x; ????????????blob.y?=?y; ????????????blob.width?=?width; ????????????blob.height?=?height; ????????????blob.InnerWidth?=?0; ????????????blob.InnerHeight?=?0; ????????????blob.name?=?Symbol("name"); ????????????return?blob; ????????}; ????????DrawBlob(blob)?{ ????????????this.ctx.globalAlpha?=?blob.alpha; ????????????this.ctx.beginPath(); ????????????this.ctx.fillStyle?=?blob.color; ????????????this.ctx.rect(blob.x,?blob.y,?blob.width,?blob.height); ????????????this.ctx.fill(); ????????????this.ctx.closePath(); ????????????this.ctx.globalAlpha?=?1; ????????}; ????????//獲取檢測區(qū)域 ????????getBounds(blob)?{ ????????????return?{ ????????????????x:?blob.x, ????????????????y:?blob.y, ????????????????width:?blob.width, ????????????????height:?blob.height, ????????????????name:?blob.name ????????????}; ????????} ????????//判斷鼠標是否點擊在指定檢測區(qū)域 ????????containsPoint(rect,?x,?y)?{ ????????????return?!(x?<?rect.x?||?x?>?rect.x?+?rect.width?|| ????????????????y?<?rect.y?||?y?>?rect.y?+?rect.height); ????????} ????} ????function?createCanvas(id)?{ ????????let?elementById?=?document.getElementById(id); ????????return?new?Promise((resolve,?reject)?=>?{ ????????????let?canvas?=?document.createElement("canvas"); ????????????let?image?=?new?Image(); ????????????image.src?=?"https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg"; ????????????//?如果有緩存,讀緩存 ????????????image.onload?=?function()?{ ????????????????image.onload?=?null;???//?避免重復加載 ????????????????canvas.height?=?image.height; ????????????????canvas.width?=?image.width; ????????????????let?ctx?=?canvas.getContext("2d"); ????????????????ctx.drawImage(image,?0,?0); ????????????????elementById.appendChild(canvas); ????????????????resolve({?canvas,?ctx,?image?}); ????????????}; ????????????image.onerror?=?function()?{ ????????????????reject(); ????????????}; ????????}); ????} ????let?canvasData?=?{}; ????createCanvas("main").then(res?=>?{ ????????canvasData?=?res; ????}); </script> </body> </html>