Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ionic 3 - Canvas draw is not perfect as per mouse/touch position

I have created one app, where user can draw anything on canvas. I have added background image to canvas. I want canvas to cover the remaining space on screen. Hence I kept width and height in percent.

Issue - Now whenever I draw something on canvas, it won't follow accurate position of mouse/touch on screen. If I draw below it will draw near about 20px up from touch. (Not sure about how much pixel up but its my assumption)

Please go-through below code.

1. HTML

<ion-row>
      <canvas no-bounce 
      (touchstart)='handleStart($event)' (touchmove)='handleMove($event)' (click)="removeSelectedTxt()"
      [ngStyle]="{'background': 'url(' + selectedImage + ') no-repeat center center fixed', '-webkit-background-size': 'contain',
      '-moz-background-size': 'contain',
      '-o-background-size': 'contain',
      'background-size': 'contain',
      'width': '98%',
      'height': '65%'}" #canvas ></canvas>
  </ion-row>

2. CSS

canvas {
      display: block;
      border: 1px solid #000;
      position: fixed;
      top: 10%;
      left: 1%;
    }

3. TS file

    import { Component, ViewChild,  ElementRef} from '@angular/core';

     @ViewChild('canvas') public canvas: ElementRef;

    this.canvasElement = this.canvas.nativeElement;

handleStart(ev){

        this.lastX = ev.touches[0].pageX;
        this.lastY = ev.touches[0].pageY;
    }

    handleMove(ev){

      let ctx = this.canvasElement.getContext('2d');
      let currentX = ev.touches[0].pageX;
      let currentY = ev.touches[0].pageY;

      ctx.beginPath();
      ctx.lineJoin = "round";
      ctx.moveTo(this.lastX, this.lastY);
      ctx.lineTo(currentX, currentY);
      ctx.closePath();
      ctx.strokeStyle = this.currentColour;
      ctx.lineWidth = this.brushSize;
      ctx.stroke();      

      this.lastX = currentX;
      this.lastY = currentY;
    }

Need help, how do I draw the accurate points of touch on canvas?

like image 260
Flutterian Avatar asked Oct 17 '22 14:10

Flutterian


1 Answers

After doing so many exercises and research on canvas draw, finally I resolved the issue.

I did below changes in typescript file. Calculated offsetLeft and offsetTop in ionViewDidLoad method.

1. ionViewDidLoad() method

this.offsetX = this.canvasElement.offsetLeft;
this.offsetY = this.canvasElement.offsetTop;
  • Once user starts drawing on canvas, means touchStart event, I called handleStart() method. Here I did changes.

2. handleStart(event) method

handleStart(ev){

        this.lastX = ev.touches[0].pageX - this.offsetX;
        this.lastY = ev.touches[0].pageY - this.offsetY;
    }
  • To draw on canvas, I called touchMove event.

3. handleMove(event) method

handleMove(ev){

      // let ctx = this.canvasElement.getContext('2d');
      let currentX = ev.touches[0].pageX - this.offsetX;
      let currentY = ev.touches[0].pageY - this.offsetY;

      this.ctx.beginPath();
      this.ctx.lineJoin = "round";
      this.ctx.moveTo(this.lastX, this.lastY);
      this.ctx.lineTo(currentX, currentY);
      this.ctx.closePath();
      this.ctx.strokeStyle = this.currentColour;
      this.ctx.lineWidth = this.brushSize;
      this.ctx.stroke();      


      this.undoList.push({
        x_start: currentX,
        y_start: currentY,
        x_end: this.lastX,
        y_end: this.lastY,
        color: this.currentColour,
        size: this.brushSize,
        mode: this.ctx.globalCompositeOperation
      });

      this.lastX = currentX;
      this.lastY = currentY;

    }

Note - If you see closely in code, what I did is I calculated offsetLeft and offsetTop. Then minus this from touch points in both handleStart and handleMove method.

like image 76
Flutterian Avatar answered Oct 20 '22 23:10

Flutterian