diff --git a/source/Panel/Statistics/Statistics.tsx b/source/Panel/Statistics/Statistics.tsx index b8c64e4..230940f 100644 --- a/source/Panel/Statistics/Statistics.tsx +++ b/source/Panel/Statistics/Statistics.tsx @@ -3,15 +3,17 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; import { useSettingWithEvent, IMixinSettingProps, Themes } from "@Context/Setting"; import { Chart as ChartJS, CategoryScale, LinearScale, - BarElement, Tooltip, Legend + BarElement, Tooltip, Legend, Decimation, + PointElement, LineElement, Title } from 'chart.js'; -import { Bar } from 'react-chartjs-2'; +import { Bar, Line } from 'react-chartjs-2'; import { Theme } from "@Component/Theme/Theme"; import { Icon } from "@fluentui/react"; import { Model } from "@Model/Model"; import { Group } from "@Model/Group"; import { ActuatorModel } from "@Model/Actuator"; import { Message } from "@Input/Message/Message"; +import { Clip, IFrame } from "@Model/Clip"; import "./Statistics.scss"; ChartJS.register( @@ -19,19 +21,19 @@ ChartJS.register( LinearScale, BarElement, Tooltip, - Legend + Legend, + PointElement, + LineElement, + Title, + Decimation ); -enum ChartType { - -} - interface IStatisticsProps { } @useSettingWithEvent("themes", "language", "lineChartType") -@useStatusWithEvent("focusClipChange", "actuatorStartChange", "fileLoad", "modelUpdate", "individualChange") +@useStatusWithEvent("focusClipChange", "actuatorStartChange", "fileLoad", "modelUpdate", "recordLoop", "individualChange") class Statistics extends Component { public barDarkOption = { @@ -85,13 +87,121 @@ class Statistics extends Component } + private clipBarChart(frame: IFrame, theme: boolean) { + + const datasets: any[] = []; + const labels: any[] = ["Group"]; + + // 收集数据 + frame.commands.forEach((command) => { + let label = command.name; + let color = `rgb(${command.parameter?.color.map((v: number) => Math.floor(v * 255)).join(",")})`; + + if (command.type === "points") { + datasets.push({label, data: [(command.data?.length ?? 0) / 3], backgroundColor: color}); + } + }); + + if (datasets.length <= 0) { + return + } + + return + } + + public lineDarkOption = { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + position: 'bottom' as const, + labels: { boxWidth: 10, boxHeight: 10, color: 'rgba(255, 255, 255, .5)' }, + decimation: { enabled: true } + }, + decimation: { enabled: true, algorithm: "lttb" as const, samples: 100 } + }, + scales: { + x: { grid: { color: 'rgba(255, 255, 255, .2)' }, type: "linear", title: { color: 'rgba(255, 255, 255, .5)'} }, + y: { grid: { color: 'rgba(255, 255, 255, .2)', borderDash: [3, 3] }, title: { color: 'rgba(255, 255, 255, .5)'} } + } + }; + + public lineLightOption = { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + position: 'bottom' as const, + labels: { boxWidth: 10, boxHeight: 10, color: 'rgba(0, 0, 0, .5)' }, + }, + decimation: { enabled: true, algorithm: "lttb" as const, samples: 100 } + }, + scales: { + x: { grid: { color: 'rgba(0, 0, 0, .2)' }, title: { color: 'rgba(0, 0, 0, .5)'} }, + y: { grid: { color: 'rgba(0, 0, 0, .2)', borderDash: [3, 3] }, title: { color: 'rgba(0, 0, 0, .5)'} } + } + }; + + private clipLineChart(clip: Clip, theme: boolean) { + + type IDataSet = {label: string, data: number[], backgroundColor: string, id: string}; + const datasets: IDataSet[] = []; + const labels: number[] = []; + + // 收集数据 + clip.frames.forEach((frame) => { + labels.push(frame.process); + frame.commands.forEach((command) => { + + if (command.type !== "points") return; + + let findKey: IDataSet | undefined; + for (let i = 0; i < datasets.length; i++) { + if (datasets[i].id === command.id) { + findKey = datasets[i]; + break; + } + } + + if (findKey) { + findKey.data.push((command.data?.length ?? 0) / 3); + } else { + findKey = {} as any; + findKey!.data = [(command.data?.length ?? 0) / 3]; + findKey!.label = command.name ?? ""; + findKey!.backgroundColor = `rgb(${command.parameter?.color.map((v: number) => Math.floor(v * 255)).join(",")})`; + findKey!.id = command.id; + datasets.push(findKey!); + } + }) + }); + + if (datasets.length <= 0) { + return + } + + return ; + } + private renderChart() { let themes = this.props.setting?.themes === Themes.light; + let lineChartType = this.props.setting?.lineChartType; // 播放模式 if (this.props.status?.focusClip) { - return this.modelBarChart(this.props.status.model, themes); + if (this.props.status.actuator.playClip && lineChartType) { + return this.clipLineChart(this.props.status.actuator.playClip, themes); + } + if (this.props.status.actuator.playFrame) { + return this.clipBarChart(this.props.status.actuator.playFrame, themes); + } } // 正在录制中 @@ -99,6 +209,9 @@ class Statistics extends Component