feat(waveform): 添加趋势图动态线宽和平移功能
- 实现趋势图按可见点数动态计算线宽,避免大数据量线条过粗 - 新增平移工具支持图表区域拖拽浏览 - 优化数据缩放事件处理,提升图表交互体验 - 添加线宽分档规则配置,支持不同数据量级的显示优化 - 移除原有的光标测量和峰值定位功能 - 更新图表点击事件为数据缩放事件处理
This commit is contained in:
@@ -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()
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user