title: Issue with zoom in and zoom out image in canvas Angular
body: <p>I am having issues when I try to zoom in and out of a canvas image.</p>
  <p>The aim is to allow users to draw rectangles on the image. I am using canvas to display the image and then draw rectangles on image, this is working fine. But now I am trying to add zoom in and zoom out functionality. I am facing following issue:</p>
  <p>When I zoom in or zoom out, I need to keep the rectangles in same place with respect to the image. The rectangle stays in the same coordinate location, but as the image is moved , the part of image in the rectangle has changed. How to keep the rectangle to cover same part of image even after zoom in/zoom out.</p>
  <p>I am new to canvas and not sure how to get this working.</p>
  <p>Here is the component that I am having trouble with:</p>
  <p>tagger.component.html</p>
  <pre><code>&lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;text-image-content&quot;&gt;
   
      &lt;div class=&quot;column1&quot;&gt;
          &lt;div style=&quot;position: relative;&quot;&gt;
              &lt;div *ngFor=&quot;let drawItem of drawItems; let i = index&quot;&gt;
                  &lt;input [ngStyle]=&quot;{'left':drawItem.x0 + 'px' , 'top': drawItem.y0 + 'px'}&quot;
                      style=&quot;position: absolute; z-index: 999;&quot; placeholder=&quot;Enter Object Name&quot;
                      [(ngModel)]=&quot;drawItem.name&quot; type=&quot;text&quot;&gt;
                  &lt;input [ngStyle]=&quot;{'left':drawItem.x0 + 'px' , 'top': drawItem.y0 + 'px'}&quot;
                      style=&quot;position: absolute; z-index: 999;&quot; type=&quot;button&quot; value=&quot;X&quot; (click)=&quot;delete(i)&quot;&gt;
              &lt;/div&gt;
              
              &lt;canvas #layer1 id=&quot;layer1&quot; style=&quot;position: absolute; left: 0; top: 0; z-index: 0;&quot;&gt;&lt;/canvas&gt;
              &lt;div class=&quot;row&quot;&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;/div&gt;
  &lt;button class=&quot;zoomBtn&quot; (click)=&quot;zoomIn()&quot;&gt;Zoom in&lt;/button&gt;
  &lt;button class=&quot;zoomBtn&quot; (click)=&quot;zoomOut()&quot;&gt;Zoom out&lt;/button&gt;
      &lt;div class=&quot;column2&quot;&gt;
          &lt;div *ngFor=&quot;let drawItem of originalItems; let i = index&quot;&gt;
              &lt;div class=&quot;details&quot;&gt;
                &lt;div &gt;Name: {{drawItem.name | titlecase}} &lt;/div&gt;
                 &lt;div&gt;({{drawItem.x0}}, {{drawItem.y0}} , {{drawItem.x0 + drawItem.x1}}, {{drawItem.y0 + drawItem.y1}})&lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  <p>tagger.component.ts</p>
  <pre><code>import {
      Component,
      ViewChild,
      Input,
      Output,
      OnInit,
      EventEmitter,
      ElementRef
  } from '@angular/core';
  
  @Component({
      selector: &quot;app-tagger&quot;,
      templateUrl: &quot;./tagger.component.html&quot;,
      styleUrls: [&quot;./tagger.component.scss&quot;]
  })
  export class TaggerComponent implements OnInit {
  
      name = &quot;Angular&quot;;
      constructor() { }
      drawItems = []
      originalItems = []
      count = 0
      @Input('CanvasHeight') CanvasHeight
      @Input('CanvasWidth') CanvasWidth
      @Output() selected = new EventEmitter();
      taggedItem = &quot;&quot;
      showInput: boolean = false;
      isMoving: boolean;
      public imgWidth: number;
      public uniX: number;
      public uniY: number;
      public uniX2: number;
      public uniY2: number;
      public initX: number;
      public initY: number;
      public imgHeight: number;
      public url: string;
      public image;
      public originalImageWidth;
      public originalImageHeight;
      public hRatio;
      public vRatio;
      public translatePos = {x: this.CanvasWidth / 2, y: this.CanvasHeight / 2};
      public scale = 1.0;
      public scaleMultiplier = 0.8;
  
      @ViewChild(&quot;layer1&quot;, { static: false }) layer1Canvas: ElementRef;
      private context: CanvasRenderingContext2D;
      private layer1CanvasElement: any;
  
    ngOnInit(){
      this.imageLoad();
    }
  
      delete(i) {
          console.log(i)
          this.drawItems.splice(i, 1);
          this.originalItems.splice(i,1);
          this.drawRect(&quot;red&quot;, 0, 0, 1);
      }
  
      imageLoad() {
        this.image = new Image();
        this.image.src = &quot;https://i.ibb.co/12TJSNy/patio.jpg&quot;;
        this.image.onload = () =&gt; {
          console.log(this.CanvasWidth, this.CanvasHeight);
          console.log(this.image.width, this.image.height);
          this.originalImageWidth = this.image.width;
          this.originalImageHeight = this.image.height;
          this.image.width = this.CanvasWidth;
          this.image.height = this.CanvasHeight;
          this.hRatio =   this.originalImageWidth/this.CanvasWidth;
          this.vRatio =  this.originalImageHeight/this.CanvasHeight; 
          this.layer1CanvasElement = this.layer1Canvas.nativeElement;
          this.layer1CanvasElement.width = this.CanvasWidth;
          this.layer1CanvasElement.height = this.CanvasHeight;
          this.showImage();
        }
      }
  
      showImage() {
          this.count ++;
          this.layer1CanvasElement = this.layer1Canvas.nativeElement;
          this.context = this.layer1CanvasElement.getContext(&quot;2d&quot;);
          this.context.clearRect(0, 0, this.CanvasWidth, this.CanvasHeight);
          this.context.save();
          this.context.translate(this.translatePos.x, this.translatePos.y);
          this.context.scale(this.scale, this.scale);
          this.context.drawImage(this.image, 0,0, this.image.width, this.image.height);
          this.context.restore()
          let parent = this;
          if(this.count==1){
            this.layer1CanvasElement.addEventListener(&quot;mousedown&quot;, (e) =&gt; {
              this.isMoving = true
              this.initX = e.offsetX;
              this.initY = e.offsetY;
            });
  
          this.layer1CanvasElement.addEventListener(&quot;mouseup&quot;, (e) =&gt; {
              this.isMoving = false
              this.showInput = true
              this.drawItems.push({
                  name: &quot;&quot;,
                  x0: this.initX,
                  y0: this.initY,
                  x1: this.uniX,
                  y1: this.uniY
              });
              this.originalItems.push({
                  name: &quot;&quot;,
                  x0: Math.ceil(this.initX * this.hRatio),
                  y0: Math.ceil(this.initY * this.vRatio),
                  x1: Math.ceil(this.uniX *this.hRatio),
                  y1: Math.ceil(this.uniY * this.vRatio)
              });
              parent.drawRect(&quot;red&quot;, e.offsetX - this.initX, e.offsetY - this.initY, 0);
              this.uniX = undefined
              this.uniY = undefined
          });
        }
          
  
          this.layer1CanvasElement.addEventListener(&quot;mousemove&quot;, (e) =&gt; {
              if (this.isMoving) {
                  parent.drawRect(&quot;red&quot;, e.offsetX - this.initX, e.offsetY - this.initY, 0);
              }
          });
  
          this.drawRect(&quot;red&quot;, 0, 0, 1);
  
      }
  
  
      drawRect(color = &quot;black&quot;, height, width, flag) {
        if (this.uniX | flag) {
          this.context.clearRect(0, 0, this.CanvasWidth, this.CanvasHeight);
          this.context.save();
          this.context.translate(this.translatePos.x, this.translatePos.y);
          this.context.scale(this.scale, this.scale);
          this.context.drawImage(this.image, 0,0, this.image.width, this.image.height);
          this.context.restore()
        }
        // console.log(this.image.width, this.image.height)
        this.uniX = height
        this.uniY = width
        this.uniX2 = height
        this.uniY2 = width
        for (var i = 0; i &lt; this.drawItems.length; i++) {
            this.context.beginPath();
            this.context.rect(
                this.drawItems[i].x0,
                this.drawItems[i].y0,
                this.drawItems[i].x1,
                this.drawItems[i].y1
            );
            this.context.lineWidth = 3;
            this.context.strokeStyle = color;
            this.context.stroke();
        }
      }
  
      zoomIn(){
        console.log(&quot;zooming in&quot;)
        this.scale /= this.scaleMultiplier;
        this.showImage();
      }
      zoomOut(){
        console.log(&quot;zooming out&quot;)
        this.scale *= this.scaleMultiplier;
        this.showImage();
        
      }
  }
  </code></pre>
  <p>tagger.component.scsss</p>
  <pre><code>.button {
      color: transparent;
      cursor: pointer;
  }
  
  .column1 {
      float: left;
      width: 70%;
      padding: 10px;
      height: 300px; /* Should be removed. Only for demonstration */
  }
  .column2 {
      float: left;
      width: 25%;
      padding: 10px;
      height: 300px; /* Should be removed. Only for demonstration */
  }
  
  /* Clear floats after the columns */
  .row:after {
      content: &quot;&quot;;
      display: table;
      clear: both;
  }
  
  .details {
      margin: 10px;
  }
  
  .text-image-content{
  border: 1px solid #979797;
      border-radius: 8px;
      padding: 0 10px;
      margin-left:20px;
      margin-right:20px;
      height: 300px;
      overflow-y: scroll;
      overflow-x: scroll;
      scrollbar-width: thin;
  }
  
  .zoomBtn{
    // height:10px;
  }
  </code></pre>
  <p>The complete code can be found in :  <a href="https://stackblitz.com/edit/angular-tsotfa?file=src%2Fapp%2Ftagger%2Ftagger.component.ts" rel="nofollow noreferrer">https://stackblitz.com/edit/angular-tsotfa?file=src%2Fapp%2Ftagger%2Ftagger.component.ts</a></p>
  <p>Thanks!</p>