@giro3d/giro3d
Version:
A JS/WebGL framework for 3D geospatial data visualization
133 lines (110 loc) • 3.7 kB
text/typescript
/*
* Copyright (c) 2015-2018, IGN France.
* Copyright (c) 2018-2026, Giro3D team.
* SPDX-License-Identifier: MIT
*/
import type { ChartData, ScatterDataPoint } from 'chart.js';
import type GUI from 'lil-gui';
import type { WebGLInfo } from 'three';
import { Chart } from 'chart.js';
import type Instance from '../../core/Instance';
import ChartPanel, { pushTrim } from './ChartPanel';
const MAX_DATA_POINTS = 30;
class FrameDuration extends ChartPanel {
public render: typeof WebGLInfo.prototype.render;
public data: ChartData<'bar', ScatterDataPoint[], string>;
public chart: Chart;
public updateStart: number;
public renderStart: number;
public constructor(parentGui: GUI, instance: Instance) {
super(parentGui, instance, 'Frame duration (ms)');
this.render = instance.renderer.info.render;
const totalFrameLength = {
label: 'Total',
tension: 0.2,
data: [] as ScatterDataPoint[],
fill: false,
borderWidth: 2,
pointRadius: 0,
backgroundColor: '#FF000030',
borderColor: '#FF000080',
};
const renderTime = {
label: 'Render',
tension: 0.2,
data: [] as ScatterDataPoint[],
fill: false,
borderWidth: 2,
pointRadius: 0,
backgroundColor: '#0050FF30',
borderColor: '#0050FFFF',
};
const labels: string[] = [];
this.data = {
labels,
datasets: [renderTime, totalFrameLength],
};
this.chart = new Chart(this.ctx, {
type: 'bar',
data: this.data,
options: {
animation: false,
plugins: {
legend: {
display: true,
position: 'bottom',
},
title: {
display: true,
text: 'Frame duration (ms)',
},
},
scales: {
x: {
stacked: true,
display: 'auto',
bounds: 'data',
type: 'linear',
},
y: {
stacked: true,
bounds: 'data',
type: 'linear',
suggestedMin: 0,
ticks: {
precision: 0,
},
},
},
},
});
this.updateStart = -1;
this.renderStart = -1;
instance.addEventListener('update-start', () => {
this.updateStart = performance.now();
});
instance.addEventListener('update-end', e => {
const now = performance.now();
pushTrim(
totalFrameLength.data,
{ x: e.frame, y: now - this.updateStart },
MAX_DATA_POINTS,
);
pushTrim(labels, '', MAX_DATA_POINTS);
});
instance.addEventListener('before-render', () => {
this.renderStart = performance.now();
});
instance.addEventListener('after-render', e => {
const now = performance.now();
pushTrim(renderTime.data, { x: e.frame, y: now - this.renderStart }, MAX_DATA_POINTS);
});
}
public override updateValues(): void {
if (this.isClosed()) {
return;
}
this.chart.update();
}
}
export default FrameDuration;