NEZ-1280 feat: 时间序列chart微调
This commit is contained in:
@@ -97,6 +97,7 @@
|
||||
&.nz-chart__component--right, &.nz-chart__component--left {
|
||||
.legend-container {
|
||||
flex-direction: column;
|
||||
padding-top: 25px;
|
||||
width: unset;
|
||||
max-width: 50%;
|
||||
max-height: unset;
|
||||
@@ -169,3 +170,34 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.nz-chart__tooltip {
|
||||
.tooltip__row {
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
min-width: 150px;
|
||||
max-width: 600px;
|
||||
line-height: 18px;
|
||||
font-size: 12px;
|
||||
|
||||
.row__label {
|
||||
max-width: 500px;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
.row__color-block {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
border-radius: 10px;
|
||||
width: 15px;
|
||||
height: 5px;
|
||||
}
|
||||
}
|
||||
.row__value {
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<div :class="legendPlacement" class="nz-chart__component nz-chart__component--time-series">
|
||||
<div
|
||||
:class="legendPlacement"
|
||||
class="nz-chart__component nz-chart__component--time-series" @mouseenter="mouseEnterChart"
|
||||
@mouseleave="mouseLeaveChart"
|
||||
>
|
||||
<div :id="`chart-canvas-${chartInfo.id}`" class="chart__canvas"></div>
|
||||
<chart-legend
|
||||
v-if="hasLegend"
|
||||
@@ -14,17 +18,15 @@
|
||||
import legend from './legend'
|
||||
import chartMixin from '@/components/chart/chartMixin'
|
||||
import * as echarts from 'echarts'
|
||||
import lodash from 'lodash'
|
||||
import moment from 'moment-timezone'
|
||||
import bus from '@/libs/bus'
|
||||
import { formatScientificNotation } from '@/components/common/js/tools'
|
||||
import chartDataFormat from '@/components/charts/chartDataFormat'
|
||||
import { randomcolor } from '@/components/common/js/radomcolor/randomcolor'
|
||||
import { chartType, chartLegendPlacement } from '@/components/common/js/constants'
|
||||
import { setChart } from '@/components/common/js/common'
|
||||
import { getChart, setChart } from '@/components/common/js/common'
|
||||
import { initColor } from '@/components/chart/chart/tools'
|
||||
|
||||
let myChart = null
|
||||
export default {
|
||||
name: 'chart-time-series', // x轴是时间的图,包括折线、柱状、堆叠、散点
|
||||
components: {
|
||||
@@ -33,7 +35,8 @@ export default {
|
||||
mixins: [chartMixin],
|
||||
data () {
|
||||
return {
|
||||
stackTotalColor: null
|
||||
stackTotalColor: null,
|
||||
isStack: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -64,30 +67,39 @@ export default {
|
||||
this.legends = []
|
||||
chartOption.series = this.handleTimeSeries(this.chartInfo, chartOption.series[0], this.chartData) // 生成series和legends
|
||||
|
||||
const { minTime, maxTime, minValue, maxValue } = this.getMinMaxFromData(this.chartData[0])
|
||||
chartOption.xAxis.axisLabel.formatter = this.xAxisLabelFormatter(minTime, maxTime)
|
||||
const { minTime, maxTime, minValue, maxValue } = this.getMinMaxFromData(this.chartData) // 此处时间是秒
|
||||
chartOption.xAxis.axisLabel.formatter = this.xAxisLabelFormatter(minTime * 1000, maxTime * 1000) // 需转为毫秒
|
||||
chartOption.tooltip.formatter = this.tooltipFormatter()
|
||||
chartOption.yAxis.axisLabel.formatter = this.yAxisLabelFormatter(minValue, maxValue)
|
||||
setTimeout(() => {
|
||||
myChart = echarts.init(document.getElementById(`chart-canvas-${this.chartInfo.id}`))
|
||||
const myChart = echarts.init(document.getElementById(`chart-canvas-${this.chartInfo.id}`))
|
||||
setChart(this.chartInfo.id, myChart) // 缓存;不使用vue的data是为避免整个chart被监听导致卡顿
|
||||
myChart.setOption(chartOption)
|
||||
this.initToolboxEvent(myChart) // 初始化toolbox事件
|
||||
})
|
||||
},
|
||||
getMinMaxFromData (originalData) {
|
||||
getMinMaxFromData (originalDatas) {
|
||||
let minTime = null
|
||||
let maxTime = null
|
||||
let minValue = null
|
||||
let maxValue = null
|
||||
if (!lodash.isEmpty(originalData)) {
|
||||
minTime = originalData[0][0]
|
||||
maxTime = originalData[originalData.length - 1][0]
|
||||
const sorted = originalData.sort((a, b) => {
|
||||
// 将数据提为二维数组
|
||||
let datas = []
|
||||
originalDatas.forEach((originalData, expressionIndex) => {
|
||||
originalData.forEach((data, dataIndex) => {
|
||||
datas = [...datas, ...data.values]
|
||||
})
|
||||
})
|
||||
const timeSorted = datas.sort((a, b) => {
|
||||
return a[0] - b[0]
|
||||
})
|
||||
const valueSorted = datas.sort((a, b) => {
|
||||
return a[1] - b[1]
|
||||
})
|
||||
minValue = sorted[0][1]
|
||||
maxValue = sorted[sorted.length - 1][1]
|
||||
}
|
||||
minTime = timeSorted[0][0]
|
||||
maxTime = timeSorted[timeSorted.length - 1][0]
|
||||
minValue = valueSorted[0][1]
|
||||
maxValue = valueSorted[valueSorted.length - 1][1]
|
||||
return { minTime, maxTime, minValue, maxValue }
|
||||
},
|
||||
xAxisLabelFormatter (minTime, maxTime) {
|
||||
@@ -121,7 +133,7 @@ export default {
|
||||
tooltipFormatter () {
|
||||
const self = this
|
||||
return function (params) {
|
||||
let str = '<div>'
|
||||
let str = '<div class="nz-chart__tooltip">'
|
||||
let sum = 0
|
||||
params.forEach((item, i) => {
|
||||
const color = self.colorList[item.seriesIndex]
|
||||
@@ -134,44 +146,53 @@ export default {
|
||||
}
|
||||
const val = formatScientificNotation(item.data[1], paramsDot)
|
||||
sum += self.numberWithEConvent(val)
|
||||
// TODO 改成class
|
||||
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
|
||||
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${item.seriesName} </div>`
|
||||
str += '<div style="padding-left: 10px;min-width: 75px;text-align: right">'
|
||||
str += chartDataFormat.getUnit(self.chartInfo.unit ? self.chartInfo.unit : 2).compute(val, null, -1, paramsDot)
|
||||
if (previousItem) {
|
||||
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right">'
|
||||
const previousval = formatScientificNotation(item.data[1], paramsDot)
|
||||
let minusVal = 0
|
||||
if (previousval <= val) {
|
||||
minusVal = val - previousval
|
||||
str += '+'
|
||||
} else {
|
||||
minusVal = previousval - val
|
||||
str += '-'
|
||||
}
|
||||
|
||||
str += chartDataFormat.getUnit(self.chartInfo.unit ? self.chartInfo.unit : 2).compute(minusVal, null, -1, paramsDot)
|
||||
str += '</span>'
|
||||
let previousDom = ''
|
||||
if (previousItem) {
|
||||
const previousVal = formatScientificNotation(item.data[1], paramsDot)
|
||||
let minusVal = 0
|
||||
let operator
|
||||
if (previousVal <= val) {
|
||||
minusVal = val - previousVal
|
||||
operator = '+'
|
||||
} else {
|
||||
minusVal = previousVal - val
|
||||
operator = '-'
|
||||
}
|
||||
str += '</div>'
|
||||
str += '</div>'
|
||||
previousDom = `
|
||||
<span>${operator}${chartDataFormat.getUnit(self.chartInfo.unit ? self.chartInfo.unit : 2).compute(minusVal, null, -1, paramsDot)}</span>
|
||||
`
|
||||
}
|
||||
str += `
|
||||
<div class="tooltip__row">
|
||||
<div class="row__label">
|
||||
<span class="row__color-block" style="background-color: ${color}"></span>
|
||||
<span>${item.seriesName}</span>
|
||||
</div>
|
||||
<div class="row__value">
|
||||
<span>${chartDataFormat.getUnit(self.chartInfo.unit ? self.chartInfo.unit : 2).compute(val, null, -1, paramsDot)}</span>
|
||||
${previousDom}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
if (self.chartInfo.type === chartType.stackArea) {
|
||||
if (!self.stackTotalColor || self.stackTotalColor == '') {
|
||||
if (self.chartInfo.type === chartType.area) {
|
||||
if (!self.stackTotalColor) {
|
||||
self.stackTotalColor = randomcolor()
|
||||
}
|
||||
sum = parseFloat(Number(sum).toFixed(2))
|
||||
// TODO 改成class
|
||||
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
|
||||
str += '<div style="line-height: 18px; font-size: 12px;padding-left:0px;">'
|
||||
str += `<span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${self.stackTotalColor};}'></span>`
|
||||
str += self.$t('dashboard.panel.chartTotal')
|
||||
str += '</div>'
|
||||
str += '<div style="padding-left: 10px;">'
|
||||
str += chartDataFormat.getUnit(self.chartInfo.unit ? self.chartInfo.unit : 2).compute(sum, null, self.chartDot)
|
||||
str += '</div>'
|
||||
str += '</div>'
|
||||
|
||||
str += `
|
||||
<div class="tooltip__row">
|
||||
<div class="row__label">
|
||||
<span class="row__color-block" style="background-color: ${self.stackTotalColor}"></span>
|
||||
<span>${self.$t('dashboard.panel.chartTotal')}</span>
|
||||
</div>
|
||||
<div class="row__value">
|
||||
<span>${chartDataFormat.getUnit(self.chartInfo.unit ? self.chartInfo.unit : 2).compute(sum, null, self.chartDot)}</span>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
str += '</div>'
|
||||
@@ -198,11 +219,98 @@ export default {
|
||||
} */
|
||||
return unit.compute(value, index, -1, 2)
|
||||
}
|
||||
},
|
||||
initToolboxEvent (myChart) {
|
||||
const self = this
|
||||
myChart.on('magictypechanged', function (params) {
|
||||
self.isStack = !self.isStack
|
||||
if (self.isStack) {
|
||||
myChart.setOption({
|
||||
toolbox: {
|
||||
feature: {
|
||||
dataZoom: {
|
||||
yAxisIndex: false,
|
||||
title: {
|
||||
zoom: self.$t('overall.toolBox.zoom'),
|
||||
back: self.$t('overall.toolBox.back')
|
||||
}
|
||||
},
|
||||
magicType: {
|
||||
type: ['stack'],
|
||||
title: {
|
||||
stack: self.$t('overall.toolBox.stack')
|
||||
},
|
||||
iconStyle: {
|
||||
borderColor: '#7e7e7e'
|
||||
},
|
||||
emphasis: {
|
||||
borderColor: '#53a3cb'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
myChart.setOption({
|
||||
toolbox: {
|
||||
feature: {
|
||||
dataZoom: {
|
||||
yAxisIndex: false,
|
||||
title: {
|
||||
zoom: self.$t('overall.toolBox.zoom'),
|
||||
back: self.$t('overall.toolBox.back')
|
||||
}
|
||||
},
|
||||
magicType: {
|
||||
type: ['stack'],
|
||||
title: {
|
||||
stack: self.$t('overall.toolBox.stack')
|
||||
},
|
||||
iconStyle: {
|
||||
borderColor: '#7e7e7e'
|
||||
},
|
||||
emphasis: {
|
||||
borderColor: '#7e7e7e'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
mouseEnterChart () {
|
||||
const myChart = getChart(this.chartInfo.id)
|
||||
if (myChart) {
|
||||
setTimeout(() => {
|
||||
myChart.setOption({
|
||||
toolbox: {
|
||||
show: true
|
||||
}
|
||||
})
|
||||
}, 300)
|
||||
}
|
||||
},
|
||||
mouseLeaveChart () {
|
||||
const myChart = getChart(this.chartInfo.id)
|
||||
if (myChart) {
|
||||
setTimeout(() => {
|
||||
myChart.setOption({
|
||||
toolbox: {
|
||||
show: false
|
||||
}
|
||||
})
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.chartOption.color || (this.chartOption.color = initColor(20))
|
||||
this.colorList = this.chartOption.color
|
||||
try {
|
||||
this.isStack = this.chartInfo.param.legend.stack
|
||||
} catch (e) {}
|
||||
|
||||
this.initChart(this.chartOption)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { initColor } from '@/components/chart/chart/tools'
|
||||
import i18n from '@/components/common/i18n'
|
||||
export const chartTimeSeriesLineOption = {
|
||||
title: {
|
||||
show: false
|
||||
@@ -7,7 +8,31 @@ export const chartTimeSeriesLineOption = {
|
||||
show: false
|
||||
},
|
||||
toolbox: {
|
||||
show: false
|
||||
show: false,
|
||||
top: '0',
|
||||
right: '18',
|
||||
showTitle: false,
|
||||
feature: {
|
||||
dataZoom: {
|
||||
yAxisIndex: false,
|
||||
title: {
|
||||
zoom: i18n.t('overall.toolBox.zoom'),
|
||||
back: i18n.t('overall.toolBox.back')
|
||||
}
|
||||
},
|
||||
magicType: {
|
||||
type: ['stack'],
|
||||
title: {
|
||||
stack: i18n.t('overall.toolBox.stack')
|
||||
},
|
||||
iconStyle: {
|
||||
borderColor: '#7e7e7e'
|
||||
},
|
||||
emphasis: {
|
||||
borderColor: '#7e7e7e'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
@@ -18,9 +43,9 @@ export const chartTimeSeriesLineOption = {
|
||||
color: initColor(),
|
||||
grid: {
|
||||
left: 20,
|
||||
right: 20,
|
||||
top: 20,
|
||||
bottom: 10,
|
||||
right: 35,
|
||||
top: 35,
|
||||
bottom: 15,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
@@ -92,8 +117,18 @@ export const chartTimeSeriesLineOption = {
|
||||
useUTC: false // 使用本地时间
|
||||
}
|
||||
export const chartTimeSeriesAreaOption = {
|
||||
|
||||
...chartTimeSeriesLineOption,
|
||||
series: [{
|
||||
...chartTimeSeriesLineOption.series[0],
|
||||
areaStyle: {}
|
||||
}]
|
||||
}
|
||||
export const chartTimeSeriesScatterOption = {
|
||||
|
||||
...chartTimeSeriesLineOption,
|
||||
toolbox: {},
|
||||
series: [{
|
||||
name: '',
|
||||
type: 'scatter',
|
||||
data: []
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import {randomcolor} from "@/components/common/js/radomcolor/randomcolor";
|
||||
export function getOption (type) {
|
||||
let chartOption = null
|
||||
switch (type) {
|
||||
case chartType.stackArea: {
|
||||
case chartType.area: {
|
||||
chartOption = lodash.cloneDeep(chartTimeSeriesAreaOption)
|
||||
break
|
||||
}
|
||||
@@ -48,7 +48,7 @@ export function getOption (type) {
|
||||
}
|
||||
|
||||
export function isTimeSeries (type) {
|
||||
return type === chartType.line || type === chartType.stackArea || type === chartType.point
|
||||
return type === chartType.line || type === chartType.area || type === chartType.point
|
||||
}
|
||||
|
||||
export function initColor (colorNum = 20) {
|
||||
|
||||
@@ -24,7 +24,22 @@ export default {
|
||||
s.name = this.handleLegend(chartInfo, data, expressionIndex, dataIndex, colorIndex)
|
||||
if (chartInfo.param.stack) { // 堆叠
|
||||
s.stack = 'Total'
|
||||
s.areaStyle = {}
|
||||
}
|
||||
if (!lodash.isEmpty(chartInfo.param.thresholds)) { // 阈值
|
||||
s.markLine = {
|
||||
symbol: 'circle',
|
||||
symbolSize: 5
|
||||
}
|
||||
s.markLine.data = chartInfo.param.thresholds.map(threshold => {
|
||||
return {
|
||||
yAxis: threshold.val,
|
||||
lineStyle: {
|
||||
color: threshold.color,
|
||||
width: 2,
|
||||
type: 'dotted'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
series.push(s)
|
||||
colorIndex++
|
||||
|
||||
@@ -17,11 +17,11 @@ const chartData = {
|
||||
height: 6,
|
||||
updateBy: 1,
|
||||
updateAt: '2021-11-10 07:06:09',
|
||||
type: 'line',
|
||||
type: 'area',
|
||||
unit: 2,
|
||||
weight: 0,
|
||||
param: '{' +
|
||||
' "style":"line",' +
|
||||
' "style":"area",' +
|
||||
' "stack":false,' +
|
||||
' "legend":{' +
|
||||
' "placement":"bottom",' +
|
||||
@@ -29,10 +29,10 @@ const chartData = {
|
||||
' },' +
|
||||
' "thresholds":[{' +
|
||||
' "color":"#eee",' +
|
||||
' "val":"10.1"' +
|
||||
' "val":"0.9"' +
|
||||
' },{' +
|
||||
' "color":"#aaa",' +
|
||||
' "val":"base"' +
|
||||
' "val":"1.1"' +
|
||||
' }],' +
|
||||
' "nullType":"zero"' +
|
||||
'}',
|
||||
@@ -130,22 +130,22 @@ const chartData = {
|
||||
height: 4,
|
||||
updateBy: 1,
|
||||
updateAt: '2021-11-10 09:05:13',
|
||||
type: 'line',
|
||||
type: 'point',
|
||||
unit: 2,
|
||||
weight: 1,
|
||||
param: '{' +
|
||||
' "style":"line",' +
|
||||
' "stack":true,' +
|
||||
' "style":"point",' +
|
||||
' "stack":false,' +
|
||||
' "legend":{' +
|
||||
' "placement":"right"' +
|
||||
// ' "values":["min","max","avg","first","last","total"]' +
|
||||
' },' +
|
||||
' "thresholds":[{' +
|
||||
' "color":"#eee",' +
|
||||
' "val":"10.1"' +
|
||||
' "color":"#ff0000",' +
|
||||
' "val":"100"' +
|
||||
' },{' +
|
||||
' "color":"#aaa",' +
|
||||
' "val":"base"' +
|
||||
' "color":"#00ff00",' +
|
||||
' "val":"250"' +
|
||||
' }],' +
|
||||
' "nullType":"zero"' +
|
||||
'}',
|
||||
|
||||
@@ -23,6 +23,7 @@ export function getChart (key) {
|
||||
}
|
||||
|
||||
export function setChart (key, value) {
|
||||
chartCache[`chart${key}`] && chartCache[`chart${key}`].dispose()
|
||||
chartCache[`chart${key}`] = value
|
||||
}
|
||||
const hexagonCache = {}
|
||||
|
||||
@@ -388,7 +388,7 @@ export const chartDataSource = [
|
||||
|
||||
export const chartType = {
|
||||
line: 'line',
|
||||
stackArea: 'stackArea',
|
||||
area: 'area',
|
||||
point: 'point',
|
||||
bar: 'bar',
|
||||
table: 'table',
|
||||
|
||||
Reference in New Issue
Block a user