fix(图表): 修复数据大屏缩放导致提示框位置偏移的问题,启动提示轮播后不使用自定义提示容器

This commit is contained in:
jianneng-fit2cloud
2025-10-31 18:32:38 +08:00
parent 118fa6e5b6
commit 97cb80f8b9
14 changed files with 98 additions and 62 deletions

View File

@@ -78,6 +78,7 @@ declare interface Chart {
fontFamily?: string
dashboardHidden?: boolean
inMobile?: boolean
[key: any]: any
}
declare type CustomAttr = DeepPartial<ChartAttr> | JSONString<DeepPartial<ChartAttr>>
declare type CustomStyle = DeepPartial<ChartStyle> | JSONString<DeepPartial<ChartStyle>>

View File

@@ -256,14 +256,8 @@ class G2TooltipCarousel {
if (!el) return false
// 检查可见比例
const rect = el.getBoundingClientRect()
let visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 60)
let visibleWidth = Math.min(rect.right, window.innerWidth) - Math.max(rect.left, 0)
const dvMainCenter = document.getElementById('dv-main-center')
if (dvMainCenter) {
const dvRect = dvMainCenter.getBoundingClientRect()
visibleHeight = Math.min(rect.bottom, dvRect.bottom) - Math.max(rect.top, dvRect.top)
visibleWidth = Math.min(rect.right, dvRect.right) - Math.max(rect.left, dvRect.left)
}
const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 60)
const visibleWidth = Math.min(rect.right, window.innerWidth) - Math.max(rect.left, 0)
const percentHeight = visibleHeight / rect.height
const percentWidth = visibleWidth / rect.width
return percentHeight > 0.7 && percentWidth > 0.7
@@ -445,7 +439,7 @@ class G2TooltipCarousel {
try {
const ctx = this.newChart.getContext()
const root = ctx.canvas.document.getElementsByClassName('plot')[0]
const { center } = root.getRenderBounds()
const { height } = root.getRenderBounds()
const scaleX = (this.newChart.getScale() || ctx.views[0].scale).x
const x =
tooltipData.data.data.x ||
@@ -456,8 +450,8 @@ class G2TooltipCarousel {
])
const { insetLeft, marginLeft, paddingLeft } = root.__data__
return {
offsetX: insetLeft + marginLeft + paddingLeft + x2,
offsetY: center[1]
offsetX: insetLeft + marginLeft + paddingLeft + x2 * this.chart.tScale,
offsetY: (height / 2) * this.chart.tScale
}
} catch (e) {
console.error('Get Tooltip offsetX fail:', e)

View File

@@ -25,6 +25,7 @@ import {
import {
createTooltipWrapper,
tooltipCss,
tooltipMaxHeight,
Transform,
ViewSpec
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
@@ -224,7 +225,7 @@ export class Bar extends G2ChartView<ViewSpec, G2Column> {
tooltip: {
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltipAttr),
enterable: false,
enterable: true,
shared: true,
position: 'top-right',
render: (_, { title, items: originalItems }) => {
@@ -263,7 +264,9 @@ export class Bar extends G2ChartView<ViewSpec, G2Column> {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -62,7 +62,8 @@ export function createTooltipWrapper(chart: Chart) {
g2TooltipWrapper.style.top = '0px'
document.body.appendChild(g2TooltipWrapper)
}
return g2TooltipWrapper
// 如果开启轮播则不使用自定义tooltip容器
return chart.customAttr?.tooltip?.carousel?.enable ? undefined : g2TooltipWrapper
}
export function tooltipCss(tooltipAttr: DeepPartial<ChartTooltipAttr>) {
@@ -88,24 +89,39 @@ export function tooltipCss(tooltipAttr: DeepPartial<ChartTooltipAttr>) {
}
}
/**
* 计算 tooltip 最大高度
* 最大高度为图表高度-20px
* @param chart
*/
export function tooltipMaxHeight(chart: Chart) {
const chartContainer = document.getElementById(chart.container)
const defaultHeight = 80
const maxHeight = chartContainer
? Math.max(chartContainer.getBoundingClientRect().height - 20, defaultHeight)
: defaultHeight
return `max-height: ${maxHeight}px;`
}
export function listenerTooltipShow(newChart: G2Chart, chart: Chart) {
newChart.on('tooltip:show', event => {
const tooltipWrapper = document.getElementById(tooltipWrapperId(chart.container))
if (tooltipWrapper) {
tooltipWrapper.style.zIndex = chart.container.indexOf('viewDialog') > -1 ? '9999' : '2000'
const allTooltips = tooltipWrapper?.querySelectorAll('.g2-tooltip')
if (!allTooltips) return
allTooltips.forEach(item => {
const tooltip = item as HTMLElement
tooltip.style.visibility = 'visible'
if (event?.offsetY) {
const { top, height } = newChart
?.getContext()
?.canvas?.context?.contextService?.$container?.getBoundingClientRect()
if (top) {
tooltip.style.top = top + height / 2 - tooltip.getBoundingClientRect().height / 2 + 'px'
}
}
const isCarousel = chart.customAttr?.tooltip?.carousel?.enable
const tooltipWrapper = isCarousel
? document.getElementById(chart.container)
: document.getElementById(tooltipWrapperId(chart.container))
if (!tooltipWrapper) return
tooltipWrapper.style.zIndex = chart.container.indexOf('viewDialog') > -1 ? '9999' : '2000'
const allTooltips = tooltipWrapper?.querySelectorAll('.g2-tooltip')
if (!allTooltips) return
allTooltips.forEach(item => {
const tooltip = item as HTMLElement
const { height, right } = newChart
?.getContext()
?.canvas?.context?.contextService?.$container?.getBoundingClientRect()
if (isCarousel) {
const tooltipHeight = tooltip.getBoundingClientRect().height
tooltip.style.top = (height / 2 - tooltipHeight / 2 + 20) * chart.tScale + 'px'
} else {
const clientY = event?.client?.y
if (!clientY) return
if (clientY < tooltip.getBoundingClientRect().height) {
@@ -120,13 +136,12 @@ export function listenerTooltipShow(newChart: G2Chart, chart: Chart) {
document.getElementById('preview-canvas-main')
if (!targetDiv || clientX == null) return
const dvRight = targetDiv.getBoundingClientRect().right
const tooltipWidth = tooltip.getBoundingClientRect().width
const left = clientX + 20
const left = clientX
tooltip.style.left =
left + tooltipWidth > dvRight ? `${dvRight - tooltipWidth}px` : `${left}px`
})
}
left + tooltipWidth > right ? `${clientX - tooltipWidth - 20}px` : `${left + 20}px`
}
})
})
}

View File

@@ -12,11 +12,11 @@ import {
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
import { valueFormatter } from '@/views/chart/components/js/formatter'
import {
TOOLTIP_ITEM_TPL,
toLinearGradient,
TOOLTIP_ITEM_TPL,
TOOLTIP_TITLE_TPL
} from '@/views/chart/components/js/panel/common/common_antv'
import { defaultsDeep, isEmpty } from 'lodash-es'
import { isEmpty } from 'lodash-es'
/**
* 分组堆叠柱状图

View File

@@ -3,6 +3,7 @@ import { flow, parseJson } from '@/views/chart/components/js/util'
import {
createTooltipWrapper,
tooltipCss,
tooltipMaxHeight,
ViewSpec
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
import { GroupStackBar } from '@/views/chart/components/js/panel/charts/g2/bar/group-stack-bar'
@@ -89,10 +90,6 @@ export class PercentageStackBar extends GroupStackBar {
css: tooltipCss(tooltip),
enterable: true,
shared: true,
bounding: {
x: 0,
y: 0
},
position: 'top-right',
render: (_, { title, items: originalItems }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
@@ -122,7 +119,9 @@ export class PercentageStackBar extends GroupStackBar {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -129,7 +129,7 @@ export class StackBar extends Bar {
tooltip: {
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltip),
enterable: false,
enterable: true,
shared: true,
position: 'top-right',
render: (_, { title, items: originalItems }) => {
@@ -151,7 +151,9 @@ export class StackBar extends Bar {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -29,7 +29,7 @@ import {
} from '../../../common/common_antv'
import { registerSymbol, Symbols } from '@antv/g2/esm/utils/marker'
import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel'
import { createTooltipWrapper, tooltipCss } from '../bar/barUtil'
import { createTooltipWrapper, tooltipCss, tooltipMaxHeight } from '../bar/barUtil'
const { t } = useI18n()
const DEFAULT_DATA = []
@@ -571,6 +571,7 @@ export class Area extends G2ChartView {
crosshairsLineDash: [4, 4],
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltipAttr),
enterable: true,
render: (e, { title, items: originalItems }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
let tooltipItems = originalItems
@@ -607,7 +608,9 @@ export class Area extends G2ChartView {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}
@@ -829,6 +832,7 @@ export class StackArea extends Area {
crosshairsLineDash: [4, 4],
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltipAttr),
enterable: true,
render: (e, { title, items }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
const result = []
@@ -849,7 +853,9 @@ export class StackArea extends Area {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -26,7 +26,7 @@ import {
import { extremumEvt, addExtremumText } from '@/views/chart/components/js/extremumUitl'
import { registerSymbol, Symbols } from '@antv/g2/esm/utils/marker'
import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel'
import { createTooltipWrapper, tooltipCss } from '../bar/barUtil'
import { createTooltipWrapper, tooltipCss, tooltipMaxHeight } from '../bar/barUtil'
const { t } = useI18n()
const DEFAULT_DATA = []
@@ -650,6 +650,7 @@ export class Line extends G2ChartView {
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltipAttr),
position: 'top-right',
enterable: true,
render: (e, { title, items: originalItems }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
let tooltipItems = originalItems
@@ -686,7 +687,9 @@ export class Line extends G2ChartView {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -25,7 +25,8 @@ import { registerSymbol, Symbols } from '@antv/g2/esm/utils/marker'
import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel'
import {
createTooltipWrapper,
tooltipCss
tooltipCss,
tooltipMaxHeight
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
const { t } = useI18n()
@@ -594,7 +595,7 @@ export class GroupLineMix extends G2ChartView {
crosshairsLineDash: [4, 4],
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltip),
enterable: false,
enterable: true,
render: (_, { title, items }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
if (tooltip.seriesTooltipFormatter?.length) {
@@ -621,7 +622,9 @@ export class GroupLineMix extends G2ChartView {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -28,7 +28,8 @@ import { registerSymbol, Symbols } from '@antv/g2/esm/utils/marker'
import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel'
import {
createTooltipWrapper,
tooltipCss
tooltipCss,
tooltipMaxHeight
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
const { t } = useI18n()
@@ -575,7 +576,7 @@ export class GroupLineMix extends G2ChartView {
crosshairsLineDash: [4, 4],
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltip),
enterable: false,
enterable: true,
render: (_, { title, items }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
if (tooltip.seriesTooltipFormatter?.length) {
@@ -602,7 +603,9 @@ export class GroupLineMix extends G2ChartView {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -27,7 +27,8 @@ import { registerSymbol, Symbols } from '@antv/g2/esm/utils/marker'
import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel'
import {
createTooltipWrapper,
tooltipCss
tooltipCss,
tooltipMaxHeight
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
const { t } = useI18n()
@@ -573,7 +574,7 @@ export class StackLineMix extends G2ChartView {
crosshairsLineDash: [4, 4],
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltip),
enterable: false,
enterable: true,
render: (_, { title, items }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
if (tooltip.seriesTooltipFormatter?.length) {
@@ -600,7 +601,9 @@ export class StackLineMix extends G2ChartView {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -26,7 +26,8 @@ import { CHART_MIX_EDITOR_PROPERTY, CHART_MIX_EDITOR_PROPERTY_INNER } from './co
import G2TooltipCarousel from '@/views/chart/components/js/G2TooltipCarousel'
import {
createTooltipWrapper,
tooltipCss
tooltipCss,
tooltipMaxHeight
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
const { t } = useI18n()
@@ -425,7 +426,7 @@ export class ColumnLineMix extends G2ChartView {
crosshairsLineDash: [4, 4],
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltip),
enterable: false,
enterable: true,
render: (_, { title, items }) => {
const titleHtml = TOOLTIP_TITLE_TPL.replace('{title}', title)
if (tooltip.seriesTooltipFormatter?.length) {
@@ -452,7 +453,9 @@ export class ColumnLineMix extends G2ChartView {
.replace('{value}', value)
})
.join('')
const listHtml = `<ul class="g2-tooltip-list" style="margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
const listHtml = `<ul class="g2-tooltip-list" style="${tooltipMaxHeight(
chart
)}margin: 0px; list-style-type: none; padding: 0px;">${itemsHtml}</ul>`
return `${titleHtml}${listHtml}`
}
}

View File

@@ -359,10 +359,11 @@ const renderG2 = async (chart, chartView: G2PlotChartView<any, any>) => {
if (dvMainStore.mobileInPc) {
dashboardHidden = !props.element.inMobile
}
const tScale = dvMainStore.canvasStyleData?.tScale
myChart = await chartView.drawChart({
chartObj: myChart,
container: containerId,
chart: { ...chart, container: containerId, dashboardHidden },
chart: { ...chart, container: containerId, dashboardHidden, tScale },
scale: scale.value,
action,
quadrantDefaultBaseline