NEZ-3211 feat: 处理tooltip的显示 以及 右Y轴
This commit is contained in:
@@ -440,7 +440,7 @@ td .nz-icon-gear:before {
|
||||
.chart-bar,
|
||||
.chart-gauge,
|
||||
.chart-sankey,
|
||||
.chart-time-series,
|
||||
.chart-time-series-tooltip,
|
||||
.chart-treemap,
|
||||
.chart-pie,
|
||||
.chart-bubble,
|
||||
@@ -456,7 +456,7 @@ td .nz-icon-gear:before {
|
||||
color: $--color-text-regular !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.chart-time-series,
|
||||
.chart-time-series-tooltip,
|
||||
.chart-pie,
|
||||
.chart-bar,
|
||||
.chart-treemap,
|
||||
@@ -464,7 +464,26 @@ td .nz-icon-gear:before {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.chart-time-series-tooltip {
|
||||
position: absolute;
|
||||
display: block;
|
||||
border-style: solid;
|
||||
white-space: nowrap;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 1px 2px 10px;
|
||||
transition: opacity 0.2s cubic-bezier(0.23, 1, 0.32, 1) 0s, visibility 0.2s cubic-bezier(0.23, 1, 0.32, 1) 0s, transform 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0s;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-width: 1px;
|
||||
border-radius: 4px;
|
||||
color: rgb(102, 102, 102);
|
||||
font: 14px / 21px "Microsoft YaHei";
|
||||
padding: 10px;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
border-color: rgb(255, 255, 255);
|
||||
z-index: 99999999;
|
||||
visibility: visible;
|
||||
pointer-events: none;
|
||||
}
|
||||
.yAxis-icon{
|
||||
margin-right: 4px;
|
||||
background: transparent !important;
|
||||
@@ -543,7 +562,7 @@ i.nz-icon-override{
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
.chart-time-series.hide{
|
||||
.chart-time-series-tooltip.hide{
|
||||
display: none !important;
|
||||
}
|
||||
.alert-rule-info-two{
|
||||
|
||||
@@ -247,26 +247,15 @@ export default {
|
||||
if (this.isGrey[index]) {
|
||||
return false
|
||||
}
|
||||
return
|
||||
if (this.chartInfo.type === 'pie' || this.chartInfo.type === 'doughnut' || this.chartInfo.type === 'rose') {
|
||||
this.$emit('hoverLegendD3', legendName, index, type)
|
||||
} else if (this.isTimeSeries) {
|
||||
if (type == 'highlight' && getChart(this.chartId)) {
|
||||
const option = getChart(this.chartId).getOption()
|
||||
const series = this.$lodash.cloneDeep(option.series)
|
||||
series[index].emphasis.focus = 'series'
|
||||
getChart(this.chartId).setOption({ series })
|
||||
} else if (getChart(this.chartId)) {
|
||||
const option = getChart(this.chartId).getOption()
|
||||
const series = this.$lodash.cloneDeep(option.series)
|
||||
series[index].emphasis.focus = 'none'
|
||||
getChart(this.chartId).setOption({ series })
|
||||
const echarts = getChart(this.chartId)
|
||||
if (type == 'highlight') {
|
||||
echarts.setSeries(index + 1, {focus:true})
|
||||
} else {
|
||||
echarts.setSeries(null, {focus: true})
|
||||
}
|
||||
getChart(this.chartId) && getChart(this.chartId).dispatchAction({
|
||||
type: type,
|
||||
seriesIndex: index,
|
||||
name: legendName
|
||||
})
|
||||
} else {
|
||||
getChart(this.chartId) && getChart(this.chartId).dispatchAction({
|
||||
type: type,
|
||||
|
||||
@@ -200,7 +200,7 @@ export default {
|
||||
}
|
||||
})
|
||||
],
|
||||
padding: [15, 15, 15, 15],
|
||||
padding: [15, this.autoPadRight, 15, 15],
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
@@ -214,11 +214,11 @@ export default {
|
||||
{
|
||||
scale: 'left',
|
||||
values: (u, vals, space) => vals.map(v => leftUnitCompute.compute(v, null, -1, decimals)),
|
||||
formatValue: (v, d) => {
|
||||
console.log(v, d, 'vd')
|
||||
return v
|
||||
},
|
||||
incrs: incrs,
|
||||
// space: (self) => {
|
||||
// console.log(self)
|
||||
// return 50
|
||||
// },
|
||||
size (self, values, axisIdx, cycleNum) {
|
||||
const axis = self.axes[axisIdx]
|
||||
|
||||
@@ -243,34 +243,14 @@ export default {
|
||||
{
|
||||
show: true,
|
||||
side: 1,
|
||||
grid: { show: false, width: 0 },
|
||||
grid: { show: false },
|
||||
scale: 'right',
|
||||
// space: (self) => {
|
||||
// console.log(self)
|
||||
// return 50
|
||||
// },
|
||||
values: (u, vals, space) => vals.map(v => rightUnitCompute.compute(v, null, -1, decimals)),
|
||||
formatValue: (v, d) => {
|
||||
console.log(v, d, 'vd')
|
||||
return v
|
||||
},
|
||||
incrs: rightIncrs
|
||||
// size (self, values, axisIdx, cycleNum) {
|
||||
// const axis = self.axes[axisIdx]
|
||||
//
|
||||
// // bail out, force convergence
|
||||
// if (cycleNum > 1) { return axis._size }
|
||||
//
|
||||
// let axisSize = axis.ticks.size + axis.gap
|
||||
//
|
||||
// // find longest value
|
||||
// const longestVal = (values ?? []).reduce((acc, val) => (
|
||||
// val.length > acc.length ? val : acc
|
||||
// ), '')
|
||||
//
|
||||
// if (longestVal != '') {
|
||||
// self.ctx.font = axis.font[0]
|
||||
// axisSize += self.ctx.measureText(longestVal).width / devicePixelRatio
|
||||
// }
|
||||
//
|
||||
// return Math.ceil(axisSize)
|
||||
// }
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ import { initColor, Incrs } from '@/components/chart/chart/tools'
|
||||
import { randomcolor } from '@/components/common/js/radomcolor/randomcolor'
|
||||
import chartDataFormat from '@/components/chart/chartDataFormat'
|
||||
import lodash from 'lodash'
|
||||
import { getMetricTypeValue } from '@/components/common/js/tools'
|
||||
import { formatScientificNotation, getMetricTypeValue } from '@/components/common/js/tools'
|
||||
import uPlot from 'uplot'
|
||||
import bus from '@/libs/bus'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
@@ -75,9 +76,12 @@ export default {
|
||||
const elementNames = this.$lodash.get(this.chartInfo, 'param.rightYAxis.elementNames', [])
|
||||
isRight = elementNames.indexOf(series.elements.name) !== -1
|
||||
}
|
||||
const name = legend.name
|
||||
const alias = legend.alias
|
||||
const statistics = series.statistics
|
||||
const obj = {
|
||||
name: series.elements.name + JSON.stringify(series.metric),
|
||||
label: series.elements.name + JSON.stringify(series.metric),
|
||||
name: name,
|
||||
label: alias,
|
||||
class: series.elements.name + JSON.stringify(series.metric),
|
||||
scale: isRight ? 'right' : 'left', // right
|
||||
yAxisIndex: isRight ? 1 : 0, // right
|
||||
@@ -85,9 +89,6 @@ export default {
|
||||
stroke: this.seriesColor[chartIndex],
|
||||
width: 1 / devicePixelRatio
|
||||
}
|
||||
const name = legend.name
|
||||
const alias = legend.alias
|
||||
const statistics = series.statistics
|
||||
this.legends.push({ name, alias, statistics, color: this.seriesColor[chartIndex] })
|
||||
return obj
|
||||
},
|
||||
@@ -96,17 +97,11 @@ export default {
|
||||
let tooltipTopOffset = 0
|
||||
const self = this
|
||||
const tooltip = document.createElement('div')
|
||||
tooltip.className = 'u-tooltip'
|
||||
|
||||
let seriesIdx = null
|
||||
let dataIdx = null
|
||||
|
||||
const fmtDate = uPlot.fmtDate('{M}/{D}/{YY} {h}:{mm}:{ss} {AA}')
|
||||
|
||||
let over
|
||||
|
||||
let tooltipVisible = false
|
||||
|
||||
let isRender = false
|
||||
function showTooltip () {
|
||||
if (!tooltipVisible) {
|
||||
tooltip.style.display = 'block'
|
||||
@@ -123,23 +118,240 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
function setTooltip (u) {
|
||||
function setTooltip (u) { // 生成tooltip内容
|
||||
showTooltip()
|
||||
|
||||
const top = u.valToPos(u.data[seriesIdx][dataIdx], 'y')
|
||||
if (!self.$lodash.get(self.chartInfo, 'param.enable.tooltip', false)) {
|
||||
return
|
||||
}
|
||||
isRender = false
|
||||
console.log(self.chartInfo, seriesIdx, dataIdx, u)
|
||||
const { left, top } = u.cursor
|
||||
const lft = u.valToPos(u.data[0][dataIdx], 'x')
|
||||
|
||||
tooltip.style.top = (tooltipTopOffset + top + shiftX) + 'px'
|
||||
tooltip.style.left = (tooltipLeftOffset + lft + shiftY) + 'px'
|
||||
let params = []
|
||||
const tooltipModel = self.$lodash.get(self.chartInfo, 'param.tooltip.mode', 'single')
|
||||
console.log(tooltipModel)
|
||||
if (self.chartInfo.param && !(tooltipModel == 'single')) {
|
||||
params = self.series.map((s, i) => {
|
||||
return {
|
||||
seriesIndex: i,
|
||||
yAxisIndex: s.yAxisIndex,
|
||||
value: [u.data[0][dataIdx], u.data[i + 1][dataIdx]],
|
||||
seriesName: s.label
|
||||
}
|
||||
})
|
||||
params = params.filter(item => {
|
||||
console.log(item.value[1], typeof (item.value[1]) == 'undefined')
|
||||
const flag = typeof (item.value[1]) == 'undefined'
|
||||
return !flag
|
||||
})
|
||||
} else if (seriesIdx) {
|
||||
const obj = self.series[seriesIdx - 1]
|
||||
params = [{
|
||||
seriesIndex: seriesIdx - 1,
|
||||
yAxisIndex: obj.yAxisIndex,
|
||||
value: [u.data[0][dataIdx], u.data[seriesIdx][dataIdx]],
|
||||
seriesName: obj.label
|
||||
}]
|
||||
}
|
||||
isRender = !!params.length
|
||||
console.log(isRender, 'isRender')
|
||||
if (!isRender) {
|
||||
tooltip.style.display = 'none'
|
||||
over.style.cursor = null
|
||||
return
|
||||
} else {
|
||||
tooltip.style.display = 'block'
|
||||
over.style.cursor = 'pointer'
|
||||
}
|
||||
tooltip.className = 'chart-time-series-tooltip'
|
||||
let str = '<div class="nz-tooltip nz-chart__tooltip">'
|
||||
const hasTotal = self.isStack
|
||||
const decimals = self.chartInfo.param.decimals || 2
|
||||
// 区分左y轴右y轴
|
||||
params.forEach(item => {
|
||||
if (self.series[item.seriesIndex]) {
|
||||
item.yAxisIndex = self.series[item.seriesIndex].yAxisIndex
|
||||
}
|
||||
})
|
||||
// 排序先展示左y轴
|
||||
params.sort((a, b) => a.yAxisIndex - b.yAxisIndex)
|
||||
// 分割
|
||||
const rightYAxisIndex = params.findIndex(item => item.yAxisIndex == 1)
|
||||
let leftYAxis = []
|
||||
let rightYAxis = []
|
||||
if (rightYAxisIndex != -1) {
|
||||
leftYAxis = params.slice(0, rightYAxisIndex)
|
||||
rightYAxis = params.slice(rightYAxisIndex)
|
||||
} else {
|
||||
leftYAxis = params
|
||||
}
|
||||
handler(leftYAxis, 'left')
|
||||
handler(rightYAxis, 'right')
|
||||
function handler (arr, type) {
|
||||
console.log(arr, type)
|
||||
if (!arr.length) {
|
||||
return
|
||||
}
|
||||
|
||||
tooltip.style.borderColor = self.seriesColor[seriesIdx - 1]
|
||||
const pctSinceStart = (((u.data[seriesIdx][dataIdx] - u.data[seriesIdx][0]) / u.data[seriesIdx][0]) * 100).toFixed(2)
|
||||
tooltip.textContent = (
|
||||
fmtDate(new Date(u.data[0][dataIdx] * 1e3)) + ' - ' + '\n' +
|
||||
uPlot.fmtNum(u.data[seriesIdx][dataIdx]) + ' (' + pctSinceStart + '% since start)'
|
||||
)
|
||||
// tooltip排序
|
||||
let sortBy
|
||||
if (self.$lodash.get(self.chartInfo, 'param.enable.tooltip') && self.$lodash.get(self.chartInfo, 'param.tooltip.mode') !== 'single' && self.$lodash.get(self.chartInfo, 'param.tooltip.sort') !== 'none') {
|
||||
sortBy = self.$lodash.get(self.chartInfo, 'param.tooltip.sort')
|
||||
}
|
||||
const previousIndex = arr.findIndex(item => item.seriesName.indexOf('Previous') !== -1)
|
||||
if (previousIndex != -1) { // 对比状态
|
||||
const arrNow = arr.slice(0, previousIndex)
|
||||
const arrPrevious = arr.slice(previousIndex)
|
||||
if (sortBy === 'asc') {
|
||||
arrNow.sort((a, b) => a.value[1] - b.value[1])
|
||||
arrPrevious.sort((a, b) => a.value[1] - b.value[1])
|
||||
} else if (sortBy === 'desc') {
|
||||
arrNow.sort((a, b) => b.value[1] - a.value[1])
|
||||
arrPrevious.sort((a, b) => b.value[1] - a.value[1])
|
||||
}
|
||||
arr = [...arrNow, ...arrPrevious]
|
||||
} else {
|
||||
if (sortBy === 'asc') {
|
||||
arr.sort((a, b) => a.value[1] - b.value[1])
|
||||
} else if (sortBy === 'desc') {
|
||||
arr.sort((a, b) => b.value[1] - a.value[1])
|
||||
}
|
||||
}
|
||||
|
||||
let sum = 0
|
||||
let flag = true
|
||||
arr.forEach((item, i) => {
|
||||
let unit = self.chartInfo.unit ? self.chartInfo.unit : 2
|
||||
if (type == 'right') {
|
||||
unit = lodash.get(self, 'chartInfo.param.rightYAxis.unit', 2)
|
||||
}
|
||||
const nameArr = item.seriesName.split('-')
|
||||
// if (nameArr.length > 1) {
|
||||
// nameArr.splice(nameArr.length - 1, 1)
|
||||
// }
|
||||
const seriesName = nameArr.join('-')
|
||||
if (i === 0 && item.seriesName.indexOf('Previous') === -1 && type == 'left') {
|
||||
const value = bus.computeTimezone(item.value[0] * 1000)
|
||||
const tData = new Date(value)
|
||||
str += '<div class="tooltip-title" style="margin-bottom: 5px">'
|
||||
str += bus.timeFormate(tData)
|
||||
str += '</div>'
|
||||
}
|
||||
// 两条y轴数据分割线
|
||||
if (i == 0 && rightYAxisIndex != 0 && type == 'right') {
|
||||
str += '<div style="border: 1px solid #EEEEEE;margin-top: 5px;margin-bottom: 5px"></div>'
|
||||
}
|
||||
if (item.seriesName.indexOf('Previous') === -1 && type == 'right') {
|
||||
if (i == 0 && (rightYAxisIndex == 0 || (arr.some(item => item.seriesName.indexOf('Previous') !== -1)))) {
|
||||
const value = bus.computeTimezone(item.value[0] * 1000)
|
||||
const tData = new Date(value)
|
||||
str += '<div class="tooltip-title" style="margin-bottom: 5px">'
|
||||
str += bus.timeFormate(tData)
|
||||
str += '</div>'
|
||||
}
|
||||
}
|
||||
// Previous分割线
|
||||
if (i !== 0 && flag && item.seriesName.indexOf('Previous') !== -1) {
|
||||
str += '<div style="border: 1px solid #EEEEEE;margin-top: 5px;margin-bottom: 5px"></div>'
|
||||
}
|
||||
if (flag && item.seriesName.indexOf('Previous') !== -1) {
|
||||
flag = false
|
||||
const value = bus.computeTimezone(item.value[0] * 1000 - self.minusTime)
|
||||
const tData = new Date(value)
|
||||
str += '<div class="tooltip-title" style="margin-bottom: 5px">'
|
||||
str += bus.timeFormate(tData)
|
||||
str += '</div>'
|
||||
}
|
||||
const color = self.colorList[item.seriesIndex]
|
||||
const previousItem = arr.find((series) => ('Previous ' + item.seriesName) === series.seriesName)
|
||||
let paramsDot = bus.countDecimals(item.value[1])
|
||||
if (paramsDot < decimals) {
|
||||
paramsDot = decimals
|
||||
} else if (paramsDot > 6) {
|
||||
paramsDot = 6
|
||||
}
|
||||
const val = formatScientificNotation(item.value[1], paramsDot)
|
||||
sum += isNaN(self.numberWithEConvent(val)) ? 0 : parseFloat(self.numberWithEConvent(val))
|
||||
let previousDom = ''
|
||||
if (previousItem) {
|
||||
const previousVal = formatScientificNotation(previousItem.value[1], paramsDot)
|
||||
let minusVal = 0
|
||||
let operator
|
||||
if (previousVal <= val) {
|
||||
minusVal = val - previousVal
|
||||
operator = '+'
|
||||
} else {
|
||||
minusVal = previousVal - val
|
||||
operator = '-'
|
||||
}
|
||||
previousDom = `
|
||||
<span>${operator}${chartDataFormat.getUnit(unit).compute(minusVal, null, -1, decimals)}</span>
|
||||
`
|
||||
}
|
||||
|
||||
// 根据左右轴设置图标
|
||||
let className = 'row__color-block'
|
||||
if (item.yAxisIndex == 0) {
|
||||
className = 'yAxis-icon nz-icon nz-icon-zuozongzhou'
|
||||
} else if (item.yAxisIndex == 1) {
|
||||
className = 'yAxis-icon nz-icon nz-icon-youzongzhou'
|
||||
}
|
||||
|
||||
// 鼠标悬浮 series data symbol 时,tooltip 中相应的legend 高亮显示
|
||||
str += `
|
||||
<div class="${(seriesIdx - 1 == item.seriesIndex) ? 'tooltip__row highlight' : 'tooltip__row'}" title="${seriesName}">
|
||||
<div class="row__label">
|
||||
<span class="${className}" style="background-color: ${color};color: ${color}"></span>
|
||||
<span>${seriesName}</span>
|
||||
</div>
|
||||
<div class="row__value">
|
||||
<span>${chartDataFormat.getUnit(unit).compute(val, null, -1, decimals)}</span>
|
||||
${previousDom}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
// 显示total
|
||||
if (hasTotal) {
|
||||
sum = parseFloat(Number(sum).toFixed(2))
|
||||
let unit = self.chartInfo.unit ? self.chartInfo.unit : 2
|
||||
let className = 'row__color-block'
|
||||
let color = ''
|
||||
if (type == 'left') {
|
||||
// 判断是否开启rightYAxis 否则显示普通图标
|
||||
if (self.series.some(item => item.yAxisIndex == 0)) {
|
||||
className = 'yAxis-icon nz-icon nz-icon-zuozongzhou'
|
||||
}
|
||||
if (!self.stackTotalColor) {
|
||||
self.stackTotalColor = randomcolor()
|
||||
}
|
||||
color = self.stackTotalColor
|
||||
} else {
|
||||
unit = lodash.get(self, 'chartInfo.param.rightYAxis.unit', 2)
|
||||
className = 'yAxis-icon nz-icon nz-icon-youzongzhou'
|
||||
if (!self.stackTotalColorRight) {
|
||||
self.stackTotalColorRight = randomcolor()
|
||||
}
|
||||
color = self.stackTotalColorRight
|
||||
}
|
||||
str += `
|
||||
<div class="tooltip__row">
|
||||
<div class="row__label" title="${self.$t('dashboard.dashboard.chartTotal')}">
|
||||
<span class="${className}" style="background-color: ${color};color: ${color}"></span>
|
||||
<span>${self.$t('dashboard.dashboard.chartTotal')}</span>
|
||||
</div>
|
||||
<div class="row__value">
|
||||
<span>${chartDataFormat.getUnit(unit).compute(sum, null, -1, decimals)}</span>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
str += '</div>'
|
||||
tooltip.innerHTML = str
|
||||
}
|
||||
|
||||
return {
|
||||
hooks: {
|
||||
ready: [
|
||||
@@ -151,14 +363,16 @@ export default {
|
||||
|
||||
let clientX
|
||||
let clientY
|
||||
|
||||
over.addEventListener('mouseleave', () => {
|
||||
if (!u.cursor._lock) {
|
||||
hideTooltip()
|
||||
}
|
||||
})
|
||||
over.addEventListener('mousedown', e => {
|
||||
clientX = e.clientX
|
||||
clientY = e.clientY
|
||||
})
|
||||
|
||||
over.addEventListener('mouseup', e => {
|
||||
// clicked in-place
|
||||
if (e.clientX == clientX && e.clientY == clientY) {
|
||||
if (seriesIdx != null && dataIdx != null) {
|
||||
onclick(u, seriesIdx, dataIdx)
|
||||
@@ -170,11 +384,9 @@ export default {
|
||||
setCursor: [
|
||||
u => {
|
||||
const c = u.cursor
|
||||
|
||||
if (dataIdx != c.idx) {
|
||||
dataIdx = c.idx
|
||||
|
||||
if (seriesIdx != null) { setTooltip(u) }
|
||||
setTooltip(u)
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -182,8 +394,7 @@ export default {
|
||||
(u, sidx) => {
|
||||
if (seriesIdx != sidx) {
|
||||
seriesIdx = sidx
|
||||
|
||||
if (sidx == null) { hideTooltip() } else if (dataIdx != null) { setTooltip(u) }
|
||||
if (dataIdx != null) { setTooltip(u) }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user