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.