gpt4 book ai didi

Angular 2+ 获取动态生成的 HTML 元素的引用以进行 Canvas 操作

转载 作者:行者123 更新时间:2023-12-02 18:28:10 25 4
gpt4 key购买 nike

我在 Angular 中提供了绘图服务,其中包含多种方法,这些方法采用各种与绘图相关的参数和一个引用 Canvas 元素动态生成的 Id 的参数,如此处的 drawLizard 方法:

绘图服务:

import { Injectable } from '@angular/core';
import { Genotype } from './genotype.model';

@Injectable({
providedIn: 'root'
})
export class DrawingService {
constructor() {
}

drawArc(x: number, y: number, radius: number, startAngle:number, endAngle: number, elementId: string, color: string, fillStatus: boolean) {
let canvas = <HTMLCanvasElement> document.getElementById(elementId);
// console.log(canvas); //TODO fix
if (canvas) {
let ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
if (fillStatus) {
ctx.fillStyle = color;
ctx.fill();
} else {
ctx.lineWidth = 1;
ctx.strokeStyle = color;
ctx.stroke();
}
} else {
//TODO handle error here
}
}

drawTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3:number, elementId: string, color: string, fillStatus: boolean){

// let canvasElementTest = <HTMLCanvasElement>document.getElementById("first");
// console.log(canvasElementTest); //TODO fix
let canvasElement = <HTMLCanvasElement>document.getElementById(elementId);
// let canvasElement: Element = <HTMLCanvasElement>document.getElementsByClassName(elementId);
console.log(canvasElement); //TODO fix
if (canvasElement){
let context = canvasElement.getContext("2d");
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.lineTo(x3, y3);
context.closePath();
context.lineWidth = 1;
context.strokeStyle = color;
context.stroke();
if(fillStatus){
context.fillStyle = color;
context.fill();
}
} else{
//TODO throw/handle error here
}
}

drawEllipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle:number, endAngle:number, elementId: string, color: string, fillStatus: boolean){
let canvas = <HTMLCanvasElement> document.getElementById(elementId);
if(canvas){
let ctx = canvas.getContext('2d');
// ctx.setLineDash([])
ctx.beginPath();
ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, false); //x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise
ctx.stroke();
if(fillStatus){
ctx.fillStyle = color;
ctx.fill();
}
ctx.closePath();
} else{
//TODO handle error here
}

}

drawLizard(canvasId: string, genotype: Genotype){
//head
this.drawTriangle(37.5,87.5,37.5,112.5,25,100, canvasId,"black", true);
this.drawArc(37.5, 100, 12.5, 3*Math.PI/2, Math.PI/2, canvasId,"black", true);
// console.log("mark got here, too"); //TODO fix

//eyes
this.drawArc(37.5, 106.25, 2, 0, 2*Math.PI, canvasId,"white", true);
this.drawArc(37.5, 93.75, 2, 0, 2*Math.PI, canvasId,"white", true);
this.drawArc(37.5, 106.25, 0.5, 0, 2*Math.PI, canvasId,"black", true);
this.drawArc(37.5, 93.75, 0.5, 0, 2*Math.PI, canvasId,"black", true);

//body
this.drawEllipse(100, 100, 50, 10, 0, 0, 2 * Math.PI, canvasId, 'black', true);

//legs
this.drawEllipse(140, 110, 30, 3, 0.65, 0, 2 * Math.PI, canvasId, 'black', true);
this.drawEllipse(140, 90, 30, 3, 0.9+Math.PI/2, 0, 2 * Math.PI, canvasId, 'black', true);
this.drawEllipse(70, 110, 30, 3, -Math.PI/6, 0, 2 * Math.PI, canvasId, 'black', true);
this.drawEllipse(70, 90, 30, 3, Math.PI/6, 0, 2 * Math.PI, canvasId, 'black', true);

//random polka dots
// let colorArray = new Array<string>("blue", "pink", "orange", "#FF00FF", "red", "#00FFFF", "#800000", "#00FF00", "#008000", "#00FFFF", "#008080", "#BFBFFE", "#800080");
// this.drawArc(77, 95, 3, 0, 2*Math.PI, canvasId, colorArray[Math.floor(Math.random()*colorArray.length)], true);

this.drawArc(60, 101, 3, 0, 2*Math.PI, canvasId, genotype.getAllele1(), true);
this.drawArc(85, 102, 3, 0, 2*Math.PI, canvasId, genotype.getAllele2(), true);
this.drawArc(109, 94, 3, 0, 2*Math.PI, canvasId, genotype.getAllele1(), true);
this.drawArc(120, 102, 3, 0, 2*Math.PI, canvasId, genotype.getAllele2(), true);
}
}

我在 lizard-display.component.html 中动态生成了几个这样的 Canvas 元素:

...
<mat-card small class="example-card" *ngFor="let individual of individuals; let i=index">
...
<canvas id="lizard-canvas{{i}}" width="200" height="200" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
...
</mat-card>
...

在我的 lizard-display.component.ts 文件中,我生成了一个示例蜥蜴并尝试绘制它:

import { OnInit, Component } from '@angular/core';
import { DrawingService } from '../drawing.service';
import { Genotype } from '../genotype.model';
import { Gene } from '../gene.model';
import { Organism } from '../organism.model';
import { ColorNameService } from '../color-name.service';
import { IndividualGenerationService } from '../individual-generation.service';

@Component({
selector: 'app-lizard-display',
templateUrl: './lizard-display.component.html',
styleUrls: ['./lizard-display.component.css'],
providers: [DrawingService]
})
export class LizardDisplayComponent implements OnInit {
private individuals: Array<Organism> = new Array<Organism>();

constructor(private ds: DrawingService, private cns: ColorNameService, private individualGenService: IndividualGenerationService) { }

ngOnInit() {

//TODO delete me after fleshed out more
let testIndividual: Organism = this.individualGenService.makeIndividual("green", "blue");
let genotype: Genotype = testIndividual.getGeneByName("spot color").getGenotype();
this.individuals.push(testIndividual);

this.ds.drawLizard('lizard-canvas0', genotype);
}
}

许多解决方案(例如 here )似乎都适合那些不必在其元素上应用 .getContext('2d') 的人。

事实上,我可以确认在 SO 上使用这些解决方案的 canvasElement(至少在绘图服务中 drawLizard 调用的 drawTriangle 方法中)是 null。

我希望能找到类似 Angular2+ 的解决方案来解决这个问题。

可以在这里找到一个实用的、相当最小的可重现示例:

git clone https://github.com/Atticus29/population-fragmentation.git
cd population-fragmentation
git checkout dynamicCanvasSO
npm install
ng serve

导航至http://localhost:4200/在浏览器中

最佳答案

获取 html 元素引用的 Angular 方法是使用 ViewChildren,如下所示:

export class LizardDisplayComponent implements OnInit, AfterViewInit {
@ViewChildren('canvases') canvases: QueryList<ElementRef>;
private individuals: Array<Organism> = new Array<Organism>();

constructor(private ds: DrawingService, private cns: ColorNameService, private individualGenService: IndividualGenerationService) { }

ngOnInit() { }

ngAfterViewInit() { // view children arent available till this hook
this.canvases.forEach(canvas => console.log(canvas));
//here you'll see each has a nativeElement property that is a reference to that element, you can theoretically pass that to your service to be drawn on, this is just looping over everything with the '#canvases' tag applied to it

let testIndividual: Organism = this.individualGenService.makeIndividual("green", "blue");
let genotype: Genotype = testIndividual.getGeneByName("spot color").getGenotype();
this.individuals.push(testIndividual);

//you can pass them to your service like this instead of the id
this.ds.drawLizard(this.canvases.toArray()[0], genotype);
}
}

viewchildren 装饰器基本上会查询组件以查找具有您在装饰器中指定的标签的任何元素,您可以在 HTML 中应用该标签,如下所示:

...
<mat-card small class="example-card" *ngFor="let individual of individuals; let i=index">
...
<canvas #canvases id="lizard-canvas{{i}}" width="200" height="200" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
...
</mat-card>
...

然后您可以将其传递给您的服务:

drawLizard(canvasRef: ElementRef, genotype: Genotype){
this.drawTriangle(37.5,87.5,37.5,112.5,25,100, canvasRef,"black", true);
...
}

drawTriangle(x1: number, y1: number, x2: number, y2: number, x3: number, y3:number, elementRef: ElementRef, color: string, fillStatus: boolean){
let canvasElement = <HTMLCanvasElement>elementRef.nativeElement;
...
}

关于Angular 2+ 获取动态生成的 HTML 元素的引用以进行 Canvas 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52289229/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com