1

I am developing a paint application. When I position the painting board on the left part of the screen, I am able to draw properly. But when I position it on the right part of the screen, the mouse doesn't draw in the place where it is positioned, but like 100 px away on the right of it. I have developed a drag function, which lets me drag the window of the paint app to different locations in the screen. I am using vanilla Javascript and custom elements.

const template = document.createElement('template')
template.innerHTML = `
<head>
<link rel="stylesheet" href="../css/paint-board.css">
</head>
<div id="board">
<div class="navbar">
<img id="pic" src="../image/tools.png" alt="paint" />
<img id="close" src="../image/error.png" alt="close window" />
</div>
<div id="bucketDiv" class="colour">
<img id="bucket" src="../image/paint-bucket.png" alt="bucket" />
</div>
</div>
<div id="paint">
<canvas id="canvasDrawing">
</canvas>
</div>
</div>
`
export class PaintBoard extends window.HTMLElement {
  constructor () {
    super()
    this.attachShadow({ mode: 'open' })
    this.shadowRoot.appendChild(template.content.cloneNode(true))
    this.x = 0
    this.y = 0
    window.colour = 'black'
    const canvas = this.shadowRoot.querySelector('#canvasDrawing')
    window.ctx = canvas.getContext('2d')
  }

  connectedCallback () {
    this.initialize()
    this.closeWindow()
    this.changeColour()
    this.changeLineWidth()
    this.changeBackground()
  }

  closeWindow () {
    const close = this.shadowRoot.querySelector('#board')
    close.addEventListener('click', event => {
      if (event.target === this.shadowRoot.querySelector('#close')) {
        close.classList.add('removed')
      }
    })
  }

  // intialize drawing on the board
  initialize () {
    const paintingBoard = this.shadowRoot.querySelector('#paint')
    this.size()
    paintingBoard.addEventListener('mousemove', event => {
      event.stopImmediatePropagation()
      this.draw(event)
    })
    paintingBoard.addEventListener('mousedown', event => {
      event.stopImmediatePropagation()
      this.setPosition(event)
    })
    paintingBoard.addEventListener('mouseenter', event => {
      this.setPosition(event)
    })
    dragElement(this.shadowRoot.querySelector('#board'))
  }

  draw (e) {
    if (e.buttons !== 1) return // if mouse is pressed.....
    window.ctx.beginPath() // begin the drawing path
    window.ctx.lineCap = 'round' // rounded end cap
    window.ctx.strokeStyle = window.colour // hex color of line
    window.ctx.moveTo(this.x, this.y) // from position
    this.x = e.clientX
    this.y = e.clientY
    window.ctx.lineTo(this.x, this.y) // to position
    window.ctx.stroke() // draw it!
  }

  // size canvas
  size () {
    window.ctx.canvas.width = 750
    window.ctx.canvas.height = 510
  }

  // new position from mouse events
  setPosition (e) {
    this.x = e.clientX
    this.y = e.clientY
  }
Black Jack
  • 13
  • 7
  • Looks like you're capturing mouse coordinate positions based on the viewport. In order to get the mouse position relative to the drawing context of the canvas, you'll need to subtract the canvas's x and y position (in relation to the viewport) from the mouse's x and y position (in relation to the viewport). – Sean Oct 23 '19 at 12:50
  • @sean Should I do that in the setPosition() function? – Black Jack Oct 23 '19 at 12:58
  • Can someone help ? – Black Jack Oct 23 '19 at 14:08

1 Answers1

0
// where canvas is your canvas element
const rect = canvas.getBoundingClientRect();
this.x = e.pageX - window.pageXOffset - rect.left;
this.y = e.pageY - window.pageYOffset - rect.top;

Worked for me, hopefully it will work for you.

e.pageX/e.pageY will get you the coordinates of the mouse on the page as a whole.

window.pageXOffset/window.pageYOffset will get you the amount the user has scrolled so far.

rect.left/rect.top will give you the coordinates of the top left corner of your canvas element

e.pageY - window.pageYOffset = location of your mouse in the window

e.pageY - window.pageYOffset - rect.top = location of your mouse inside the canvas