Add statistics panel
This commit is contained in:
		
							parent
							
								
									2dbbd0952a
								
							
						
					
					
						commit
						4ea3c9e1f4
					
				| @ -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<IStatisticsProps & IMixinStatusProps & IMixinSettingProps> { | ||||
| 
 | ||||
|     public barDarkOption = { | ||||
| @ -85,13 +87,121 @@ class Statistics extends Component<IStatisticsProps & IMixinStatusProps & IMixin | ||||
|         /> | ||||
|     } | ||||
| 
 | ||||
|     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 <Message i18nKey="Panel.Info.Statistics.Nodata"/> | ||||
|         } | ||||
| 
 | ||||
|         return <Bar | ||||
|             data={{datasets, labels}} | ||||
|             options={ theme ? this.barLightOption : this.barDarkOption } | ||||
|         /> | ||||
|     } | ||||
| 
 | ||||
|     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 <Message i18nKey="Panel.Info.Statistics.Nodata"/> | ||||
|         } | ||||
| 
 | ||||
|         return <Line | ||||
|             options={ theme ? this.lineLightOption : this.lineDarkOption } | ||||
|             data={{labels, datasets:[{data: [1], }] }} | ||||
|         />; | ||||
|     } | ||||
| 
 | ||||
|     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<IStatisticsProps & IMixinStatusProps & IMixin | ||||
|             this.props.status?.actuator.mod === ActuatorModel.Record || | ||||
| 			this.props.status?.actuator.mod === ActuatorModel.Offline | ||||
|         ) { | ||||
|             if (this.props.status.actuator.recordClip && lineChartType) { | ||||
|                 return this.clipLineChart(this.props.status.actuator.recordClip, themes); | ||||
|             } | ||||
|             return this.modelBarChart(this.props.status.model, themes); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user