0

我正在使用Angular 8

我有一个canvas元素必须显示在父组件内的不同子组件中,但其上的数据应该相同。

为了解决这种情况,我ng-content在子组件中使用了

组件AB具有 HTML 包含

<div class="child">
  <ng-content select=["canvasPreview]"></ng-content>
</div>

而且ParentComponent

 <mat-horizontal-stepper labelPosition="bottom" #stepper (selectionChange)="onSelectionChange($event)">

  <mat-step>
      <ng-template matStepLabel>Upload Image</ng-template>

      <app-upload-background-image
        [(previewImage)]="previewImage"
        (previewImageChange)="onPreviewImageChange($event)">
      </app-upload-background-image>

  </mat-step>

  <mat-step>
      <ng-template matStepLabel>Place Canvas A</ng-template>

      <app-a>
        <div canvasPreview *ngTemplateOutlet="canvas"></div>
      </app-a>
  </mat-step>

  <mat-step>
    <ng-template matStepLabel>Design Canvas B</ng-template>

    <app-b>
      <div canvasPreview *ngTemplateOutlet="canvas"></div>
    </app-b>
  </mat-step>

</mat-horizontal-stepper>

<ng-template #canvas>
   <app-canvas-child></app-canvas-child>
</ng-template>

app-canvas-child组件具有canvas元素

canvas-child.component.html

<div class="title">Canvas Success</div>

<canvas height="400" width="500">

但是在Parent组件中,它从组件显示Canvas Success标题app-canvas-child,但画布区域是空白的。直接在父组件中使用相同(在 ng-template 之外)可以正常工作并显示画布。

4

2 回答 2

0

我认为会出现这个问题,因为内容投影的角度克隆元素。 如果一个画布节点被克隆它的上下文,它就丢失了。在您的情况下,您必须提供父组件的画布上下文。

堆栈闪电战: https ://stackblitz.com/edit/canvas-cloning-angular

应用组件:

import { Component, ViewChild, TemplateRef,ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('c',{static:false}) canvas;
  ctx

  constructor(private cdRef:ChangeDetectorRef) {

  }

  ngAfterViewInit() {
    const c = this.canvas.nativeElement
    this.ctx = c.getContext("2d");
    this.ctx.fillStyle = "#FF0000";
    this.ctx.fillRect(0, 0, 150, 75);
    this.cdRef.detectChanges();
  }

  change() {
    console.log("ADS")
    this.ctx.fillStyle = "#FFff00";
    this.ctx.fillRect(0, 0, 150, 75);
    this.canvas = { ... this.canvas }
  }
}

AppComponent-tpl:

<h1>In Parent:</h1>
<canvas #c width="200" height="100"></canvas>

<child [canvasAAA]="canvas"></child>
<child [canvasAAA]="canvas"></child>
<child [canvasAAA]="canvas"></child>
<button (click)="change()">change</button>

子组件:

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

@Component({
  selector: 'child',
  template: `<h2>In Child</h2><canvas #c width="200" height="100"></canvas><hr>`,
})
export class ChildComponent  {
  @Input() canvasAAA;
  @ViewChild('c',{static:false}) c;

  ngOnChanges(){
    if(!this.c || !this.canvasAAA){
      return;
    }
    console.log(this.canvasAAA)
    var context = this.c.nativeElement.getContext('2d');

    //set dimensions
    this.c.nativeElement.width = this.canvasAAA.nativeElement.width;
    this.c.nativeElement.height = this.canvasAAA.nativeElement.height;

    //apply the old canvas to the new one
    context.drawImage(this.canvasAAA.nativeElement, 0, 0);

  }
}
于 2019-12-26T18:13:14.723 回答
0

我想你必须使用ngProjectAs. 我已经写了一篇关于它的文章。

你应该像这样修改你的代码:

  <mat-step>
      <ng-template matStepLabel>Place Canvas A</ng-template>

      <app-a>
        <div ngProjectAs="[canvasPreview]" *ngTemplateOutlet="canvas"></div>
      </app-a>
  </mat-step>

  <mat-step>
    <ng-template matStepLabel>Design Canvas B</ng-template>

    <app-b>
      <div ngProjectAs="[canvasPreview]" *ngTemplateOutlet="canvas"></div>
    </app-b>
  </mat-step>
于 2019-12-26T18:33:47.057 回答