From 73e0b3791990bd60c06c2c0388aae9f9faf538a6 Mon Sep 17 00:00:00 2001
From: zxl <763096477@qq.com>
Date: 星期三, 25 三月 2026 09:16:50 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/show-demo' into show_demo
---
src/views/dataAnalysis/components/DataReLineChart.vue | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 202 insertions(+), 0 deletions(-)
diff --git a/src/views/dataAnalysis/components/DataReLineChart.vue b/src/views/dataAnalysis/components/DataReLineChart.vue
index 782f712..857fd8d 100644
--- a/src/views/dataAnalysis/components/DataReLineChart.vue
+++ b/src/views/dataAnalysis/components/DataReLineChart.vue
@@ -22,13 +22,204 @@
type: Boolean,
default: false,
},
+ enablePointClick: {
+ type: Boolean,
+ default: false,
+ },
},
data() {
return {
chartEntity: null,
+ zrClickHandler: null,
+ zrMoveHandler: null,
+ zrMouseOutHandler: null,
+ lastHoverIndex: -1,
+ lastEmitName: '',
+ lastEmitAt: 0,
+ lastLegendToggleAt: 0,
}
},
methods: {
+ getOffsetPoint(event) {
+ if (!event) {
+ return null
+ }
+ if (event.offsetX !== undefined && event.offsetY !== undefined) {
+ return [event.offsetX, event.offsetY]
+ }
+ if (event.event && event.event.offsetX !== undefined && event.event.offsetY !== undefined) {
+ return [event.event.offsetX, event.event.offsetY]
+ }
+ return null
+ },
+ isPointInGrid(point) {
+ if (!this.chartEntity || !this.chartEntity.containPixel || !point) {
+ return false
+ }
+ return this.chartEntity.containPixel({ gridIndex: 0 }, point)
+ },
+ getXData() {
+ return this.chartData && this.chartData.xData ? this.chartData.xData : []
+ },
+ resolveNearestIndexByOffsetX(offsetX) {
+ let xData = this.getXData()
+ if (!this.chartEntity || !this.chartEntity.convertToPixel || !xData.length) {
+ return -1
+ }
+ let nearestIndex = -1
+ let minDistance = Number.MAX_VALUE
+ for (let i = 0; i < xData.length; i++) {
+ let xPixel = this.chartEntity.convertToPixel({ xAxisIndex: 0 }, xData[i])
+ if (Array.isArray(xPixel)) {
+ xPixel = xPixel[0]
+ }
+ if (xPixel === undefined || xPixel === null || Number.isNaN(Number(xPixel))) {
+ continue
+ }
+ let distance = Math.abs(Number(offsetX) - Number(xPixel))
+ if (distance < minDistance) {
+ minDistance = distance
+ nearestIndex = i
+ }
+ }
+ if (nearestIndex === -1) {
+ return -1
+ }
+ return nearestIndex
+ },
+ resolveClickIndex(event, params) {
+ let xData = this.getXData()
+ if (!xData.length) {
+ return -1
+ }
+ let point = this.getOffsetPoint(event)
+ if (!this.isPointInGrid(point)) {
+ return -1
+ }
+ if (params && typeof params.dataIndex === 'number' && xData[params.dataIndex] !== undefined) {
+ return params.dataIndex
+ }
+ if (params && params.name) {
+ let nameIndex = xData.findIndex((item) => item === params.name)
+ if (nameIndex > -1) {
+ return nameIndex
+ }
+ }
+ if (this.chartEntity && this.chartEntity.convertFromPixel && event) {
+ let xAxisValue = this.chartEntity.convertFromPixel({ xAxisIndex: 0 }, [event.offsetX, event.offsetY])
+ if (xAxisValue !== undefined && xAxisValue !== null && !Number.isNaN(Number(xAxisValue))) {
+ let xIndex = Math.round(Number(xAxisValue))
+ if (xIndex >= 0 && xIndex < xData.length) {
+ return xIndex
+ }
+ }
+ }
+ if (event && event.offsetX !== undefined && event.offsetX !== null) {
+ return this.resolveNearestIndexByOffsetX(event.offsetX)
+ }
+ return -1
+ },
+ emitChartClickByIndex(index, seriesName) {
+ let xData = this.getXData()
+ if (index < 0 || index >= xData.length) {
+ return
+ }
+ let clickName = xData[index]
+ let now = Date.now()
+ if (this.lastEmitName === clickName && now - this.lastEmitAt < 120) {
+ return
+ }
+ this.lastEmitName = clickName
+ this.lastEmitAt = now
+ this.$emit('chart-click', {
+ name: clickName,
+ seriesName: seriesName || null,
+ })
+ },
+ hideTooltip() {
+ if (!this.chartEntity) {
+ return
+ }
+ this.chartEntity.dispatchAction({
+ type: 'hideTip',
+ })
+ },
+ bindChartClick() {
+ if (!this.chartEntity) {
+ return
+ }
+ this.chartEntity.off('click')
+ if (this.chartEntity.getZr) {
+ let zr = this.chartEntity.getZr()
+ if (this.zrClickHandler) {
+ zr.off('click', this.zrClickHandler)
+ }
+ if (this.zrMoveHandler) {
+ zr.off('mousemove', this.zrMoveHandler)
+ }
+ if (this.zrMouseOutHandler) {
+ zr.off('globalout', this.zrMouseOutHandler)
+ }
+ }
+ if (!this.enablePointClick) {
+ let chartDom = document.getElementById(this.domId)
+ if (chartDom) {
+ chartDom.style.cursor = 'default'
+ }
+ return
+ }
+ let chartDom = document.getElementById(this.domId)
+ if (chartDom) {
+ chartDom.style.cursor = 'pointer'
+ }
+ this.chartEntity.on('legendselectchanged', () => {
+ this.lastLegendToggleAt = Date.now()
+ })
+ this.chartEntity.on('click', (params) => {
+ if (params && params.componentType === 'legend') {
+ return
+ }
+ if (Date.now() - this.lastLegendToggleAt < 180) {
+ return
+ }
+ let index = this.resolveClickIndex(params && params.event ? params.event : null, params)
+ this.emitChartClickByIndex(index, params ? params.seriesName : null)
+ })
+ this.zrMoveHandler = (event) => {
+ let xData = this.getXData()
+ if (!xData.length) {
+ return
+ }
+ let xIndex = this.resolveClickIndex(event, null)
+ if (xIndex < 0 || xIndex >= xData.length) {
+ return
+ }
+ if (this.lastHoverIndex === xIndex) {
+ return
+ }
+ this.lastHoverIndex = xIndex
+ this.chartEntity.dispatchAction({
+ type: 'showTip',
+ seriesIndex: 0,
+ dataIndex: xIndex,
+ })
+ }
+ this.zrMouseOutHandler = () => {
+ this.lastHoverIndex = -1
+ this.hideTooltip()
+ }
+ this.zrClickHandler = (event) => {
+ if (Date.now() - this.lastLegendToggleAt < 180) {
+ return
+ }
+ let index = this.resolveClickIndex(event, null)
+ this.emitChartClickByIndex(index, null)
+ }
+ let zr = this.chartEntity.getZr()
+ zr.on('mousemove', this.zrMoveHandler)
+ zr.on('globalout', this.zrMouseOutHandler)
+ zr.on('click', this.zrClickHandler)
+ },
setChart() {
if (!this.chartEntity) {
let chartDom = document.getElementById(this.domId)
@@ -38,6 +229,8 @@
var option = {
tooltip: {
trigger: 'axis',
+ confine: true,
+ extraCssText: 'pointer-events:none;',
axisPointer: {
// 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
type: 'line', // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
@@ -216,6 +409,7 @@
],
}
option && this.chartEntity.setOption(option, true)
+ this.bindChartClick()
},
setPieUpChart() {
if (!this.chartEntity) {
@@ -241,6 +435,8 @@
var option = {
tooltip: {
trigger: 'axis',
+ confine: true,
+ extraCssText: 'pointer-events:none;',
axisPointer: {
// 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
type: 'line', // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
@@ -299,6 +495,7 @@
series: [...data],
}
option && this.chartEntity.setOption(option, true)
+ this.bindChartClick()
},
setOnlyLineChart() {
if (!this.chartEntity) {
@@ -309,6 +506,8 @@
var option = {
tooltip: {
trigger: 'axis',
+ confine: true,
+ extraCssText: 'pointer-events:none;',
axisPointer: {
// 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
type: 'line', // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
@@ -442,6 +641,7 @@
],
}
option && this.chartEntity.setOption(option, true)
+ this.bindChartClick()
},
},
}
@@ -449,5 +649,7 @@
<style lang="less" scoped>
.line-chart {
height: 20vh;
+ position: relative;
+ overflow: hidden;
}
</style>
--
Gitblit v1.8.0