Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/91.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 放大/缩小(缩放)后无法在画布上正确绘制_Javascript_Html_Angular_Canvas_Html5 Canvas - Fatal编程技术网

Javascript 放大/缩小(缩放)后无法在画布上正确绘制

Javascript 放大/缩小(缩放)后无法在画布上正确绘制,javascript,html,angular,canvas,html5-canvas,Javascript,Html,Angular,Canvas,Html5 Canvas,缩放后我无法正确绘制 其目的是允许用户在图像上绘制矩形。我使用画布来显示图像,然后在图像上绘制矩形,这很好。但现在我正在尝试添加放大和缩小功能。我需要在放大/缩小后移动矩形,我能够正确地这样做 我有3个数组,保存矩形坐标: drawItems:绘制时的初始矩形坐标 currentItems:缩放以显示矩形后的坐标 originalItems:相对于原始图像大小而不是画布的坐标 当我缩放画布并尝试在特定位置绘制矩形时,由于某种原因,它会显示在其他位置 我是画布和棱角的新手,请告诉我哪里出了问题 t

缩放后我无法正确绘制

其目的是允许用户在图像上绘制矩形。我使用画布来显示图像,然后在图像上绘制矩形,这很好。但现在我正在尝试添加放大和缩小功能。我需要在放大/缩小后移动矩形,我能够正确地这样做

我有3个数组,保存矩形坐标:

  • drawItems:绘制时的初始矩形坐标
  • currentItems:缩放以显示矩形后的坐标
  • originalItems:相对于原始图像大小而不是画布的坐标
  • 当我缩放画布并尝试在特定位置绘制矩形时,由于某种原因,它会显示在其他位置

    我是画布和棱角的新手,请告诉我哪里出了问题

    tagger-component.ts

    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 = []
        currentItems = []
        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.9;
       
       
        public previousScale = 1.0;
    
        @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 ++;
            var s = Math.max(this.CanvasWidth / this.image.width, this.CanvasHeight / this.image.height);
            console.log(s)
            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
                var a = this.initX * this.scale
                var b = this.initY * this.scale
                var c = this.uniX * this.scale
                var d = this.uniY * this.scale
                console.log(this.initX,this.initY,this.uniX,this.uniY)
                console.log(a,b,c,d)
                this.drawItems.push({
                    name: "",
                    x0: a,
                    y0: b,
                    x1: c,
                    y1: d
                });
                 this.currentItems.push({
                    x0: a,
                    y0: b,
                    x1: c,
                    y1: d
                });
                this.originalItems.push({
                    name: "",
                    x0: Math.ceil(a * this.hRatio),
                    y0: Math.ceil(b * this.vRatio),
                    x1: Math.ceil(c *this.hRatio),
                    y1: Math.ceil(d * 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()
          }
          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.currentItems[i].x0,
                  this.currentItems[i].y0 ,
                  this.currentItems[i].x1 ,
                  this.currentItems[i].y1 
              );
              this.context.lineWidth = 3;
              this.context.strokeStyle = color;
              this.context.stroke();
          }
        }
        scaleUpBoundingBox(){
          for (var i = 0; i < this.drawItems.length; i++) {
            this.currentItems[i].x0 = this.drawItems[i].x0 * this.scale;
            this.currentItems[i].y0 = this.drawItems[i].y0 * this.scale;
            this.currentItems[i].x1 = this.drawItems[i].x1 * this.scale;
            this.currentItems[i].y1 = this.drawItems[i].y1 * this.scale;
          }
        }
    
        zoomIn(){
          console.log("zooming in")
          this.previousScale = this.scale
          this.scale /= this.scaleMultiplier;
          // console.log(this.previousScale,this. scale)
          this.scaleUpBoundingBox();
          this.showImage();
        }
        zoomOut(){
          console.log("zooming out")
          this.previousScale = this.scale
          this.scale *= this.scaleMultiplier;
          // console.log(this.previousScale,this. scale)
          this.scaleUpBoundingBox();
          this.showImage();  
        }
    }
    
    完整代码可在此处找到:

    <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 * scale + 'px' , 'top': drawItem.y0  *scale + '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>
    
    .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;
    }