It's hard to explain. But I'll try, the whole canvas is offset. I'm not sure how this happened or how to fix it. Like when your mouse is in the top left corner of the page and you start from the center, it matches the top left corner of the canvas element itself. Use code snippets to understand what I'm talking about.
let currentColor = null; let inputs = document.getElementsByClassName("style2"); for (const input of inputs) { input.addEventListener("click", (e) => { if (e.detail !== 2) e.preventDefault(); }); } let arr = []; for (let i = 0; i < inputs.length + 1; i++) { arr.push(i.toString()); } arr.shift(); for (const input of inputs) { input.addEventListener("input", (e) => { const { value } = document.getElementById(e.target.id); currentColor = value; $("#selectedColor").css("background-color", value); }) input.addEventListener("click", (e) => { const { value } = document.getElementById(e.target.id); currentColor = value; $("#selectedColor").css("background-color", value); }) } var rangeslider = document.getElementById("sliderRange"); const setSize = document.getElementById("setSize") const submit = document.getElementById("submit") submit.addEventListener("click", (e) => { rangeslider.value = setSize.value }) const button = document.getElementById("clear") // create canvas element and append it to document body var canvas = document.getElementById('canvas'); // some hotfixes... ( ≖_≖) // get canvas 2D context and set him correct size var ctx = canvas.getContext('2d'); resize(); // last known position var pos = { x: 0, y: 0 }; window.addEventListener('resize', resize); button.addEventListener('click', clear) document.addEventListener('mousemove', draw); document.addEventListener('mousedown', setPosition); document.addEventListener('mousemove', setPosition); // new position from mouse event function setPosition(e) { let canvas = document.getElementById("canvas") pos.x = e.clientX pos.y = e.clientY } // resize canvas function resize() { ctx.canvas.width = 650; ctx.canvas.height = 375; } function draw(e) { // mouse left button must be pressed if (e.buttons !== 1) return; let canvas = document.getElementById('canvas'); console.log(pos) ctx.beginPath(); // begin ctx.lineWidth = rangeslider.value; ctx.lineCap = 'round'; ctx.strokeStyle = currentColor; ctx.moveTo(pos.x, pos.y); // from setPosition(e); ctx.lineTo(pos.x, pos.y); // to ctx.stroke(); // draw it! } function clear() { ctx.clearRect(0, 0, canvas.width, canvas.height); }
html, body { height: 100%; width: 100%; font-family: sans-serif; background-color: #B3B7B5; /* overflow: hidden; */ } .style2 { -webkit-appearance: none; -moz-appearance: none; appearance: none; background-color: transparent; width: 35px; height: 35px; border: none; cursor: pointer; } .style2::-webkit-color-swatch { border-radius: 50%; border: 3px solid #000000; } .style2::-moz-color-swatch { border-radius: 50%; border: 3px solid #000000; } .box { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: center; gap: 5px; max-width: 320px; margin: 0 auto; padding: 7.5px 10px; } .box1 { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: center; gap: 5px; max-width: 9999px; margin: 0 auto; padding: 10px 10px; } .box5 { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: center; gap: 5px; max-width: 650px; margin: 0 auto; padding: 10px 10px; } .box2 { display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; align-items: center; gap: 5px; max-width: 9999px; margin: 0 auto; padding: 10px 10px; } #selectedColor { width: 100px; height: 30px; border: 3px solid black; border-radius: 5px; background-color: black; } .canvas { height: 350px; width: 650px; border: 3px solid black; border-radius: 5px; background-color: white; cursor: crosshair; position: relative; /* left: 50%; */ } #clear { width: 50px; height: 35px; font-size: 15px; border-radius: 5px; } #submit { width: 59px; height: 23px; margin: auto; left: 35%; border-radius: 5px; position: relative; } .rangeslider { width: 50%; } .myslider { -webkit-appearance: none; background: #FCF3CF ; width: 50%; height: 20px; opacity: 2; } .myslider::-webkit-slider-thumb { -webkit-appearance: none; cursor: pointer; background: #34495E ; width: 5%; height: 20px; } .myslider:hover { opacity: 1; } .rangeslider { left: 38%; position: absolute; }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>replit</title> <link href="style.css" rel="stylesheet" type="text/css" /> </head> <body> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="box5"> <canvas class="canvas" id="canvas"></canvas> </div> <div class="box1"> <button id="clear">Clear</button><br> </div> <div class="box1"> <div class="rangeslider"> <input type="range" min="1" max="100" value="5" class="myslider" id="sliderRange"> </div> </div> <div class=box1> <div> <input id="setSize" type="text" placeholder="Set Brush Size... (Max 100)"> <br> <button type="submit" id="submit" for="setSize">Submit</button> </div> </div> <div class="box"> <div class="container"> <input type="color" value="#000000" class="style2" id="1" /> </div> <div class="container"> <input type="color" value="#ffffff" class="style2" id="2" /> </div> <div class="container"> <input type="color" value="#ffffff" class="style2" id="3" /> </div> <div class="container"> <input type="color" value="#ffffff" class="style2" id="4" /> </div> <div class="container"> <input type="color" value="#ffffff" class="style2" id="5" /> </div> </div> <div class="box"> <label for="selectedColor">Current Color:</label> <div id="selectedColor"></div> </div> <script src="script.js"></script> </body> </html>
I know this code is a bit weird, but please tell me.
P粉9051445142024-03-29 14:08:37
The way to calculate the mouse position is not appropriate, and the deviation of the canvas relative to the viewport needs to be taken into account. You cannot use getBoundingClientRect() to do this:
function setPosition(e) { const canvas = document.getElementById("canvas"); const bounds = canvas.getBoundingClientRect(); pos.x = e.clientX - bounds.left; pos.y = e.clientY - bounds.top; }
But you must also fix the .canvas
css class by removing the width and height or setting the same height as in the resize function.
https://codepen.io/Joulss/pen/BaPYgpZ?editors=1111
P粉4818158972024-03-29 11:28:25
This is actually an easy problem to solve. You just forgot about the offsets clientX
and clientY
. You see, these coordinates are in window space, so (0,0) will be in the upper left corner of the window. If your canvas was also in the top left corner then everything would look fine, but in your case the canvas is in the center so the coordinates don't line up. This can be fixed by subtracting the coordinates from the screen position of the canvas.
This is an example:
function setPosition(e) { let canvas = document.getElementById("canvas") let bounds = canvas.getBoundingClientRect() pos.x = e.clientX - bounds.x pos.y = e.clientY - bounds.y }