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

图片说明
在网上学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个回答

你要重新计算,画布上的画点。就是说,画布起点与鼠标起点不同了。你要计算画布到视口的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>
weixin_46423206
weixin_46423206 非常感谢!
2 个月之前 回复

可以换一个思路,把img的图片加载在canvas上,然后在canvas上画图

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐