Select image to have border on particular width and height [closed]

This is a follow-up question based on Select x and y on image in particular areas and create a border on it

What I want more to achieve it is to enable clicking directly on the image and automatically selecting a specific area (like number 81) with a border, it should like a feature that calculates which part of the image is being clicked based on the mouse click coordinates relative to the image.

I don’t want to post any code here because it is on the Stackblitz

I don’t understand why people voted to close this question only because they didn’t want to look the code from the other question.

I didn’t want to create same code again and again that is why I have posted the stackblitz link.

But anyway here you have some details.

The previous question got solved but with a follow up code which needs to be done.

The idea it is to select into image and then select particular parts but only to be available to select on numbers on image and nowhere else.

The image is based on coordinates which shows particular numbers.

This is the html.

<table>
  <thead>
    <tr>
      <th scope="col">Name</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let row of columns">
      <td (click)="showCorner(row)">{{ row.itemNumber }}</td>
      <td (click)="showCorner(row)">{{ row.partNumber }}</td>
    </tr>
  </tbody>
</table>

<div class="flex-1 relative">
  <div class="relative">
    <img
      #imgPath
      (click.double)="addBorder($event)"
      style="width: 832px; max-width: fit-content;"
      src="../../assets/flow-editor/Image/ev00129014.png"
    />
    <div
      id="rec1"
      class="absolute"
      [ngStyle]="{ left: coordinateX + 'px', top: coordinateY + 'px' }"
    ></div>
  </div>
</div>

And this is the TS.

export class AppComponent implements AfterViewInit {
  @ViewChild('imgPath', { static: false }) imgElementRef!: ElementRef;
  coordinateX!: number;
  coordinateY!: number;
  originalCoordinates: any; // To store original coordinates
  columns = [
    {
      itemNumber: '1',
      partNumber: '4400535240',
      coordinates: [
        {
          itemCounter: 0,
          xposition: 970,
          yposition: 375,
        },
      ],
    },
    {
      itemNumber: '2',
      partNumber: '4400541680',
      coordinates: [
        {
          itemCounter: 0,
          xposition: 1282,
          yposition: 522,
        },
      ],
    },
    {
      itemNumber: '4',
      partNumber: '4400541390',
      coordinates: [
        {
          itemCounter: 0,
          xposition: 445,
          yposition: 307,
        },
      ],
    },
  ];

  constructor() {
    // Deep copy of original columns to preserve original coordinates
    this.originalCoordinates = JSON.parse(JSON.stringify(this.columns));
  }

  ngAfterViewInit() {
    // Calculate and apply scaling when the view is initialized
    this.calculateAndApplyScaling();
  }

  private calculateOffset(): number {
    const imgElement = this.imgElementRef.nativeElement as HTMLImageElement;

    // Get various properties
    const imgTopPosition = imgElement.getBoundingClientRect().top;
    const imgOffsetTop = imgElement.offsetTop;
    const windowScrollY = window.scrollY;
    const documentClientTop =
      document.documentElement.clientTop || document.body.clientTop || 0;

    // Log the properties
    console.log('Image Element getBoundingClientRect().top:', imgTopPosition);
    console.log('Image Element offsetTop:', imgOffsetTop);
    console.log('Window scrollY:', windowScrollY);
    console.log('Document clientTop:', documentClientTop);

    return window.scrollY + imgTopPosition;
  }

  showCorner(event: any) {
    // Calculate and apply scaling
    this.calculateAndApplyScaling();

    // Use the scaled coordinates
    this.coordinateX = event.coordinates[0].xposition;
    const offsetY = this.calculateOffset();
    this.coordinateY = event.coordinates[0].yposition + offsetY - 15;

    // Log coordinates to console
    console.log('Selected Coordinates:', this.coordinateX, this.coordinateY);

    // Update the border element
    this.updateBorderElement();
  }

  private calculateAndApplyScaling() {
    const imgElement = this.imgElementRef.nativeElement as HTMLImageElement;
    const currentWidth = imgElement.clientWidth;
    const currentHeight = imgElement.clientHeight;

    console.log(
      'Image Current Width:',
      currentWidth,
      'Current Height:',
      currentHeight
    );

    // Use naturalWidth and naturalHeight properties
    const originalWidth = imgElement.naturalWidth;
    const originalHeight = imgElement.naturalHeight;

    const scaleX = currentWidth / originalWidth;
    const scaleY = currentHeight / originalHeight;

    console.log('Scale Factor X:', scaleX, 'Scale Factor Y:', scaleY);

    // Apply scale factors to each original coordinate
    this.columns.forEach((column, index) => {
      column.coordinates.forEach((coordinate, coordIndex) => {
        const originalCoordinate =
          this.originalCoordinates[index].coordinates[coordIndex];
        coordinate.xposition = originalCoordinate.xposition * scaleX;
        coordinate.yposition = originalCoordinate.yposition * scaleY;

        console.log(
          `Original Coordinates: (${originalCoordinate.xposition}, ${originalCoordinate.yposition}), Scaled Coordinates: (${coordinate.xposition}, ${coordinate.yposition})`
        );
      });
    });
  }

  private updateBorderElement() {
    const recElement = document.getElementById('rec1') as HTMLElement;
    if (recElement) {
      recElement.style.border = '2px solid red';
      recElement.style.width = '25px';
      recElement.style.height = '25px';
      recElement.style.left = this.coordinateX + 'px';
      recElement.style.top = this.coordinateY + 'px';

      console.log(
        'Border Element Updated:',
        `Left: ${this.coordinateX}px, Top: ${this.coordinateY}px`
      );
    }
  }

  addBorder(event: any) {
    console.log('Add Border Event:', event);
    const e = event.target.getBoundingClientRect();
    console.log('Bounding Client Rect:', e);
    const xClientH = event.screenY;
    const xClientY = event.screenX;

    this.coordinateX = xClientY;
    this.coordinateY = xClientH;
    console.log(
      'Coordinates from Event:',
      `X: ${this.coordinateX}, Y: ${this.coordinateY}`
    );

    const recElement = document.getElementById('rec1') as HTMLInputElement;
    if (recElement) {
      recElement.innerHTML =
        "<img src='../../assets/flow-editor/Image/rec.gif' style='width:25px; height:25px;'></img>";
    }
  }
}

The idea it is to select on image and then to create the border exactly the same what is being added when we select a row on table.