feat(waveform): 添加趋势图动态线宽和平移功能

- 实现趋势图按可见点数动态计算线宽,避免大数据量线条过粗
- 新增平移工具支持图表区域拖拽浏览
- 优化数据缩放事件处理,提升图表交互体验
- 添加线宽分档规则配置,支持不同数据量级的显示优化
- 移除原有的光标测量和峰值定位功能
- 更新图表点击事件为数据缩放事件处理
This commit is contained in:
2026-05-07 11:16:51 +08:00
parent 2babe9d99d
commit 32f324909d
6 changed files with 235 additions and 168 deletions

View File

@@ -12,6 +12,10 @@ import * as echarts from 'echarts' // 全引入
// import 'echarts-liquidfill'
// import 'echarts/lib/component/dataZoom'
defineOptions({
name: 'LineChart'
})
const color = [
'var(--el-color-primary)',
'#07CCCA',
@@ -30,15 +34,72 @@ const chartRef = ref<HTMLDivElement>()
const props = defineProps(['options', 'isInterVal', 'pieInterVal', 'group'])
const emit = defineEmits<{
'chart-click': [
'chart-data-zoom': [
value: {
timeLabel: string
value: number
seriesName: string
start: number
end: number
}
]
}>()
let chart: echarts.ECharts | any = null
let isPanPointerDown = false
const getChartViewportRoot = () => chart?.getZr()?.painter?.getViewportRoot?.() as HTMLElement | undefined
const resetChartCursor = () => {
const viewportRoot = getChartViewportRoot()
if (viewportRoot) viewportRoot.style.cursor = ''
isPanPointerDown = false
}
const updatePanCursor = (event: { offsetX: number; offsetY: number }) => {
const viewportRoot = getChartViewportRoot()
if (!viewportRoot || props.options?.activeTool !== 'pan') {
resetChartCursor()
return
}
// 平移只在图形绘图区内生效,鼠标样式同步限制到同一范围,避免坐标轴和空白区误导操作。
const isInGrid = chart?.containPixel?.({ gridIndex: 0 }, [event.offsetX, event.offsetY])
viewportRoot.style.cursor = isInGrid ? (isPanPointerDown ? 'grabbing' : 'grab') : ''
}
const bindPanCursorEvents = () => {
const zr = chart?.getZr?.()
if (!zr) return
zr.off('mousemove', updatePanCursor)
zr.off('mousedown', handlePanCursorMouseDown)
zr.off('mouseup', handlePanCursorMouseUp)
zr.off('globalout', resetChartCursor)
zr.on('mousemove', updatePanCursor)
zr.on('mousedown', handlePanCursorMouseDown)
zr.on('mouseup', handlePanCursorMouseUp)
zr.on('globalout', resetChartCursor)
}
const unbindPanCursorEvents = () => {
const zr = chart?.getZr?.()
if (!zr) return
zr.off('mousemove', updatePanCursor)
zr.off('mousedown', handlePanCursorMouseDown)
zr.off('mouseup', handlePanCursorMouseUp)
zr.off('globalout', resetChartCursor)
resetChartCursor()
}
function handlePanCursorMouseDown(event: { offsetX: number; offsetY: number }) {
isPanPointerDown = true
updatePanCursor(event)
}
function handlePanCursorMouseUp(event: { offsetX: number; offsetY: number }) {
isPanPointerDown = false
updatePanCursor(event)
}
const resizeHandler = () => {
// 不在视野中的时候不进行resize
if (!chartRef.value) return
@@ -51,6 +112,7 @@ const resizeHandler = () => {
}
const initChart = () => {
if (!props.isInterVal && !props.pieInterVal) {
unbindPanCursorEvents()
chart?.dispose()
}
// chart?.dispose()
@@ -128,6 +190,15 @@ const initChart = () => {
end: 100
}
],
toolbox: {
show: false,
feature: {
dataZoom: {
yAxisIndex: 'none'
}
},
...(props.options?.toolbox || null)
},
color: props.options?.color || color,
series: props.options?.series,
...props.options?.options
@@ -136,16 +207,17 @@ const initChart = () => {
handlerBar(options)
chart.setOption(options, true)
chart.off('click')
chart.on('click', (params: any) => {
const value = Array.isArray(params.value) ? params.value[1] : params.value
chart.off('datazoom')
chart.on('datazoom', (params: any) => {
const zoomPayload = Array.isArray(params.batch) ? params.batch[0] : params
const start = Number(zoomPayload?.start)
const end = Number(zoomPayload?.end)
if (params.componentType !== 'series' || !Number.isFinite(Number(value))) return
if (!Number.isFinite(start) || !Number.isFinite(end)) return
emit('chart-click', {
timeLabel: `${params.name ?? params.dataIndex ?? ''}`,
value: Number(value),
seriesName: `${params.seriesName || ''}`
emit('chart-data-zoom', {
start,
end
})
})
chart.dispatchAction({
@@ -153,6 +225,7 @@ const initChart = () => {
key: 'dataZoomSelect',
dataZoomSelectActive: props.options?.activeTool === 'box-zoom'
})
bindPanCursorEvents()
setTimeout(() => {
chart.resize()
@@ -268,14 +341,14 @@ const handlerXAxis = () => {
let throttle: ReturnType<typeof setTimeout>
// 动态计算table高度
const resizeObserver = new ResizeObserver(entries => {
for (const entry of entries) {
if (throttle) {
clearTimeout(throttle)
}
throttle = setTimeout(() => {
resizeHandler()
}, 100)
if (!entries.length) return
if (throttle) {
clearTimeout(throttle)
}
throttle = setTimeout(() => {
resizeHandler()
}, 100)
})
onMounted(() => {
initChart()
@@ -284,11 +357,12 @@ onMounted(() => {
defineExpose({ initChart })
onBeforeUnmount(() => {
resizeObserver.unobserve(chartRef.value!)
unbindPanCursorEvents()
chart?.dispose()
})
watch(
() => props.options,
(newVal, oldVal) => {
() => {
initChart()
}
)