我正在使用Angular 8
我有一个canvas
元素,它必须显示在父组件内的不同子组件中,但其上的数据应该是相同的。
为了解决这种情况,我在子组件中使用了ng-content
,例如
组件A和组件 B包含 HTML
<div class="child">
<ng-content select=["canvasPreview]"></ng-content>
</div>
父组件有
<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">
但在父组件中,它显示app-canvas-child
组件的画布成功标题,但画布区域为空白。直接在父组件中使用相同(在 ng 模板之外(工作正常并显示画布。
我认为会出现这个问题,因为内容投影的角度克隆元素。如果画布节点被克隆,则其上下文将丢失。在您的情况下,您必须提供父组件的画布上下文。
堆栈闪电战: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);
}
}
我认为你必须使用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>