Drawing a line beneath the mouse's center using JavaScript

Struggling with my JavaScript drawing tool, particularly the draw() function. The line is consistently off-center below the mouse cursor. How do I fix this issue? My aim is to have the line always follow the center of the mouse as it moves. Could someone clarify if e.pageX and e.pageY accurately represent the mouse's center coordinates as x and y? Thanks in advance!

<!doctype html>
<html>

<head>
  <style>
    canvas {
      border: 1px solid black;
    }
  </style>
</head>

<body>
  <div class="controls">
    <button class="clear">Clear</button> <span>Color
            <input type="color" value="#ffff00" id="penColor"></span>
    <span>Width
            <input type="range" min="1" max="20" value="10" id="penWidth"></span>
  </div>

  <canvas id="canvas"></canvas>
  <script>
    let penColor = document.getElementById("penColor");
    let penWidth = document.getElementById("penWidth");
    let canvas = document.getElementById("canvas");
    canvas.width = 700;
    canvas.height = 700;

    let context = canvas.getContext("2d");
    let clearButton = document.querySelector(".clear");

    let position = {
      x: null,
      y: null
    }

    let initialization = (e) => {
      canvas.addEventListener("mousemove", draw);
      canvas.addEventListener("mouseenter", setPosition)
      canvas.addEventListener("mousemove", setPosition)
    }

    window.onload = initialization;

    let setPosition = (e) => {
      position.x = e.pageX;
      position.y = e.pageY;
    }

    clearButton.addEventListener("click", (e) => {
      let confirmation = confirm("Are you sure you want to clear the canvas?");

      let result = confirmation ? true : false;
      if (result) {
        context.clearRect(0, 0, canvas.width, canvas.height);
      }
    })


    let draw = (e) => {
      if (e.buttons !== 1) return;
      context.beginPath();
      context.moveTo(position.x, position.y);

      setPosition(e);

      context.lineTo(position.x, position.y);
      context.lineWidth = penWidth.value;
      context.strokeStyle = penColor.value;
      context.lineCap = "round";
      context.stroke();
    }
  </script>
</body>

</html>

Answer №1

Understanding MouseEvent.pageX

When dealing with the MouseEvent interface, the pageX property is a read-only attribute that provides the horizontal coordinate (in pixels) of the mouse click event, relative to the document's left edge.

https://example.com/mouseevent-pagex

It's important to note that this value does not represent the X position on the canvas directly, as adjustments need to be made by subtracting the canvas position.

e.pageX - canvas.offsetLeft;
e.pageY - canvas.offsetTop;

let canvas = document.getElementById("canvas");
canvas.width = canvas.height = 200;

let context = canvas.getContext("2d");
let position = { x: null, y: null }

let setPosition = (e) => {
  position.x = e.pageX - canvas.offsetLeft;
  position.y = e.pageY - canvas.offsetTop;
}

let draw = (e) => {
  if (e.buttons !== 1) return;
  context.beginPath();
  context.moveTo(position.x, position.y);

  setPosition(e);
  context.lineTo(position.x, position.y);
  context.stroke();
}

canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mouseenter", setPosition)
canvas.addEventListener("mousemove", setPosition)
canvas {
  border: 1px solid black;
}
<canvas id="canvas"></canvas>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JavaScript Switch Open/Close Mobile Navigation Menu

I'm currently facing a challenge with a specific issue. I want to implement a toggle menu for mobile devices on a website that I'm developing. It's functioning smoothly, and you can see it in action on this CodePen. The JavaScript code for ...

What are the appropriate situations to utilize Q.defer versus using Promise.resolve/reject?

I've been working with nodejs and I'm curious about when to use Q defer over Promise.resolve/reject? There are numerous examples of both methods, such as: // using Q defer function oneWay(myVal) { var deferred = Q.defer(); if (myVal < 0) ...

Migration processes encountering delays due to running nodes

When running migrations in Node, I am encountering a timeout error. The specific error message is: Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. Here is the ...

HTML parsing with HTMLAgilityPack can sometimes be tricky, as the SelectNodes

I've heard great things about the HTMLAgilityPack library and decided to give it a shot, but I have been struggling to make it work for months now. No matter what I do, all my attempts seem to result in null. Following tutorials like this one () doesn ...

Update the div on the current page using externally retrieved information

Once again, I find myself stuck on a problem. Allow me to explain. Within this div, I have retrieved data using HTML SIMPLE DOM from another site. Like so: <div id="data">.....</div> Currently, the data refreshes whenever the user reloads th ...

Unable to find the XPATH element with Selenium in Python due to element not being located

Can anyone help me troubleshoot? My XPATH seems correct, but it's showing 'no element found' error. I also attempted using find_elements(By.XPATH, "/html/body/div[3]/div[3]/div[5]/div[1]/table[*]/tbody/tr[*]/td[1]/a") import time from selen ...

Getting the local folder name using AngularJs

Is there a way to retrieve the directory name by browsing to a folder and clicking a button? I was considering utilizing <input type="file" /> to achieve this. ...

Vue JS causing page to flash briefly before disappearing

I recently started exploring Vue and I'm working on creating a basic search function that takes a user input query and displays all matching users. To help me with this, I've been following a video tutorial for guidance. Despite not encounterin ...

Unable to modify translation values in an existing ngx-translate object

I am facing an issue where I am unable to change the value of an object property within a translation JSON file using ngx translate. Despite attempting to update the value dynamically when receiving data from an API, it seems to remain unchanged. I have t ...

Looking to create a clone of an HTML element, make some modifications, and extract the HTML string without impacting the DOM?

After working with some HTML code, I encountered the following: <div style="background:red;width:900px;height:200px" id="wrap"> <div id="inner" style="width:300px;float:left"> ... </div> </div> The tasks at hand are ...

The hunt is on for greater value within the index

My requirement is to check the text content of a box. If it matches any value stored in an ARRAY, then I have to execute a specific action. var ARRAY1 = ["Saab", "Volvo", "BMW"]; if (select[i].innerHTML.indexOf('ARRAY1') != -1){//code here} ...

The functionality of getAttribute has changed in Firefox 3.5 and IE8, no longer behaving as it did before

Creating a JavaScript function to locate an anchor in a page (specifically with, not an id) and then going through its parent elements until finding one that contains a specified class. The code below works perfectly in Firefox 3.0 but encounters issues wi ...

The agent.add() function is malfunctioning, while console.log() is functioning properly

I'm currently working on integrating a bot using Telegram, Dialogflow, and Firebase. One particular function that I'm struggling with is as follows: function findDoc(agent){ const userId = request.body.originalDetectIntentRequest.payload.dat ...

Using an HTML5 image icon as an input placeholder

Is there a way to incorporate an image icon into an input placeholder and have it disappear when the user starts typing, across all browsers? In trying to achieve this, I successfully implemented a solution for webkit (Safari+Chrome) using ::-webkit-input ...

Reference to a method from a child component in Vue returns an undefined method when using v-for loop

I am facing an issue with a child component and a button that triggers a method within it: <div v-for="(i,index) in user.usertype.max_user" :key="index" class="d-flex w-50"> <vue-user-profiles ref="userProfileComponent"></vue ...

How can I connect the Bootstrap-datepicker element with the ng-model in AngularJS?

Below is the html code for the date field : <div class='form-group'> <label>Check out</label> <input type='text' ng-model='checkOut' class='form-control' data-date-format="yyyy-mm-dd" plac ...

Tips for including an external babel JS (ES6) file in an HTML document:

To include the babel js file in an HTML file, take a look at the code snippet below: <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudfl ...

Develop a JavaScript library for use in the npm ecosystem

I have developed a minimalist JavaScript library that includes common functions: !!window.JsUtils || (window.JsUtils = {}); JsUtils = (function () { "use strict"; return { randomHex: function (len) { var maxlen = 8; ...

Using callbacks in Node.js to pass variables

I'm relatively new to working with node and I'm attempting to develop a function that retrieves server information. However, I've encountered an issue. I've set up a config object (which will eventually be dynamically updated by certain ...

Unusual syntax in Symfony framework

I am currently working on a new project for a website using the Symfony3 framework, and I have encountered an issue with understanding the syntax in Twig: <li><a href="{{ path('contact') }}">{{ 'site.template.menu.contact'| ...