问答详情
源自:9-5 Canvas图形库

html canvas 绘图实现可拖拽矩形发生偏移

问题描述

在线dome

前端在采样canvas 绘制,可拖动矩形时,产生了一个bug,检查了很久找不到原因,请求大佬们解惑;

bug 演示

当图中有两个可拖动块时,拖动一个,另外一个 会发生小许的偏移

http://img1.mukewang.com/63902f810001dd8e12700690.jpg


完整代码

<!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();//解禁当前元素为可放置被拖拽元素的区域,即允许在此放置物体
    };
    let pathList = [];
    class CreateBlank {
        constructor(canvas, ctx, area) {
            this.ctx = ctx;
            this.canvas = canvas;
            this.image = area.image;
            //创建滑块
            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) {
            // 判断鼠标是否在检测区域
            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;
                };
            }
        }
        //创建圆滑块
        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;
        };
        //获取检测区域
        getBounds(blob) {
            return {
                x: blob.x,
                y: blob.y,
                width: blob.width,
                height: blob.height,
                name: blob.name
            };
        }
        //判断鼠标是否点击在指定检测区域
        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>


提问者:qq_慕设计3294053 2022-12-07 14:16

个回答