首页 > 解决方案 > Three.js 在动态 Angular 组件中渲染

问题描述

目前正在处理three.jsAngular 中动态创建的组件。静态(通过选择器)创建的 Plot3dComponent完美运行。但是当通过 ComponentFactoryResolver 动态创建它时,该组件不会渲染任何东西。还尝试添加一些延迟,setTimeout但我无法让它渲染任何东西。该save函数的图像输出只是一个具有所需宽度和高度的白色矩形,就像画布元素一样。你有什么想法?

我的模板渲染组件

<ng-container #plot3dref></ng-container>

缩小的组件类看起来像这样

@ViewChild('plot3dref', {read: ViewContainerRef}) plot3dref: ViewContainerRef;

save(geometry: Geometry) {
  const componentFactory = this.componentFactoryResolver.resolveComponentFactory(Plot3dComponent);
  const componentRef = this.plot3dref.createComponent(componentFactory);
  const instance = (<Plot3dComponent>componentRef.instance);

  instance.geometry = geometry;
  instance.materials = this.materials;
  instance.selectedBlock = -1;

  console.log(instance.save());
}, 100);

缩小的Plot3dComponent看起来像这样

@Component({
  selector: 'app-plot-3d',
  template: '<canvas #canvas></canvas>',
  styles: [`:host { width: 100%; } canvas { width: 100%; }`],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class Plot3dComponent implements OnInit, AfterViewInit, OnDestroy {
  @ViewChild('canvas') private canvasRef: ElementRef;
  @Input() geometry: Geometry;
  @Input() selectedBlock: number;
  @Input() materials: Material[];
  [...]

  ngOnInit() { this.render = this.render.bind(this); }
  save() { return this.canvasRef.nativeElement.toDataURL(); }

  ngAfterViewInit() {
    this.startRendering();
  }

  private startRendering() {
    this.renderer = new THREE.WebGLRenderer({
      canvas: this.canvas,
      antialias: true,
      preserveDrawingBuffer: true
    });

    const component: Plot3dComponent = this;

    (function render() {
      component.render();
    }());
  }
}

谢谢,干杯!

编辑:这个问题似乎也出现在@angular/materialmat-tab-groups。还在那里测试了固定高度。

标签: javascriptangulartypescriptthree.jsrendering

解决方案


实际上,它可以与静态和动态组件创建一起使用。使用工作示例创建了一个最小的stackblitz 。这是相关的代码片段。

export class DynamicComponent {
  @ViewChild('canvas') private canvasRef: ElementRef;
  [...]

  ngOnInit() {
    const renderer = new WebGLRenderer();
    renderer.setSize(200, 150);
    this.canvasRef.nativeElement.append(renderer.domElement);
    [...]
}

推荐阅读