9 changed files with 360 additions and 6 deletions
@ -0,0 +1,311 @@ |
|||
import { Line } from 'react-chartjs-2' |
|||
import { |
|||
Chart as ChartJS, |
|||
CategoryScale, |
|||
LinearScale, |
|||
PointElement, |
|||
LineElement, |
|||
Title, |
|||
Tooltip, |
|||
Legend |
|||
} from 'chart.js' |
|||
import { FileTextOutlined, ClockCircleOutlined, EyeOutlined } from '@ant-design/icons' |
|||
|
|||
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend) |
|||
|
|||
function randomAround(base, delta) { |
|||
return base + Math.round((Math.random() * 2 - 1) * delta) |
|||
} |
|||
|
|||
function getTimeLabels(count) { |
|||
const now = new Date() |
|||
return Array.from({ length: count }).map((_, i) => { |
|||
const d = new Date(now.getTime() - (count - 1 - i) * 2 * 1000) |
|||
return d.toTimeString().slice(0, 8) |
|||
}) |
|||
} |
|||
|
|||
function DeflectionCollection() { |
|||
const count = 10 |
|||
const targetCount = 5 // 支持多个target |
|||
|
|||
// 为每个target生成颜色 |
|||
const targetColors = [ |
|||
'rgba(75,192,192,1)', // 青色 |
|||
'rgba(255,99,132,1)', // 红色 |
|||
'rgba(54,162,235,1)', // 蓝色 |
|||
'rgba(255,206,86,1)', // 黄色 |
|||
'rgba(153,102,255,1)' // 紫色 |
|||
] |
|||
|
|||
// 生成多个target的数据 |
|||
const targetsData = Array.from({ length: targetCount }).map((_, targetIndex) => ({ |
|||
name: `Target ${targetIndex + 1}`, |
|||
color: targetColors[targetIndex % targetColors.length], |
|||
data: Array.from({ length: count }).map((_, i) => ({ |
|||
x: 350 + targetIndex * 50 + Math.sin(i * 0.5 + targetIndex) * 20 + randomAround(0, 3), |
|||
y: 50 + targetIndex * 20 + Math.cos(i * 0.3 + targetIndex) * 15 + randomAround(0, 2), |
|||
w: randomAround(125, 5), |
|||
h: randomAround(115, 5) |
|||
})) |
|||
})) |
|||
|
|||
const timeLabels = getTimeLabels(count) |
|||
|
|||
const dataY = { |
|||
labels: timeLabels, |
|||
datasets: targetsData.map((target) => ({ |
|||
label: `${target.name}`, |
|||
data: target.data.map((d) => d.y), |
|||
borderColor: target.color, |
|||
backgroundColor: target.color.replace('1)', '0.2)'), |
|||
tension: 0.3, |
|||
pointRadius: 3, |
|||
pointHoverRadius: 5 |
|||
})) |
|||
} |
|||
|
|||
const dataX = { |
|||
labels: timeLabels, |
|||
datasets: targetsData.map((target) => ({ |
|||
label: `${target.name}`, |
|||
data: target.data.map((d) => d.x), |
|||
borderColor: target.color, |
|||
backgroundColor: target.color.replace('1)', '0.2)'), |
|||
tension: 0.3, |
|||
pointRadius: 3, |
|||
pointHoverRadius: 5 |
|||
})) |
|||
} |
|||
|
|||
const options = { |
|||
responsive: true, |
|||
maintainAspectRatio: false, |
|||
plugins: { |
|||
legend: { |
|||
display: true, |
|||
labels: { |
|||
boxWidth: 8, |
|||
boxHeight: 8, |
|||
font: { |
|||
size: 10 |
|||
}, |
|||
padding: 5 |
|||
}, |
|||
position: 'top' |
|||
}, |
|||
title: { display: false } |
|||
}, |
|||
scales: { |
|||
x: { |
|||
title: { display: true, text: '时间' }, |
|||
ticks: { font: { size: 10 } } |
|||
}, |
|||
y: { |
|||
title: { display: true, text: '挠度值' }, |
|||
ticks: { font: { size: 10 } } |
|||
} |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<div |
|||
style={{ |
|||
height: 'calc(100vh - 100px)', |
|||
maxHeight: '100%', |
|||
display: 'flex', |
|||
overflow: 'hidden', |
|||
margin: '0', |
|||
boxSizing: 'border-box' |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
flex: 1, |
|||
minWidth: 0, |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
padding: '10px', |
|||
gap: '10px', |
|||
overflow: 'hidden' |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
flex: 1, |
|||
minHeight: 0, |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
overflow: 'hidden', |
|||
border: '1px solid var(--border-color)' |
|||
}} |
|||
> |
|||
<p style={{ margin: '0 0 5px 0', fontSize: '14px', fontWeight: '500' }}>Y方向曲线</p> |
|||
<div style={{ flex: 1, minHeight: 0, position: 'relative' }}> |
|||
<Line data={dataY} options={options} /> |
|||
</div> |
|||
</div> |
|||
<div |
|||
style={{ |
|||
flex: 1, |
|||
minHeight: 0, |
|||
display: 'flex', |
|||
flexDirection: 'column', |
|||
overflow: 'hidden', |
|||
border: '1px solid var(--border-color)' |
|||
}} |
|||
> |
|||
<p style={{ margin: '0 0 5px 0', fontSize: '14px', fontWeight: '500' }}>X方向曲线</p> |
|||
<div style={{ flex: 1, minHeight: 0, position: 'relative' }}> |
|||
<Line data={dataX} options={options} /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div |
|||
style={{ |
|||
width: '300px', |
|||
minWidth: '300px', |
|||
maxWidth: '300px', |
|||
margin: '10px', |
|||
padding: '10px', |
|||
border: '1px solid var(--border-color)', |
|||
overflow: 'auto', |
|||
boxSizing: 'border-box' |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
fontSize: '14px', |
|||
fontWeight: '600', |
|||
marginBottom: '10px', |
|||
color: '#333' |
|||
}} |
|||
> |
|||
实时数据 |
|||
</div> |
|||
|
|||
{targetsData.map((target, index) => { |
|||
const latestData = target.data[target.data.length - 1] |
|||
const latestTime = timeLabels[timeLabels.length - 1] |
|||
|
|||
return ( |
|||
<div |
|||
key={index} |
|||
style={{ |
|||
marginBottom: '15px', |
|||
padding: '10px', |
|||
backgroundColor: '#fafafa', |
|||
border: '1px solid #e8e8e8', |
|||
borderRadius: '4px' |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
display: 'flex', |
|||
alignItems: 'center', |
|||
marginBottom: '8px' |
|||
}} |
|||
> |
|||
<div |
|||
style={{ |
|||
width: '8px', |
|||
height: '8px', |
|||
backgroundColor: target.color, |
|||
borderRadius: '50%', |
|||
marginRight: '8px' |
|||
}} |
|||
></div> |
|||
<span |
|||
style={{ |
|||
fontSize: '14px', |
|||
fontWeight: '500', |
|||
color: '#333' |
|||
}} |
|||
> |
|||
测点位置:{index + 1} |
|||
</span> |
|||
</div> |
|||
|
|||
<div |
|||
style={{ |
|||
display: 'flex', |
|||
alignItems: 'center', |
|||
marginBottom: '5px' |
|||
}} |
|||
> |
|||
<FileTextOutlined style={{ fontSize: '12px', color: '#666' }} /> |
|||
<span |
|||
style={{ |
|||
fontSize: '12px', |
|||
color: '#666', |
|||
marginLeft: '5px' |
|||
}} |
|||
> |
|||
测点描述: |
|||
</span> |
|||
</div> |
|||
|
|||
<div |
|||
style={{ |
|||
display: 'flex', |
|||
alignItems: 'center', |
|||
marginBottom: '5px' |
|||
}} |
|||
> |
|||
<ClockCircleOutlined style={{ fontSize: '12px', color: '#666' }} /> |
|||
<span |
|||
style={{ |
|||
fontSize: '12px', |
|||
color: '#666', |
|||
marginLeft: '5px' |
|||
}} |
|||
> |
|||
采集时间:{new Date().toLocaleDateString()} {latestTime} |
|||
</span> |
|||
</div> |
|||
|
|||
<div |
|||
style={{ |
|||
display: 'flex', |
|||
alignItems: 'center', |
|||
marginBottom: '3px' |
|||
}} |
|||
> |
|||
<EyeOutlined style={{ fontSize: '12px', color: '#666' }} /> |
|||
<span |
|||
style={{ |
|||
fontSize: '12px', |
|||
color: '#333', |
|||
marginLeft: '5px' |
|||
}} |
|||
> |
|||
X → {latestData.x.toFixed(3)} |
|||
</span> |
|||
</div> |
|||
|
|||
<div |
|||
style={{ |
|||
display: 'flex', |
|||
alignItems: 'center' |
|||
}} |
|||
> |
|||
<EyeOutlined style={{ fontSize: '12px', color: '#666' }} /> |
|||
<span |
|||
style={{ |
|||
fontSize: '12px', |
|||
color: '#333', |
|||
marginLeft: '5px' |
|||
}} |
|||
> |
|||
Y → {latestData.y.toFixed(3)} |
|||
</span> |
|||
</div> |
|||
</div> |
|||
) |
|||
})} |
|||
</div> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default DeflectionCollection |
@ -0,0 +1,3 @@ |
|||
.chartContainer { |
|||
width: 100%; |
|||
} |
@ -0,0 +1,7 @@ |
|||
import React from 'react' |
|||
|
|||
function ImageCollection() { |
|||
return <div>ImageCollection</div> |
|||
} |
|||
|
|||
export default ImageCollection |
Loading…
Reference in new issue