Javascript 画布中图像的放大和缩小问题
当我尝试放大和缩小画布图像时,我遇到了问题 其目的是允许用户在图像上绘制矩形。我使用画布来显示图像,然后在图像上绘制矩形,这很好。但现在我正在尝试添加放大和缩小功能。我面临以下问题: 当我放大或缩小时,我需要将矩形保持在与图像相同的位置。矩形保持在相同的坐标位置,但随着图像的移动,矩形中的图像部分已更改。如何在放大/缩小后保持矩形覆盖图像的相同部分 我是画布新手,不知道如何让它工作 以下是我遇到问题的组件: tagger.component.htmlJavascript 画布中图像的放大和缩小问题,javascript,angular,typescript,canvas,html5-canvas,Javascript,Angular,Typescript,Canvas,Html5 Canvas,当我尝试放大和缩小画布图像时,我遇到了问题 其目的是允许用户在图像上绘制矩形。我使用画布来显示图像,然后在图像上绘制矩形,这很好。但现在我正在尝试添加放大和缩小功能。我面临以下问题: 当我放大或缩小时,我需要将矩形保持在与图像相同的位置。矩形保持在相同的坐标位置,但随着图像的移动,矩形中的图像部分已更改。如何在放大/缩小后保持矩形覆盖图像的相同部分 我是画布新手,不知道如何让它工作 以下是我遇到问题的组件: tagger.component.html <div class="ro
<div class="row">
<div class="text-image-content">
<div class="column1">
<div style="position: relative;">
<div *ngFor="let drawItem of drawItems; let i = index">
<input [ngStyle]="{'left':drawItem.x0 + 'px' , 'top': drawItem.y0 + 'px'}"
style="position: absolute; z-index: 999;" placeholder="Enter Object Name"
[(ngModel)]="drawItem.name" type="text">
<input [ngStyle]="{'left':drawItem.x0 + 'px' , 'top': drawItem.y0 + 'px'}"
style="position: absolute; z-index: 999;" type="button" value="X" (click)="delete(i)">
</div>
<canvas #layer1 id="layer1" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<div class="row">
</div>
</div>
</div>
</div>
<button class="zoomBtn" (click)="zoomIn()">Zoom in</button>
<button class="zoomBtn" (click)="zoomOut()">Zoom out</button>
<div class="column2">
<div *ngFor="let drawItem of originalItems; let i = index">
<div class="details">
<div >Name: {{drawItem.name | titlecase}} </div>
<div>({{drawItem.x0}}, {{drawItem.y0}} , {{drawItem.x0 + drawItem.x1}}, {{drawItem.y0 + drawItem.y1}})</div>
</div>
</div>
</div>
</div>
完整的代码可以在以下位置找到:
谢谢 在Zoomin或Zoomout函数中,减小或增大边界框的坐标值,即this.drawItems。这就可以了。我已经试过了,但我无法正确计算坐标。请制作一个单独的变量来存储固定值,并在单独的变量中更改值。感谢您的响应。我可以让它工作,但现在有一些其他问题。缩放后我无法绘制。请看这个问题:
import {
Component,
ViewChild,
Input,
Output,
OnInit,
EventEmitter,
ElementRef
} from '@angular/core';
@Component({
selector: "app-tagger",
templateUrl: "./tagger.component.html",
styleUrls: ["./tagger.component.scss"]
})
export class TaggerComponent implements OnInit {
name = "Angular";
constructor() { }
drawItems = []
originalItems = []
count = 0
@Input('CanvasHeight') CanvasHeight
@Input('CanvasWidth') CanvasWidth
@Output() selected = new EventEmitter();
taggedItem = ""
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("layer1", { 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("red", 0, 0, 1);
}
imageLoad() {
this.image = new Image();
this.image.src = "https://i.ibb.co/12TJSNy/patio.jpg";
this.image.onload = () => {
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("2d");
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("mousedown", (e) => {
this.isMoving = true
this.initX = e.offsetX;
this.initY = e.offsetY;
});
this.layer1CanvasElement.addEventListener("mouseup", (e) => {
this.isMoving = false
this.showInput = true
this.drawItems.push({
name: "",
x0: this.initX,
y0: this.initY,
x1: this.uniX,
y1: this.uniY
});
this.originalItems.push({
name: "",
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("red", e.offsetX - this.initX, e.offsetY - this.initY, 0);
this.uniX = undefined
this.uniY = undefined
});
}
this.layer1CanvasElement.addEventListener("mousemove", (e) => {
if (this.isMoving) {
parent.drawRect("red", e.offsetX - this.initX, e.offsetY - this.initY, 0);
}
});
this.drawRect("red", 0, 0, 1);
}
drawRect(color = "black", 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 < 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("zooming in")
this.scale /= this.scaleMultiplier;
this.showImage();
}
zoomOut(){
console.log("zooming out")
this.scale *= this.scaleMultiplier;
this.showImage();
}
}
.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: "";
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;
}