听力补偿新增左右耳曲线
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import * as echarts from "echarts";
|
||||
import {
|
||||
HEARING_FREQ_LABELS,
|
||||
buildHearingSplineSeries,
|
||||
} from "@/lib/hearingCurve";
|
||||
|
||||
const LEFT_COLOR = "rgb(0, 255, 246)";
|
||||
const RIGHT_COLOR = "#FF5A36";
|
||||
|
||||
type HearingCompensationChartProps = {
|
||||
left: number[];
|
||||
right: number[];
|
||||
leftLabel?: string;
|
||||
rightLabel?: string;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export default function HearingCompensationChart({
|
||||
left,
|
||||
right,
|
||||
leftLabel = "Left",
|
||||
rightLabel = "Right",
|
||||
className,
|
||||
}: HearingCompensationChartProps) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const chartRef = useRef<echarts.ECharts | null>(null);
|
||||
|
||||
const leftSeries = useMemo(() => buildHearingSplineSeries(left), [left]);
|
||||
const rightSeries = useMemo(() => buildHearingSplineSeries(right), [right]);
|
||||
|
||||
useEffect(() => {
|
||||
const el = containerRef.current;
|
||||
if (!el) return;
|
||||
|
||||
const option: echarts.EChartsOption = {
|
||||
animation: false,
|
||||
legend: {
|
||||
show: true,
|
||||
top: 8,
|
||||
data: [
|
||||
{
|
||||
name: leftLabel,
|
||||
icon: "circle",
|
||||
textStyle: { color: LEFT_COLOR },
|
||||
itemStyle: { color: LEFT_COLOR, borderColor: LEFT_COLOR },
|
||||
},
|
||||
{
|
||||
name: rightLabel,
|
||||
icon: "circle",
|
||||
textStyle: { color: RIGHT_COLOR },
|
||||
itemStyle: { color: RIGHT_COLOR, borderColor: RIGHT_COLOR },
|
||||
},
|
||||
],
|
||||
textStyle: { fontSize: 13 },
|
||||
},
|
||||
grid: {
|
||||
left: 48,
|
||||
right: 36,
|
||||
top: 48,
|
||||
bottom: 28,
|
||||
},
|
||||
graphic: [
|
||||
{
|
||||
type: "text",
|
||||
right: 10,
|
||||
bottom: 6,
|
||||
style: {
|
||||
text: "Hz",
|
||||
fill: "#999",
|
||||
fontSize: 14,
|
||||
},
|
||||
z: 100,
|
||||
},
|
||||
],
|
||||
xAxis: {
|
||||
type: "value",
|
||||
min: 0,
|
||||
max: HEARING_FREQ_LABELS.length - 1,
|
||||
interval: 1,
|
||||
axisLabel: {
|
||||
formatter: (value: number) => {
|
||||
const idx = Math.round(value);
|
||||
if (Math.abs(value - idx) > 1e-6) return "";
|
||||
return HEARING_FREQ_LABELS[idx] ?? "";
|
||||
},
|
||||
fontSize: 14,
|
||||
color: "#999",
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: { type: "solid", color: "#3A4348" },
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: { color: "#3A4348" },
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
min: -80,
|
||||
max: 0,
|
||||
interval: 10,
|
||||
name: "dB",
|
||||
nameLocation: "end",
|
||||
nameGap: 8,
|
||||
nameTextStyle: {
|
||||
color: "#999",
|
||||
fontSize: 14,
|
||||
align: "right",
|
||||
padding: [0, 8, 0, 0],
|
||||
},
|
||||
axisLabel: {
|
||||
fontSize: 14,
|
||||
color: "#999",
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: { type: "solid", color: "#3A4348" },
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: { color: "#3A4348" },
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: leftLabel,
|
||||
type: "line",
|
||||
data: leftSeries,
|
||||
showSymbol: false,
|
||||
smooth: false,
|
||||
lineStyle: { color: LEFT_COLOR, width: 2 },
|
||||
itemStyle: { color: LEFT_COLOR },
|
||||
},
|
||||
{
|
||||
name: rightLabel,
|
||||
type: "line",
|
||||
data: rightSeries,
|
||||
showSymbol: false,
|
||||
smooth: false,
|
||||
lineStyle: { color: RIGHT_COLOR, width: 2 },
|
||||
itemStyle: { color: RIGHT_COLOR },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (!chartRef.current) {
|
||||
chartRef.current = echarts.init(el, undefined, { renderer: "canvas" });
|
||||
}
|
||||
chartRef.current.setOption(option, true);
|
||||
|
||||
const onResize = () => chartRef.current?.resize();
|
||||
const ro = new ResizeObserver(onResize);
|
||||
ro.observe(el);
|
||||
window.addEventListener("resize", onResize);
|
||||
|
||||
return () => {
|
||||
ro.disconnect();
|
||||
window.removeEventListener("resize", onResize);
|
||||
};
|
||||
}, [leftSeries, rightSeries, leftLabel, rightLabel]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
chartRef.current?.dispose();
|
||||
chartRef.current = null;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={
|
||||
className
|
||||
?? "w-full h-[min(42vw,200px)] min-h-[140px] md:h-[260px] lg:h-[300px] rounded-lg bg-black/30"
|
||||
}
|
||||
aria-hidden
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user