javascript 选择图像上特定区域的x和y,并在其上创建边框

eni9jsuy  于 11个月前  发布在  Java
关注(0)|答案(1)|浏览(155)

我有一个基于选择图像的问题。我有一个来自BE的对象数组,每个Obj都有自己的坐标,这取决于图像的X和Y。Image在那里有一些绘图,并包括一些数字。因此Obj上的属性itemNumber与img中显示的数字相同。例如,如果itemNumber为1,则坐标为数字1将是与图像接壤。
到目前为止,我已经取得了一些成就,但我不能选择正确的X和Y每次它是去其他地方的边界。
我创建了一个Stackblitz
在stackblitz你可以找到2个img的。在第二个你会如何它应该是。我尝试了很多事情,但不成功
这是我的Obj json。

[
 {
        "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
            }
        ]
    },
 ]`

字符串
这是我的TS代码。

showCorner(event: ResponseList) {
console.log(event.coordinates)

const xClientHeight = document.getElementById('imgPath')?.clientHeight as number;
const xClientWidth = document.getElementById('imgPath')?.clientWidth as number;

console.log(xClientHeight);
console.log(xClientWidth);

this.coordinateX =  xClientWidth - event.coordinates[0].yposition;
this.coordinateY = xClientHeight - event.coordinates[0].xposition;


(document.getElementById('rec1') as HTMLInputElement).innerHTML = "<img src='../../../assets/rec.gif'  style='width:25px; height:25px;'></img>";

}

showImage(imagePath: string) {
return this.environment.endpoints.backendBaseUrl + imagePath; // 
imagePath
}


我的HTML代码

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

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


正如你可以看到在图像中有数字。当你点击表中的每个数字将被选中。

rsl1atfo

rsl1atfo1#

问题是,坐标来自后端,我不能改变他们,不知何故,我需要像你一样,因为你在img中看到有大约40个坐标为1图像,我有大约100图像,我不能他们手动
来自后端的img尺寸为1664 × 2344  
根据后端提供的信息,在组件中设置原始图像尺寸(1664x2344)。
根据前端当前显示的图像大小和原始尺寸计算缩放因子。将缩放应用于坐标:使用缩放因子调整从后端接收的坐标。我在这个stackblitz中调整了它们。
你的app.component.ts是:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
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();
  }

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

    // Use the scaled coordinates
    this.coordinateX = event.coordinates[0].xposition;
    this.coordinateY = event.coordinates[0].yposition + 80;

    // 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 / this.originalWidth;
    const scaleY = currentHeight / this.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>";
    }
  }
}

字符串
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>


请注意,我必须将任何资源路径从../assets/...调整到../../assets/...,以确保资源图像正确显示。

相关问题