You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular生产构建开启脚本优化后Plotly 3D图形无法显示问题

问题:开启Angular生产环境脚本优化后Plotly 3D图形无法显示,提示WebGL不支持

当在angular.json中设置projects:app:architect:build:configurations:production:optimization:scripts为true时,3D图形无法显示,无报错信息,但页面显示替代提示:"WebGL is not supported by your browser - visit https://get.webgl.org for more info"。

模块代码

import * as PlotlyJS from 'plotly.js-dist-min';
import { PlotlyModule } from 'angular-plotly.js';

PlotlyModule.plotlyjs = PlotlyJS;

@NgModule({
  declarations: [
    AnalyticsVisualizationComponent,
    and another
  ],
  imports: [
    CommonModule,
    PlotlyModule,
    and another
  ],
})

组件代码

import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { Location } from '@angular/common';
import { PREDICTIONS_MOCK } from '@app/app/shared/mock/predictions.mock';
import { ActivatedRoute, Router } from '@angular/router';
import { AnalyticsService } from '@app/app/shared/services/dashboard/analytics.service';
import { Plotly } from 'angular-plotly.js/lib/plotly.interface';
import { LoadingService } from '@app/app/shared/services/app-state/loader.service';
import { finalize, takeUntil } from 'rxjs/operators';
import { PlotlyComponent } from 'angular-plotly.js';
import { Point } from 'plotly.js-dist-min';
import { AppStateService } from '@app/app/shared/services/app-state/app-state.service';
import { Subject } from 'rxjs';
import { ContrastService } from '@app/app/shared/services/settings/contrast.service';

@Component({
  selector: 'app-analytics-visualization',
  templateUrl: './analytics-visualization.component.html',
  styleUrls: ['./analytics-visualization.component.scss'],
})
export class AnalyticsVisualizationComponent implements OnInit, OnDestroy {

  @ViewChild('plot', { static: false }) public plot: PlotlyComponent;

  public graph: Plotly.Layout;
  public isActive = false;
  public minScale = 0.8;
  public maxScale = 3.5;
  public maxRadius = 6;
  public minRadius = 1.3;
  public graphName: {};
  public coords: { x: number, y: number, z: number };
  public items = PREDICTIONS_MOCK;

  private _destroy$ = new Subject<void>();

  constructor(
    private _route: ActivatedRoute,
    private _location: Location,
    private _router: Router,
    private _analyticsServices: AnalyticsService,
    private _loadingService: LoadingService,
    private _appStateService: AppStateService,
    private _contrastService: ContrastService,
  ) {
  }

  public ngOnInit(): void {
    this._loadingService.changeLoadingState(true);
    this._analyticsServices.getAnalytics3d_data()
      .pipe(finalize(() => this._loadingService.changeLoadingState(false)))
      .subscribe((res) => {
        const ret = res.replace('[NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]',
          '[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]');
        this.graphName = JSON.parse(ret);
        this.isActive = true;
        this.onCreateGraph(this.graphName);
      });
    this._subscribeOnAccessibility();
  }

  public ngOnDestroy(): void {
    this._destroy$.next();
    this._destroy$.complete();
  }

  public onCreateGraph(name: {}): void {
    if (name) {
      this.graph = {
        data: [
          {
            opacity: 0.7,
            color: 'rgba(20, 121, 186, 1)',
            type: 'mesh3d',
            x: name[0].flat(),
            y: name[1].flat(),
            z: name[2].flat(),
          },
        ],
        width: 1000,
        height: 700,
        margin: {
          l: 0,
          r: 0,
          b: 50,
          t: 50,
        },
        scene: {
          camera: {
            eye: { ...this.coords },
          },
          xaxis: {
            title: 'X – Dates',
            gridcolor: this._contrastService.getPropertyValue('--light-black'),
          },
          yaxis: {
            title: 'Y – Maturities',
            gridcolor: this._contrastService.getPropertyValue('--light-black'),
          },
          zaxis: {
            title: 'Z – Spot yields',
            gridcolor: this._contrastService.getPropertyValue('--light-black'),
          },
        },
      };
    }
  }

  public onRelayout(event: { 'scene.camera': { eye: Point } }): void {
    this.coords = { ...event['scene.camera']?.eye };
    const dist = Math.sqrt(this.coords.x ** 2 + this.coords.y ** 2 + this.coords.z ** 2);
    if (dist <= this.maxRadius || dist >= this.minRadius) {
      this._minMaxRelayout(0, event['scene.camera']?.eye);
    }
    if (dist < this.minRadius) {
      this._minMaxRelayout(this.minScale);
    }
    if (dist > this.maxRadius) {
      this._minMaxRelayout(this.maxScale);
    }
  }

  private _minMaxRelayout(count: number, eye?: Point): void {
    this.graph.scene.camera.eye.x = count || eye.x;
    this.graph.scene.camera.eye.y = count || eye.y;
    this.graph.scene.camera.eye.z = count || eye.z;
    this.plot.updatePlot().then();
  }

  private _subscribeOnAccessibility(): void {
    this._appStateService.contrast
      .pipe(takeUntil(this._destroy$))
      .subscribe(() => this.onCreateGraph(this.graphName));
  }

}

模板代码

<div class="c-dashboard__ticket-details">
  <plotly-plot *ngIf="isActive" #plot [data]="graph.data" [layout]="graph" (relayout)="onRelayout($event)"></plotly-plot>
</div>

已尝试的解决方案

  • 通过脚本引入库
  • 将渲染方法放入runOutsideAngular()
  • 连接/断开zone
  • 排除组件构建
  • 开启浏览器硬件加速(Chrome 107.0.5304.89 64位,驱动已更新)

该问题仅在开启应用优化时出现,对应angular.json配置如下:

"optimization": {
  "scripts": true,
  "styles": true,
  "fonts": true
},
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,

期望

开启"optimization": {"scripts": true,"styles": true,"fonts": true}配置时,能正常显示3D图形。

内容的提问来源于stack exchange,提问作者Александр Нестеров

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 08:20:32