mirror of
https://github.com/dataease/dataease.git
synced 2026-06-16 20:42:07 +08:00
fix(图表): 提示轮播优化
This commit is contained in:
@@ -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 {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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') {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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}`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
createTooltipWrapper,
|
||||
handleEmptyDataStrategy,
|
||||
tooltipCss,
|
||||
tooltipMaxHeight,
|
||||
ViewSpec
|
||||
} from '@/views/chart/components/js/panel/charts/g2/bar/barUtil'
|
||||
import {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user