170 lines
4.5 KiB
Vue
170 lines
4.5 KiB
Vue
<template>
|
|
<div ref="chart" class="chart-container"></div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted, watch, nextTick } from 'vue';
|
|
import * as echarts from 'echarts';
|
|
|
|
interface HistoryItem {
|
|
ts: number;
|
|
currentDis: number;
|
|
dphi_deg: number;
|
|
amp2_pp_adc: number;
|
|
f0_hz: number;
|
|
[key: string]: any;
|
|
}
|
|
|
|
const props = defineProps<{
|
|
data: HistoryItem[];
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'select', index: number): void;
|
|
}>();
|
|
|
|
const chart = ref<HTMLElement | null>(null);
|
|
let chartInstance: echarts.ECharts | null = null;
|
|
|
|
const initChart = () => {
|
|
if (chart.value && !chartInstance) {
|
|
chartInstance = echarts.init(chart.value);
|
|
chartInstance.on('click', (params) => {
|
|
if (params.dataIndex !== undefined) {
|
|
emit('select', params.dataIndex);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
const updateChart = () => {
|
|
if (!chartInstance) return;
|
|
|
|
const dataPhase = props.data.map(item => [(item.currentDis / 1600).toFixed(3), item.dphi_deg]);
|
|
const dataP2P = props.data.map(item => [(item.currentDis / 1600).toFixed(3), item.amp2_pp_adc]);
|
|
|
|
const option = {
|
|
animation: false,
|
|
legend: {
|
|
data: ['相位差 (Deg)', '峰峰值 (ADC)'],
|
|
show: true,
|
|
top: 0,
|
|
left: 'center',
|
|
textStyle: { color: '#333' }
|
|
},
|
|
grid: {
|
|
show: true,
|
|
backgroundColor: '#fff',
|
|
borderColor: '#333',
|
|
borderWidth: 1,
|
|
left: '8%',
|
|
right: '8%',
|
|
bottom: '10%',
|
|
top: '24',
|
|
containLabel: false
|
|
},
|
|
tooltip: {
|
|
trigger: 'axis',
|
|
showContent: false,
|
|
axisPointer: { type: 'cross' }
|
|
},
|
|
xAxis: {
|
|
type: 'category',
|
|
name: '距离 (mm)',
|
|
nameLocation: 'middle',
|
|
nameGap: 3,
|
|
nameTextStyle: { color: '#333', fontSize: 12 },
|
|
axisTick: { show: true, alignWithLabel: true },
|
|
axisLine: { show: true, lineStyle: { color: '#333' } },
|
|
axisLabel: { color: '#333' },
|
|
splitLine: { show: true, lineStyle: { color: '#ccc' } }
|
|
},
|
|
yAxis: [
|
|
{
|
|
type: 'value',
|
|
name: '相位差 (deg)',
|
|
nameLocation: 'middle',
|
|
nameGap: 45,
|
|
nameTextStyle: { color: '#333', fontSize: 12 },
|
|
position: 'left',
|
|
axisLine: { show: true, lineStyle: { color: '#333' } },
|
|
axisLabel: { color: '#333' },
|
|
splitLine: { show: true, lineStyle: { color: '#ccc' } }
|
|
},
|
|
{
|
|
type: 'value',
|
|
name: '峰峰值 (ADC)',
|
|
nameLocation: 'middle',
|
|
nameGap: 45,
|
|
nameTextStyle: { color: '#333', fontSize: 12 },
|
|
position: 'right',
|
|
axisLine: { show: true, lineStyle: { color: '#333' } },
|
|
axisLabel: { color: '#333' },
|
|
splitLine: { show: false }
|
|
}
|
|
],
|
|
series: [
|
|
{
|
|
name: '相位差 (Deg)',
|
|
type: 'line',
|
|
data: dataPhase,
|
|
yAxisIndex: 0,
|
|
smooth: 0.3,
|
|
symbol: 'circle',
|
|
symbolSize: 4,
|
|
itemStyle: { color: '#c23531' },
|
|
lineStyle: { color: '#c23531', width: 2 }
|
|
},
|
|
{
|
|
name: '峰峰值 (ADC)',
|
|
type: 'line',
|
|
data: dataP2P,
|
|
yAxisIndex: 1,
|
|
smooth: 0.3,
|
|
symbol: 'circle',
|
|
symbolSize: 4,
|
|
itemStyle: { color: '#2f4554' },
|
|
lineStyle: { color: '#2f4554', width: 2 }
|
|
}
|
|
]
|
|
};
|
|
|
|
chartInstance.setOption(option);
|
|
};
|
|
|
|
const showTip = (index: number) => {
|
|
if (!chartInstance) return;
|
|
chartInstance.dispatchAction({
|
|
type: 'showTip',
|
|
seriesIndex: 0,
|
|
dataIndex: index
|
|
});
|
|
};
|
|
|
|
onMounted(() => {
|
|
initChart();
|
|
window.addEventListener('resize', () => {
|
|
chartInstance?.resize();
|
|
});
|
|
if (props.data.length > 0) {
|
|
updateChart();
|
|
}
|
|
});
|
|
|
|
watch(() => props.data, () => {
|
|
nextTick(() => {
|
|
if (!chartInstance) initChart();
|
|
updateChart();
|
|
});
|
|
}, { deep: true });
|
|
|
|
defineExpose({ showTip });
|
|
</script>
|
|
|
|
<style scoped>
|
|
.chart-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
</style>
|