fix(图表): 提示轮播优化

This commit is contained in:
jianneng-fit2cloud
2025-11-05 11:15:58 +08:00
parent 6ca027a381
commit 8570b545ae
7 changed files with 71 additions and 29 deletions

View File

@@ -193,7 +193,7 @@ class G2TooltipCarousel {
if (!this.intersectionObserver) {
this.intersectionObserver = new IntersectionObserver(this.handleIntersection.bind(this), {
root: null,
threshold: [0, 0.3, 0.5, 0.7, 1]
threshold: [0, 0.1, 0.3, 0.5, 0.7, 0.9, 1]
})
}
this.intersectionObserver?.observe(this.newChart.getContainer())
@@ -212,7 +212,7 @@ class G2TooltipCarousel {
instance.stop()
instance.start()
})
}, 100)
}, 1000)
/**
* 移除事件监听
@@ -256,11 +256,20 @@ class G2TooltipCarousel {
if (!el) return false
// 检查可见比例
const rect = el.getBoundingClientRect()
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)
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') ||
document.getElementById('preview-canvas-main') ||
document.getElementById('edit-canvas-main')
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 percentHeight = visibleHeight / rect.height
const percentWidth = visibleWidth / rect.width
return percentHeight > 0.7 && percentWidth > 0.7
return percentHeight >= 0.9 && percentWidth >= 0.7
}
/**
@@ -421,7 +430,7 @@ class G2TooltipCarousel {
const isMix = this.isMixChart()
const isLineOrMix = this.isLineChart() || isMix
this.newChart.emit('element:select', {
data: { data: [isMix && originalData ? originalData : tooltipData.data.data] }
data: { data: [isLineOrMix && originalData ? originalData : tooltipData.data.data] }
})
const { offsetX, offsetY } = this.getTooltipOffsetX(tooltipData)
this.newChart.emit('tooltip:show', {
@@ -437,24 +446,37 @@ class G2TooltipCarousel {
*/
getTooltipOffsetX(tooltipData) {
try {
const ctx = this.newChart.getContext()
const root = ctx.canvas.document.getElementsByClassName('plot')[0]
const { height } = root.getRenderBounds()
const scaleX = (this.newChart.getScale() || ctx.views[0].scale).x
const x =
tooltipData.data.data.x ||
tooltipData.data.data[this.newChart?.children?.[0]?.value?.encode?.x]
const [x2] = (this.newChart.getView()?.coordinate || ctx.views[0].coordinate).map([
scaleX.map(x),
0.5
])
const { insetLeft, marginLeft, paddingLeft } = root.__data__
return {
offsetX: insetLeft + marginLeft + paddingLeft + x2 * this.chart.tScale,
offsetY: (height / 2) * this.chart.tScale
tooltipData?.data?.data?.x ??
tooltipData?.data?.data?.[this.newChart?.children?.[0]?.value?.encode?.x]
const ctx = this.newChart?.getContext()
if (!ctx) return {}
const elements = ctx.canvas?.document?.getElementsByClassName('element') || []
const root = ctx.canvas?.document?.getElementsByClassName('plot')?.[0]
if (!root || elements.length === 0) return {}
const { insetLeft = 0, marginLeft = 0, paddingLeft = 0 } = root.__data__ || {}
const plotPaddingLeft = insetLeft + marginLeft + paddingLeft
const offsetY = (root.getRenderBounds().height / 2) * (this.chart.tScale || 1)
if (this.isLineChart()) {
const xField = ctx.views[0].options.marks[0].encode.x
const firstXElement = elements.filter(
ele => ele.markType === 'point' && ele.__data__.data[xField] === x
)?.[0]
const offsetX =
plotPaddingLeft +
(firstXElement?.__data__?.points?.[0]?.[0] + firstXElement?.__data__?.points?.[1]?.[0]) /
2
return { offsetX, offsetY }
} else {
const xElement = Array.from(elements).find(ele => ele.__data__?.title === x)
if (!xElement || !xElement.__data__?.points) return {}
const points = xElement.__data__.points
const offsetX = plotPaddingLeft + (points[0][0] + points[1][0]) / 2
return { offsetX, offsetY }
}
} catch (e) {
console.error('Get Tooltip offsetX fail:', e)
return {}
}
}

View File

@@ -304,7 +304,12 @@ export class Bar extends G2ChartView<ViewSpec, G2Column> {
paddingInner: 0.01
}
}
if (this.name === 'bar' || this.name === 'percentage-bar-stack' || this.name === 'waterfall') {
if (
this.name === 'bar' ||
this.name === 'percentage-bar-stack' ||
this.name === 'waterfall' ||
this.name === 'bar-group-stack'
) {
scale.x.paddingInner = -0.21
}
if (this.name === 'bar-group') {

View File

@@ -72,7 +72,8 @@ export function tooltipCss(tooltipAttr: DeepPartial<ChartTooltipAttr>) {
background: tooltipAttr.backgroundColor,
'max-height': '50vh',
'overflow-y': 'auto',
position: 'fixed'
position: 'fixed',
'scrollbar-width': tooltipAttr.carousel.enable ? 'none !important' : 'auto'
},
'.g2-tooltip-title': {
color: tooltipAttr.color,
@@ -91,16 +92,18 @@ 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;`
const chartRect = chartContainer?.getBoundingClientRect()
let doubleHeight = chartRect.height * 2 - 20
if (chart.customAttr?.tooltip?.carousel?.enable) {
doubleHeight = chartRect.height / 1.2 - 20
}
const maxHeight = chartContainer ? Math.max(doubleHeight, defaultHeight) : defaultHeight
return `max-height: ${maxHeight}px;max-width: ${chartRect.width / 2}px;`
}
export function listenerTooltipShow(newChart: G2Chart, chart: Chart) {

View File

@@ -7,6 +7,7 @@ import { StackBar } from '@/views/chart/components/js/panel/charts/g2/bar/stack-
import {
createTooltipWrapper,
tooltipCss,
tooltipMaxHeight,
Transform,
ViewSpec
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
@@ -81,7 +82,7 @@ export class GroupStackBar extends StackBar {
tooltip: {
mount: createTooltipWrapper(chart),
css: tooltipCss(tooltip),
enterable: false,
enterable: true,
shared: true,
position: 'top-right',
render: (_, { title, items: originalItems }) => {
@@ -105,7 +106,9 @@ export class GroupStackBar extends StackBar {
.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

@@ -15,6 +15,7 @@ import {
createTooltipWrapper,
handleEmptyDataStrategy,
tooltipCss,
tooltipMaxHeight,
ViewSpec
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
import {

View File

@@ -340,6 +340,13 @@ export class GroupLineMix extends G2ChartView {
}
merge(lineMark, rightColorScale)
merge(pointMark, rightColorScale)
merge(intervalMark, {
scale: {
x: {
paddingInner: -0.21
}
}
})
merge(intervalMark, {
style: {
columnWidthRatio: basicStyle.columnWidthRatio / 100

View File

@@ -2565,6 +2565,7 @@ function hideChildrenLabels(child) {
)
child.legend && (child.legend = false)
child.slider && Object.assign(child.slider, { x: false, y: false })
child.tooltip = false
}
/**