Linked backend data to detectors' meshes.
This commit is contained in:
@@ -13,33 +13,51 @@ interface AreaChartProps {
|
||||
data?: ChartDataPoint[]
|
||||
}
|
||||
|
||||
const AreaChart: React.FC<AreaChartProps> = ({ className = '' }) => {
|
||||
const AreaChart: React.FC<AreaChartProps> = ({ className = '', data }) => {
|
||||
const width = 635
|
||||
const height = 200
|
||||
const paddingBottom = 20
|
||||
const baselineY = height - paddingBottom
|
||||
const maxPlotHeight = height - 40
|
||||
|
||||
const safeData = (Array.isArray(data) && data.length > 0)
|
||||
? data
|
||||
: [
|
||||
{ value: 5 },
|
||||
{ value: 3 },
|
||||
{ value: 7 },
|
||||
{ value: 2 },
|
||||
{ value: 6 },
|
||||
{ value: 4 },
|
||||
{ value: 8 }
|
||||
]
|
||||
|
||||
const maxVal = Math.max(...safeData.map(d => d.value || 0), 1)
|
||||
const stepX = safeData.length > 1 ? width / (safeData.length - 1) : width
|
||||
|
||||
const points = safeData.map((d, i) => {
|
||||
const x = i * stepX
|
||||
const y = baselineY - (Math.min(d.value || 0, maxVal) / maxVal) * maxPlotHeight
|
||||
return { x, y }
|
||||
})
|
||||
|
||||
const linePath = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ')
|
||||
const areaPath = `${linePath} L${width},${baselineY} L0,${baselineY} Z`
|
||||
|
||||
return (
|
||||
<div className={`w-full h-full ${className}`}>
|
||||
<svg className="w-full h-full" viewBox="0 0 635 200">
|
||||
<svg className="w-full h-full" viewBox={`0 0 ${width} ${height}`}>
|
||||
<defs>
|
||||
<linearGradient id="areaGradient" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stopColor="rgb(42, 157, 144)" stopOpacity="0.3" />
|
||||
<stop offset="100%" stopColor="rgb(42, 157, 144)" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path
|
||||
d="M0,180 L100,120 L200,140 L300,80 L400,60 L500,100 L635,90 L635,200 L0,200 Z"
|
||||
fill="url(#areaGradient)"
|
||||
/>
|
||||
<path
|
||||
d="M0,180 L100,120 L200,140 L300,80 L400,60 L500,100 L635,90"
|
||||
stroke="rgb(42, 157, 144)"
|
||||
strokeWidth="2"
|
||||
fill="none"
|
||||
/>
|
||||
<circle cx="0" cy="180" r="3" fill="rgb(42, 157, 144)" />
|
||||
<circle cx="100" cy="120" r="3" fill="rgb(42, 157, 144)" />
|
||||
<circle cx="200" cy="140" r="3" fill="rgb(42, 157, 144)" />
|
||||
<circle cx="300" cy="80" r="3" fill="rgb(42, 157, 144)" />
|
||||
<circle cx="400" cy="60" r="3" fill="rgb(42, 157, 144)" />
|
||||
<circle cx="500" cy="100" r="3" fill="rgb(42, 157, 144)" />
|
||||
<circle cx="635" cy="90" r="3" fill="rgb(42, 157, 144)" />
|
||||
<path d={areaPath} fill="url(#areaGradient)" />
|
||||
<path d={linePath} stroke="rgb(42, 157, 144)" strokeWidth="2" fill="none" />
|
||||
{points.map((p, i) => (
|
||||
<circle key={i} cx={p.x} cy={p.y} r="3" fill="rgb(42, 157, 144)" />
|
||||
))}
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user