It’s very hard to explain. But I’ll try, the whole canvas is offset. I’m not sure how this even happened or how to fix it. It’s like when your mouse is in the top left corner of the page, and you started in the center, it matches up with the top left corner of the canvas element itself. Use the code snippets to see 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 kind of weird but please bare with me.
2
Answers
This is actually a simple one to solve. You merely forgot to offset the
clientX
andclientY
. You see, those coordinates are in window space therefore (0,0) will be the top left of your window. If your canvas is also in the top left then everything will seem all fine but in your case the canvas is center so the coordinates won’t align. This can be fixed by subtracting the coordinates by the screen position of the canvas.Here’s an example:
You can read more about getBoundingClientRect over at https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
The way of calculating the position of the mouse is not appropriate, it is necessary to take into account the deviation of the canvas compared to the viewport. You can’t do it using getBoundingClientRect() :
But you also have to fix the
.canvas
css class by removing width and height or by setting the same height than in the resize function.https://codepen.io/Joulss/pen/BaPYgpZ?editors=1111