NEZ-2243 feat:排行图表样式调整

This commit is contained in:
zyh
2022-10-14 16:20:20 +08:00
parent 59854abfe4
commit 42cb90559e
4 changed files with 91 additions and 95 deletions

View File

@@ -19,6 +19,11 @@
<div style="display: inline-block">{{tooltip.value}}</div> <div style="display: inline-block">{{tooltip.value}}</div>
</div> </div>
</div> </div>
<div class="chart-canvas-tooltip-content">
<div>rank</div>
<div>{{tooltip.rank+1}}</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -27,7 +32,7 @@
import chartMixin from '@/components/chart/chartMixin' import chartMixin from '@/components/chart/chartMixin'
import chartFormat from '@/components/chart/chartFormat' import chartFormat from '@/components/chart/chartFormat'
import * as d3 from 'd3' import * as d3 from 'd3'
import { formatScientificNotation, getMetricTypeValue } from '@/components/common/js/tools' import { getMetricTypeValue } from '@/components/common/js/tools'
import chartDataFormat from '@/components/chart/chartDataFormat' import chartDataFormat from '@/components/chart/chartDataFormat'
import { initColor } from '@/components/chart/chart/tools' import { initColor } from '@/components/chart/chart/tools'
import lodash from 'lodash' import lodash from 'lodash'
@@ -57,6 +62,7 @@ export default {
title: 0, title: 0,
value: 0, value: 0,
mapping: {}, mapping: {},
rank: 0,
show: false show: false
} }
} }
@@ -85,6 +91,7 @@ export default {
originalDatas.forEach((originalData, expressionIndex) => { originalDatas.forEach((originalData, expressionIndex) => {
originalData.forEach((data, dataIndex) => { originalData.forEach((data, dataIndex) => {
const value = getMetricTypeValue(data.values, chartInfo.param.statistics) const value = getMetricTypeValue(data.values, chartInfo.param.statistics)
if (value != 0) {
const showValue = chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(value, null, -1, decimals) const showValue = chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(value, null, -1, decimals)
const mapping = this.selectMapping(value, chartInfo.param.valueMapping, chartInfo.param.enable && this.chartInfo.param.enable.valueMapping) const mapping = this.selectMapping(value, chartInfo.param.valueMapping, chartInfo.param.enable && this.chartInfo.param.enable.valueMapping)
const legend = this.handleLegend(chartInfo, data, expressionIndex, dataIndex, colorIndex) const legend = this.handleLegend(chartInfo, data, expressionIndex, dataIndex, colorIndex)
@@ -103,6 +110,7 @@ export default {
mapping: mapping mapping: mapping
}) })
colorIndex++ colorIndex++
}
}) })
}) })
}, },
@@ -119,14 +127,12 @@ export default {
const height = svgDom.getBoundingClientRect().height const height = svgDom.getBoundingClientRect().height
const bodyX = 50 const bodyX = 50
const bodyY = 50 const bodyY = 50
const bodyWidth = width - 2 * bodyX const bodyWidth = width - 3 * bodyX
const bodyHeight = height - 2 * bodyY const bodyHeight = height - 2 * bodyY
const svg = d3.select(`#rank-svg-${this.chartId}`) const svg = d3.select(`#rank-svg-${this.chartId}`)
// 从大到小排序 // 从大到小排序
let rankData = lodash.cloneDeep(this.rankData) let rankData = lodash.cloneDeep(this.rankData)
// 过滤掉为0的数据
rankData = rankData.filter(item => item.value != 0)
rankData.sort((a, b) => b.value - a.value) rankData.sort((a, b) => b.value - a.value)
rankData = rankData.map((item, index) => { rankData = rankData.map((item, index) => {
return { return {
@@ -144,8 +150,10 @@ export default {
const scaleY = d3.scaleBand() const scaleY = d3.scaleBand()
.domain(rankData.map((d) => d.rank).sort((a, b) => b - a)) .domain(rankData.map((d) => d.rank).sort((a, b) => b - a))
.range([bodyHeight, 0]) .range([bodyHeight, 0])
.paddingInner(0.3)
.paddingOuter(0.06) .paddingOuter(0.06)
.paddingInner(0.6)
const minWidth = 10
// 渲染柱形 // 渲染柱形
const bars = svg.append('g') const bars = svg.append('g')
@@ -159,32 +167,13 @@ export default {
.attr('y', (d) => scaleY(d.rank)) .attr('y', (d) => scaleY(d.rank))
.attr('height', scaleY.bandwidth()) .attr('height', scaleY.bandwidth())
.attr('fill', (d) => d.background) .attr('fill', (d) => d.background)
.attr('width', (d) => scaleX(d.value) > 10 ? scaleX(d.value) : 10) .attr('width', (d) => scaleX(d.value) > minWidth ? scaleX(d.value) : minWidth)
.style('cursor', 'pointer')
.on('mouseenter', this.rankEnter)
.on('mousemove', this.rankMove)
.on('mouseleave', this.rankLeave)
bars.exit().remove() bars.exit().remove()
// 坐标轴
const xAxis = d3.axisTop(scaleX)
.ticks(6)
.tickSize(-(bodyHeight))
// .tickSizeOuter(0)
// .tickSizeInner(0)
.tickFormat(d => {
const value = formatScientificNotation(d, 6)
let chartUnit = this.chartInfo.unit
chartUnit = chartUnit || 2
const unit = chartDataFormat.getUnit(chartUnit)
return unit.compute(value, null, -1, 2)
})
const ticks = svg.append('g')
.attr('class', 'xAxis')
.call(xAxis)
.attr('transform', `translate(${bodyX},${bodyY})`)
ticks.select('.tick:first-of-type text').remove()
ticks.selectAll('.tick text').attr('class', 'tickTest')
ticks.select('.tick:first-of-type line').attr('class', 'tickLineFirst')
ticks.selectAll('.tick:not(:first-of-type) line').attr('class', 'tickLine')
ticks.select('.domain').remove()
// 文本标签 // 文本标签
svg.append('g') svg.append('g')
.attr('transform', `translate(${bodyX},${bodyY})`) .attr('transform', `translate(${bodyX},${bodyY})`)
@@ -196,63 +185,59 @@ export default {
.on('mousemove', this.rankMove) .on('mousemove', this.rankMove)
.on('mouseleave', this.rankLeave) .on('mouseleave', this.rankLeave)
.html((d) => { .html((d) => {
let flag = true
// 判断柱子宽度和高度 // 判断柱子宽度和高度
if (scaleY.bandwidth() < 38 || scaleX(d.value) < 120) { if (scaleY.bandwidth() > 10) {
flag = false return this.rankFormatterLabel(d)
} }
return flag ? this.rankFormatterLabel(d) : ''
}) })
.attr('x', scaleX(0)) .attr('x', (d) => {
let x = 0
if (scaleX(d.value) > minWidth) {
x = scaleX(d.value) + 10
} else {
x = minWidth + 10
}
return x
})
.attr('y', (d) => scaleY(d.rank)) .attr('y', (d) => scaleY(d.rank))
.attr('height', scaleY.bandwidth()) .attr('height', scaleY.bandwidth())
.attr('width', (d) => scaleX(d.value) > 10 ? scaleX(d.value) : 10)
.style('cursor', 'pointer') .style('cursor', 'pointer')
.style('overflow', 'visible')
// 生成标签和矩形
svg.append('g')
.attr('transform', `translate(${bodyX},${bodyY})`)
.selectAll('text')
.data(rankData)
.enter()
.append('text')
.attr('x', 4)
.attr('y', d => scaleY(d.rank) - 12)
.text(d => {
if (this.chartInfo.param.text !== 'all' && this.chartInfo.param.text !== 'legend') {
return ''
}
const margin = scaleY(1) - scaleY(0) - scaleY.bandwidth()
if (margin > 30 || !margin) {
return d.alias
}
})
}) })
}, },
// 处理label // 处理label
rankFormatterLabel (data) { rankFormatterLabel (data) {
let str = ''
let valueStr = '' let valueStr = ''
if (this.chartInfo.param.text === 'all') { if (this.chartInfo.param.text === 'all') {
str += data.alias
valueStr = data.mapping && data.mapping.display ? this.handleDisplay(data.mapping.display, { ...data.labels, value: data.showValue }) : data.showValue valueStr = data.mapping && data.mapping.display ? this.handleDisplay(data.mapping.display, { ...data.labels, value: data.showValue }) : data.showValue
} }
if (this.chartInfo.param.text === 'value' || !this.chartInfo.param.text) { if (this.chartInfo.param.text === 'value' || !this.chartInfo.param.text) {
valueStr = data.mapping && data.mapping.display ? this.handleDisplay(data.mapping.display, { ...data.labels, value: data.showValue }) : data.showValue valueStr = data.mapping && data.mapping.display ? this.handleDisplay(data.mapping.display, { ...data.labels, value: data.showValue }) : data.showValue
} }
if (this.chartInfo.param.text === 'legend') { if (valueStr) {
str += data.alias
}
if (this.chartInfo.param.text === 'none') {
str += ''
}
if (str && valueStr) {
return ` return `
<div style="width:100%;height: 100%;display: flex;align-items: flex-end;justify-content: center;flex-direction: column;color:#000000"> <div style="width:auto;height: 100%;display: flex;justify-content: center;flex-direction: column;">
<p style="width:100%;padding:0 12px;box-sizing: border-box;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:right;color: ${data.mapping && data.mapping.color && data.mapping.color.text}"> <p class="chart-label" style="cursor:pointer;white-space: nowrap;color: ${data.mapping && data.mapping.color && data.mapping.color.text}">
<span>${str}</span>
</p>
<p style="width:100%;padding:0 12px;box-sizing: border-box;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:right;color: ${data.mapping && data.mapping.color && data.mapping.color.text}">
<i class="${data.mapping && data.mapping.icon}" style="color: ${data.mapping && data.mapping.color && data.mapping.color.icon};font-size:1em;"></i>
<span>${valueStr}</span>
</p>
</div>
`
} else if (str) {
return `
<div style="width:100%;height: 100%;display: flex;align-items: flex-end;justify-content: center;flex-direction: column;color:#000000">
<p style="width:100%;padding:0 12px;box-sizing: border-box;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:right;color: ${data.mapping && data.mapping.color && data.mapping.color.text}">
<i class="${data.mapping && data.mapping.icon}" style="color: ${data.mapping && data.mapping.color && data.mapping.color.icon};font-size:1em;"></i>
<span>${str}</span>
</p>
</div>
`
} else if (valueStr) {
return `
<div style="width:100%;height: 100%;display: flex;align-items: flex-end;justify-content: center;flex-direction: column;color:#000000">
<p style="width:100%;padding:0 12px;box-sizing: border-box;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:right;color: ${data.mapping && data.mapping.color && data.mapping.color.text}">
<i class="${data.mapping && data.mapping.icon}" style="color: ${data.mapping && data.mapping.color && data.mapping.color.icon};font-size:1em;"></i> <i class="${data.mapping && data.mapping.icon}" style="color: ${data.mapping && data.mapping.color && data.mapping.color.icon};font-size:1em;"></i>
<span>${valueStr}</span> <span>${valueStr}</span>
</p> </p>
@@ -265,6 +250,7 @@ export default {
this.tooltip.title = data.alias this.tooltip.title = data.alias
this.tooltip.value = data.showValue this.tooltip.value = data.showValue
this.tooltip.mapping = data.mapping this.tooltip.mapping = data.mapping
this.tooltip.rank = data.rank
this.tooltip.show = true this.tooltip.show = true
this.setPosition(e) this.setPosition(e)
}, },

View File

@@ -99,6 +99,7 @@ export default {
originalDatas.forEach((originalData) => { originalDatas.forEach((originalData) => {
originalData.forEach((data, dataIndex) => { originalData.forEach((data, dataIndex) => {
const value = getMetricTypeValue(data.values, chartInfo.param.statistics) const value = getMetricTypeValue(data.values, chartInfo.param.statistics)
if (value != 0) {
const obj = { const obj = {
value: value, value: value,
realValue: value, realValue: value,
@@ -110,6 +111,7 @@ export default {
obj.target = data.metric[chartInfo.param.targetLabel] obj.target = data.metric[chartInfo.param.targetLabel]
sankeyData.push(obj) sankeyData.push(obj)
} }
}
}) })
}) })

View File

@@ -705,6 +705,7 @@
:prop="'param.valueMapping.' + index + '.value'" :prop="'param.valueMapping.' + index + '.value'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="value"
> >
<el-input-number <el-input-number
:controls="false" :controls="false"
@@ -719,6 +720,7 @@
:prop="'param.valueMapping.' + index + '.from'" :prop="'param.valueMapping.' + index + '.from'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="from"
> >
<el-input-number <el-input-number
:controls="false" :controls="false"
@@ -733,6 +735,7 @@
:prop="'param.valueMapping.' + index + '.to'" :prop="'param.valueMapping.' + index + '.to'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="to"
> >
<el-input-number <el-input-number
:controls="false" :controls="false"
@@ -747,6 +750,7 @@
:prop="'param.valueMapping.' + index + '.regx'" :prop="'param.valueMapping.' + index + '.regx'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="regx"
> >
<el-input <el-input
size="small" size="small"

View File

@@ -620,6 +620,7 @@
:prop="'param.valueMapping.' + index + '.value'" :prop="'param.valueMapping.' + index + '.value'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="value"
> >
<el-input-number <el-input-number
:controls="false" :controls="false"
@@ -634,6 +635,7 @@
:prop="'param.valueMapping.' + index + '.from'" :prop="'param.valueMapping.' + index + '.from'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="from"
> >
<el-input-number <el-input-number
:controls="false" :controls="false"
@@ -648,6 +650,7 @@
:prop="'param.valueMapping.' + index + '.to'" :prop="'param.valueMapping.' + index + '.to'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="to"
> >
<el-input-number <el-input-number
:controls="false" :controls="false"
@@ -662,6 +665,7 @@
:prop="'param.valueMapping.' + index + '.regx'" :prop="'param.valueMapping.' + index + '.regx'"
:rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}" :rules="{ required: true, message: $t('validate.required'), trigger: 'blur'}"
class="thresholds-from-item" class="thresholds-from-item"
key="regx"
> >
<el-input <el-input
size="small" size="small"