weixin_46423206 2020-07-24 15:51 采纳率: 0%
浏览 579
已采纳

画布放居中 鼠标错位应该怎么解决

图片说明
在网上学javaScript(Canvas)做了个画板,现在想把这画布放在中间,用CSS调到中间之后就画不了(鼠标错位),
网上找不着什么教程,希望那位大佬教教

HTML
<body>

    <canvas id="drawing-board" width="500" height="500"></canvas>
    <div class="color-group">
        <ul>
            <li id="black" class="color-item active" style="background-color: black;"></li>
            <li id="red" class="color-item" style="background-color: #FF3333;"></li>
            <li id="blue" class="color-item" style="background-color: #0066FF;"></li>
            <li id="yellow" class="color-item" style="background-color: #FFFF33;"></li>
            <li id="green" class="color-item" style="background-color: #33CC66;"></li>
            <li id="gray" class="color-item" style="background-color: gray;"></li>
            <li id="fuchsia" class="color-item" style="background-color: fuchsia;"></li>
            <li id="aqua" class="color-item" style="background-color: aqua;"></li>
            <li id="purple" class="color-item" style="background-color: purple;"></li>
            <li id="maroon" class="color-item" style="background-color: maroon;"></li>



        </ul>
    </div>
    <div id="range-wrap"><input type="range" id="range" min="1" max="8" value="5" title=""></div>
    <div class="tools">
        <button id="brush" class="active" title=""><i class="iconfont icon-qianbi">笔</i></button>
        <button id="eraser" title="" text=""><i class="iconfont icon-xiangpi">橡皮</i></button>
        <button id="clear" title=""><i class="iconfont icon-qingchu">清除</i></button>
        <button id="undo" title=""><i class="iconfont icon-chexiao">返回</i></button>
        <button id="save" title=""><i class="iconfont icon-fuzhi">保存</i></button>
    </div>
</body>

CSS
*{margin:0; padding: 0;user-select: none;}
body{overflow:hidden}

#drawing-board{background: white;position:fixed; display: block;cursor: crosshair; width:500px height:500px;border: solid 2px gray;}
.tools{position: fixed;left:0;bottom: 50px; width:100%;display: flex;justify-content: center;text-align: center}
.tools button{border-radius: 50%;width: 50px;height: 50px; background-color: rgba(255,255,255,0.7);border: 1px solid #eee;outline: none;cursor: pointer;box-sizing: border-box;margin: 0 10px;text-align: center;color:#ccc;line-height: 50px;box-shadow:0 0 8px rgba(0,0,0,0.1); transition: 0.3s;}
.tools button.active,.tools button:active{box-shadow: 0 0 15px #00CCFF; color:#00CCFF;}
.tools button i{font-size: 14px;}
.color-group{position:fixed;width: 30px;left: 30px;top:30%;transform: translate(0,-150px)}
.color-group ul{list-style: none;}
.color-group ul li{width: 30px;height: 30px;margin: 10px 0;border-radius: 50%;box-sizing: border-box;border:3px solid white;box-shadow: 0 0 8px rgba(0,0,0,0.2);cursor: pointer;transition: 0.3s;}
.color-group ul li.active{box-shadow:0 0 15px #00CCFF;}
#range-wrap{position: fixed;top: 50%;right:30px;width: 30px;height: 150px;margin-top: -75px;}
#range-wrap input{transform: rotate(-90deg);width: 150px;height: 20px;margin: 0;transform-origin: 75px 75px;    border-radius: 15px;-webkit-appearance: none;outline: none;position: relative;}
#range-wrap input::after{display: block;content:"";width:0;height: 0;border:5px solid transparent;
    border-right:150px solid #00CCFF;border-left-width:0;position: absolute;left: 0;top: 5px;border-radius:15px; z-index: 0; }
#range-wrap input[type=range]::-webkit-slider-thumb,#range-wrap input[type=range]::-moz-range-thumb{-webkit-appearance: none;}
#range-wrap input[type=range]::-webkit-slider-runnable-track,#range-wrap input[type=range]::-moz-range-track {height: 10px;border-radius: 10px;box-shadow: none;}
#range-wrap input[type=range]::-webkit-slider-thumb{-webkit-appearance: none;height: 20px;width: 20px;margin-top: -1px;background: #ffffff;border-radius: 50%;box-shadow: 0 0 8px #00CCFF;position: relative;z-index: 999;}

@media screen and (max-width: 868px) {
    .tools{bottom:auto;top:20px;}
    .tools button{width: 50px;height: 50px;line-height: 50px;margin-bottom: 50px;box-shadow:0 0 5px rgba(0,0,0,0.1);}
    .tools button.active,.tools button:active{box-shadow: 0 0 5px #00CCFF;}
    .tools button i{font-size: 30px;}
    .tools #swatches{display: none}
    .color-group{left: 0;top:auto;bottom: 40px;display: flex;width:100%;justify-content: center;text-align: center;transform: translate(0,0)}
    .color-group ul li{display: inline-block;margin:0 5px;}
    .color-group ul li.active{box-shadow:0 0 10px ;}
    #range-wrap{right:auto;left: 20px;}
}


JS

let canvas = document.getElementById("drawing-board");
let ctx = canvas.getContext("2d");
let eraser = document.getElementById("eraser");
let brush = document.getElementById("brush");
let reSetCanvas = document.getElementById("clear");
let aColorBtn = document.getElementsByClassName("color-item");
let save = document.getElementById("save");
let undo = document.getElementById("undo");
let range = document.getElementById("range");
let clear = false;
let activeColor = 'black';
let lWidth = 4;

autoSetSize(canvas);

setCanvasBg('white');

listenToUser(canvas);

getColor();

window.onbeforeunload = function(){
    return "Reload site?";
};



function autoSetSize(canvas) {
    canvasSetSize();

    function canvasSetSize() {
        let pageWidth = document.documentElement.clientWidth;
        let pageHeight = document.documentElement.clientHeight;

        canvas.width = 500;
        canvas.height = 500;
    }

    window.onresize = function () {
        canvasSetSize();
    }
}

function setCanvasBg(color) {
    ctx.fillStyle = color;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "black";
}

function listenToUser(canvas) {
    let painting = false;
    let lastPoint = {x: undefined, y: undefined};

    if (document.body.ontouchstart !== undefined) {
        canvas.ontouchstart = function (e) {
            this.firstDot = ctx.getImageData(0, 0, canvas.width, canvas.height);
            saveData(this.firstDot);
            painting = true;
            let x = e.touches[0].clientX;
            let y = e.touches[0].clientY;
            lastPoint = {"x": x, "y": y};
            ctx.save();
            drawCircle(x, y, 0);
        };
        canvas.ontouchmove = function (e) {
            if (painting) {
                let x = e.touches[0].clientX;
                let y = e.touches[0].clientY;
                let newPoint = {"x": x, "y": y};
                drawLine(lastPoint.x, lastPoint.y, newPoint.x, newPoint.y);
                lastPoint = newPoint;
            }
        };

        canvas.ontouchend = function () {
            painting = false;
        }
    } else {
        canvas.onmousedown = function (e) {
            this.firstDot = ctx.getImageData(0, 0, canvas.width, canvas.height);
            saveData(this.firstDot);
            painting = true;
            let x = e.clientX;
            let y = e.clientY;
            lastPoint = {"x": x, "y": y};
            ctx.save();
            drawCircle(x, y, 0);
        };
        canvas.onmousemove = function (e) {
            if (painting) {
                let x = e.clientX;
                let y = e.clientY;
                let newPoint = {"x": x, "y": y};
                drawLine(lastPoint.x, lastPoint.y, newPoint.x, newPoint.y,clear);
                lastPoint = newPoint;
            }
        };

        canvas.onmouseup = function () {
            painting = false;
        };

        canvas.mouseleave = function () {
            painting = false;
        }
    }
}

function drawCircle(x, y, radius) {
    ctx.save();
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI * 2);
    ctx.fill();
    if (clear) {
        ctx.clip();
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.restore();
    }
}

function drawLine(x1, y1, x2, y2) {
    ctx.lineWidth = lWidth;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    if (clear) {
        ctx.save();
        ctx.globalCompositeOperation = "destination-out";
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
        ctx.closePath();
        ctx.clip();
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.restore();
    }else{
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.stroke();
        ctx.closePath();
    }
}

range.onchange = function(){
    lWidth = this.value;
};

eraser.onclick = function () {
    clear = true;
    this.classList.add("active");
    brush.classList.remove("active");
};

brush.onclick = function () {
    clear = false;
    this.classList.add("active");
    eraser.classList.remove("active");
};

reSetCanvas.onclick = function () {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    setCanvasBg('white');
};

save.onclick = function () {
    let imgUrl = canvas.toDataURL("image/png");
    let saveA = document.createElement("a");
    document.body.appendChild(saveA);
    saveA.href = imgUrl;
    saveA.download = "zspic" + (new Date).getTime();
    saveA.target = "_blank";
    saveA.click();
};

function getColor(){
    for (let i = 0; i < aColorBtn.length; i++) {
        aColorBtn[i].onclick = function () {
            for (let i = 0; i < aColorBtn.length; i++) {
                aColorBtn[i].classList.remove("active");
                this.classList.add("active");
                activeColor = this.style.backgroundColor;
                ctx.fillStyle = activeColor;
                ctx.strokeStyle = activeColor;
            }
        }
    }
}

let historyDeta = [];

function saveData (data) {
    (historyDeta.length === 10) && (historyDeta.shift());
    historyDeta.push(data);
}

undo.onclick = function(){
    if(historyDeta.length < 1) return false;
    ctx.putImageData(historyDeta[historyDeta.length - 1], 0, 0);
    historyDeta.pop()
};

  • 写回答

2条回答

  • it_lin_web 2020-07-25 17:09
    关注

    你要重新计算,画布上的画点。就是说,画布起点与鼠标起点不同了。你要计算画布到视口的left与top,然后画到画布上,鼠标的坐标都减掉对应的left与top。我帮你改了。代码如下:图片说明

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
            content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
                user-select: none;
            }
    
            body {
                /* overflow: hidden */
                position: relative;
                width: 500px;
                margin: 0 auto;
                height: 500px;
            }
    
            #drawing-board {
                background: white;
                /* position: fixed; */
                display: block;
                cursor: crosshair;
                width: 500px;
                height:500px;
                border: solid 2px gray;
                position: absolute;
                left: 0;
                top: 0;
            }
    
            .tools {
                position: fixed;
                left: 0;
                bottom: 50px;
                width: 100%;
                display: flex;
                justify-content: center;
                text-align: center
            }
    
            .tools button {
                border-radius: 50%;
                width: 50px;
                height: 50px;
                background-color: rgba(255, 255, 255, 0.7);
                border: 1px solid #eee;
                outline: none;
                cursor: pointer;
                box-sizing: border-box;
                margin: 0 10px;
                text-align: center;
                color: #ccc;
                line-height: 50px;
                box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
                transition: 0.3s;
            }
    
            .tools button.active,
            .tools button:active {
                box-shadow: 0 0 15px #00CCFF;
                color: #00CCFF;
            }
    
            .tools button i {
                font-size: 14px;
            }
    
            .color-group {
                position: fixed;
                width: 30px;
                left: 30px;
                top: 30%;
                transform: translate(0, -150px)
            }
    
            .color-group ul {
                list-style: none;
            }
    
            .color-group ul li {
                width: 30px;
                height: 30px;
                margin: 10px 0;
                border-radius: 50%;
                box-sizing: border-box;
                border: 3px solid white;
                box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
                cursor: pointer;
                transition: 0.3s;
            }
    
            .color-group ul li.active {
                box-shadow: 0 0 15px #00CCFF;
            }
    
            #range-wrap {
                position: fixed;
                top: 50%;
                right: 30px;
                width: 30px;
                height: 150px;
                margin-top: -75px;
            }
    
            #range-wrap input {
                transform: rotate(-90deg);
                width: 150px;
                height: 20px;
                margin: 0;
                transform-origin: 75px 75px;
                border-radius: 15px;
                -webkit-appearance: none;
                outline: none;
                position: relative;
            }
    
            #range-wrap input::after {
                display: block;
                content: "";
                width: 0;
                height: 0;
                border: 5px solid transparent;
                border-right: 150px solid #00CCFF;
                border-left-width: 0;
                position: absolute;
                left: 0;
                top: 5px;
                border-radius: 15px;
                z-index: 0;
            }
    
            #range-wrap input[type=range]::-webkit-slider-thumb,
            #range-wrap input[type=range]::-moz-range-thumb {
                -webkit-appearance: none;
            }
    
            #range-wrap input[type=range]::-webkit-slider-runnable-track,
            #range-wrap input[type=range]::-moz-range-track {
                height: 10px;
                border-radius: 10px;
                box-shadow: none;
            }
    
            #range-wrap input[type=range]::-webkit-slider-thumb {
                -webkit-appearance: none;
                height: 20px;
                width: 20px;
                margin-top: -1px;
                background: #ffffff;
                border-radius: 50%;
                box-shadow: 0 0 8px #00CCFF;
                position: relative;
                z-index: 999;
            }
    
            @media screen and (max-width: 868px) {
                .tools {
                    bottom: auto;
                    top: 20px;
                }
    
                .tools button {
                    width: 50px;
                    height: 50px;
                    line-height: 50px;
                    margin-bottom: 50px;
                    box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
                }
    
                .tools button.active,
                .tools button:active {
                    box-shadow: 0 0 5px #00CCFF;
                }
    
                .tools button i {
                    font-size: 30px;
                }
    
                .tools #swatches {
                    display: none
                }
    
                .color-group {
                    left: 0;
                    top: auto;
                    bottom: 40px;
                    display: flex;
                    width: 100%;
                    justify-content: center;
                    text-align: center;
                    transform: translate(0, 0)
                }
    
                .color-group ul li {
                    display: inline-block;
                    margin: 0 5px;
                }
    
                .color-group ul li.active {
                    box-shadow: 0 0 10px;
                }
    
                #range-wrap {
                    right: auto;
                    left: 20px;
                }
            }
        </style>
    </head>
    
    <body>
    
        <canvas id="drawing-board" width="500" height="500"></canvas>
        <div class="color-group">
            <ul>
                <li id="black" class="color-item active" style="background-color: black;"></li>
                <li id="red" class="color-item" style="background-color: #FF3333;"></li>
                <li id="blue" class="color-item" style="background-color: #0066FF;"></li>
                <li id="yellow" class="color-item" style="background-color: #FFFF33;"></li>
                <li id="green" class="color-item" style="background-color: #33CC66;"></li>
                <li id="gray" class="color-item" style="background-color: gray;"></li>
                <li id="fuchsia" class="color-item" style="background-color: fuchsia;"></li>
                <li id="aqua" class="color-item" style="background-color: aqua;"></li>
                <li id="purple" class="color-item" style="background-color: purple;"></li>
                <li id="maroon" class="color-item" style="background-color: maroon;"></li>
            </ul>
        </div>
        <div id="range-wrap"><input type="range" id="range" min="1" max="8" value="5" title=""></div>
        <div class="tools">
            <button id="brush" class="active" title=""><i class="iconfont icon-qianbi">笔</i></button>
            <button id="eraser" title="" text=""><i class="iconfont icon-xiangpi">橡皮</i></button>
            <button id="clear" title=""><i class="iconfont icon-qingchu">清除</i></button>
            <button id="undo" title=""><i class="iconfont icon-chexiao">返回</i></button>
            <button id="save" title=""><i class="iconfont icon-fuzhi">保存</i></button>
        </div>
    </body>
    
    </html>
    <script>
        let canvas = document.getElementById("drawing-board");
        let ctx = canvas.getContext("2d");
        let eraser = document.getElementById("eraser");
        let brush = document.getElementById("brush");
        let reSetCanvas = document.getElementById("clear");
        let aColorBtn = document.getElementsByClassName("color-item");
        let save = document.getElementById("save");
        let undo = document.getElementById("undo");
        let range = document.getElementById("range");
        let clear = false;
        let activeColor = 'black';
        let lWidth = 4;
    
    
        let offsetLeft = canvas.getBoundingClientRect().left
        let offsetTop = canvas.getBoundingClientRect().top
    
    
        autoSetSize(canvas);
    
        setCanvasBg('white');
    
        listenToUser(canvas);
    
        getColor();
    
        window.onbeforeunload = function () {
            return "Reload site?";
        };
    
        function autoSetSize(canvas) {
            canvasSetSize();
    
            function canvasSetSize() {
                let pageWidth = document.documentElement.clientWidth;
                let pageHeight = document.documentElement.clientHeight;
    
                canvas.width = 500;
                canvas.height = 500;
            }
    
            window.onresize = function () {
                canvasSetSize();
            }
        }
    
        function setCanvasBg(color) {
            ctx.fillStyle = color;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = "black";
        }
    
        function listenToUser(canvas) {
            let painting = false;
            let lastPoint = { x: undefined, y: undefined };
    
            if (document.body.ontouchstart !== undefined) {
                canvas.ontouchstart = function (e) {
                    let x = e.touches[0].clientX;
                    let y = e.touches[0].clientY;
                    this.firstDot = ctx.getImageData(0, 0, canvas.width, canvas.height);
                    saveData(this.firstDot);
                    painting = true;
    
                    lastPoint = { "x": x, "y": y };
                    ctx.save();
                    drawCircle(x - offsetLeft, y - offsetTop, 0);
                };
                canvas.ontouchmove = function (e) {
                    if (painting) {
                        let x = e.touches[0].clientX;
                        let y = e.touches[0].clientY;
                        let newPoint = { "x": x, "y": y };
                        drawLine(lastPoint.x - offsetLeft, lastPoint.y - offsetTop, newPoint.x - offsetLeft, newPoint.y - offsetTop, clear);
                        lastPoint = newPoint;
                    }
                };
    
                canvas.ontouchend = function () {
                    painting = false;
                }
            } else {
                canvas.onmousedown = function (e) {
                    this.firstDot = ctx.getImageData(0, 0, canvas.width, canvas.height);
                    saveData(this.firstDot);
                    painting = true;
                    let x = e.clientX;
                    let y = e.clientY;
                    lastPoint = { "x": x, "y": y };
                    ctx.save();
                    drawCircle(x - offsetLeft, y - offsetTop, 0);
                };
                canvas.onmousemove = function (e) {
                    if (painting) {
                        let x = e.clientX;
                        let y = e.clientY;
                        let newPoint = { "x": x, "y": y };
                        drawLine(lastPoint.x - offsetLeft, lastPoint.y - offsetTop, newPoint.x - offsetLeft, newPoint.y - offsetTop, clear);
                        lastPoint = newPoint;
                    }
                };
    
                canvas.onmouseup = function () {
                    painting = false;
                };
    
                canvas.mouseleave = function () {
                    painting = false;
                }
            }
        }
    
        function drawCircle(x, y, radius) {
            ctx.save();
            ctx.beginPath();
            ctx.arc(x, y, radius, 0, Math.PI * 2);
            ctx.fill();
            if (clear) {
                ctx.clip();
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.restore();
            }
        }
    
        function drawLine(x1, y1, x2, y2) {
            ctx.lineWidth = lWidth;
            ctx.lineCap = "round";
            ctx.lineJoin = "round";
            if (clear) {
                ctx.save();
                ctx.globalCompositeOperation = "destination-out";
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                ctx.stroke();
                ctx.closePath();
                ctx.clip();
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.restore();
            } else {
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                ctx.stroke();
                ctx.closePath();
            }
        }
    
        range.onchange = function () {
            lWidth = this.value;
        };
    
        eraser.onclick = function () {
            clear = true;
            this.classList.add("active");
            brush.classList.remove("active");
        };
    
        brush.onclick = function () {
            clear = false;
            this.classList.add("active");
            eraser.classList.remove("active");
        };
    
        reSetCanvas.onclick = function () {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            setCanvasBg('white');
        };
    
        save.onclick = function () {
            let imgUrl = canvas.toDataURL("image/png");
            let saveA = document.createElement("a");
            document.body.appendChild(saveA);
            saveA.href = imgUrl;
            saveA.download = "zspic" + (new Date).getTime();
            saveA.target = "_blank";
            saveA.click();
        };
    
        function getColor() {
            for (let i = 0; i < aColorBtn.length; i++) {
                aColorBtn[i].onclick = function () {
                    for (let i = 0; i < aColorBtn.length; i++) {
                        aColorBtn[i].classList.remove("active");
                        this.classList.add("active");
                        activeColor = this.style.backgroundColor;
                        ctx.fillStyle = activeColor;
                        ctx.strokeStyle = activeColor;
                    }
                }
            }
        }
    
        let historyDeta = [];
    
        function saveData(data) {
            (historyDeta.length === 10) && (historyDeta.shift());
            historyDeta.push(data);
        }
    
        undo.onclick = function () {
            if (historyDeta.length < 1) return false;
            ctx.putImageData(historyDeta[historyDeta.length - 1], 0, 0);
            historyDeta.pop()
        };
    </script>
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料