diff --git a/nezha-fronted/src/assets/css/components/chart/chart.scss b/nezha-fronted/src/assets/css/components/chart/chart.scss index 921c8f3ee..426dffe62 100644 --- a/nezha-fronted/src/assets/css/components/chart/chart.scss +++ b/nezha-fronted/src/assets/css/components/chart/chart.scss @@ -721,7 +721,6 @@ pointer-events: none !important; } } - .foreign{ overflow: visible; .foreign-label-wrap{ @@ -733,15 +732,13 @@ align-items: center; } } - .funnel-label{ cursor: pointer; pointer-events: auto; line-height: 16px; color: $--color-text-primary; } - -.doughnut-label{ +.doughnut-label,.rose-label{ cursor: pointer; pointer-events: auto; font-size: 12px; diff --git a/nezha-fronted/src/components/chart/ChartScreenHeader.vue b/nezha-fronted/src/components/chart/ChartScreenHeader.vue index c84238e87..d2e9af158 100644 --- a/nezha-fronted/src/components/chart/ChartScreenHeader.vue +++ b/nezha-fronted/src/components/chart/ChartScreenHeader.vue @@ -136,6 +136,7 @@ export default { case 'gauge' : case 'pie' : case 'doughnut' : + case 'rose' : case 'treemap' : case 'log' : case 'hexagon' : diff --git a/nezha-fronted/src/components/chart/chart.vue b/nezha-fronted/src/components/chart/chart.vue index 0c89c035a..55772efc3 100644 --- a/nezha-fronted/src/components/chart/chart.vue +++ b/nezha-fronted/src/components/chart/chart.vue @@ -36,6 +36,15 @@ :is-fullscreen="isFullscreen" @chartIsNoData="chartIsNoData" > + -
+
@@ -120,7 +120,7 @@ export default { 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) this.doughnutData.push({ - value: value, + value: Number(value), realValue: value, showValue: showValue, name: legend.name, @@ -141,7 +141,6 @@ export default { this.$emit('chartIsNoData', this.isNoData) }, drawDoughnutChart (animate) { - this.dispose() const svgDom = document.getElementById(`chart-canvas-${this.chartId}`) if (!svgDom) { return false @@ -160,8 +159,17 @@ export default { const width = svgDom.getBoundingClientRect().width const height = svgDom.getBoundingClientRect().height - this.svg = d3.select(`#chart-canvas-${this.chartId}`).append('svg').attr('height', height).attr('width', width).attr('viewBox', [-width / 2, -height / 2, width, height]).style('display', 'block') - const chart = this.svg.append('g') + let chart + if (this.svg) { + chart = this.svg.select('g') + } else { + this.svg = d3.select(`#chart-canvas-${this.chartId}`).append('svg').style('display', 'block') + chart = this.svg.append('g') + } + this.svg + .attr('width', width) + .attr('height', height) + .attr('viewBox', [-width / 2, -height / 2, width, height]) const outerRadius = (Math.min(width, height) / 2) * 0.6 // outer radius of pie, in pixels const innerRadius = outerRadius * 0.67 // inner radius of pie, in pixels (non-zero for donut) @@ -174,15 +182,15 @@ export default { const arcs = pie(doughnutData) function doughnutOver (e, d) { - d3.select(chart.selectAll('path').nodes()[d.index]) + chart.select('.path-' + d.index) .transition() .attr('d', d3.arc() .innerRadius(innerRadius) - .outerRadius(outerRadius * 1.05) + .outerRadius(outerRadius * 1.06) ) } function doughnutOut (e, d) { - d3.select(chart.selectAll('path').nodes()[d.index]) + chart.select('.path-' + d.index) .transition() .attr('d', d3.arc() .innerRadius(innerRadius) @@ -190,28 +198,30 @@ export default { ) } - const that = this // 图形 chart.selectAll('path') - .data(arcs) + .data(arcs.filter(function (d) { + return d.data.value + })) .join('path') .attr('fill', d => d.data.background) .attr('d', arc) + .attr('class', (d) => 'path-' + d.index) .style('cursor', 'pointer') .classed('no-events', true) .on('mouseover', doughnutOver) .on('mouseout', doughnutOut) - .on('mouseenter', that.doughnutEnter) - .on('mousemove', that.doughnutMove) - .on('mouseleave', that.doughnutLeave) + .on('mouseenter', this.doughnutEnter) + .on('mousemove', this.doughnutMove) + .on('mouseleave', this.doughnutLeave) .transition().duration(animate === true ? 600 : 0) - .attrTween('d', (d) => { + .attrTween('d', function (d) { let currentArc = this._current if (!currentArc) { currentArc = { startAngle: 0, endAngle: 0 } } const i = d3.interpolate(currentArc, d) - this._current = i(0) // 当饼图更新时,从当前角度过渡到新角度 + this._current = i(1) // 当饼图更新时,从当前角度过渡到新角度 return function (t) { return arc(i(t)) } @@ -243,8 +253,9 @@ export default { d3.select(this).classed('no-events', false) }) }, + // 处理label - formatterLabel ({ data }) { + formatterLabel ({ data }) { let str = '' let valueStr = '' if (this.chartInfo.param.text === 'all') { @@ -327,7 +338,7 @@ export default { this.tooltip.x = e.pageX + 15 } }, - clickLegendDoughnut (isGrey) { + clickLegendD3 (isGrey) { const data = this.doughnutData.filter((item, i) => !isGrey[i]) this.selectData = this.$loadsh.cloneDeep(data) this.drawDoughnutChart(true) diff --git a/nezha-fronted/src/components/chart/chart/chartPie.vue b/nezha-fronted/src/components/chart/chart/chartPie.vue index bcbe1afba..b937d6876 100644 --- a/nezha-fronted/src/components/chart/chart/chartPie.vue +++ b/nezha-fronted/src/components/chart/chart/chartPie.vue @@ -2,7 +2,7 @@
diff --git a/nezha-fronted/src/components/chart/chart/chartRose.vue b/nezha-fronted/src/components/chart/chart/chartRose.vue new file mode 100644 index 000000000..ec41f99c0 --- /dev/null +++ b/nezha-fronted/src/components/chart/chart/chartRose.vue @@ -0,0 +1,395 @@ + + + diff --git a/nezha-fronted/src/components/chart/chart/legend.vue b/nezha-fronted/src/components/chart/chart/legend.vue index 9da175c94..73b8ba612 100644 --- a/nezha-fronted/src/components/chart/chart/legend.vue +++ b/nezha-fronted/src/components/chart/chart/legend.vue @@ -139,8 +139,8 @@ export default { this.clickLegendTreemap(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) return } - if (this.chartInfo.type === 'doughnut') { - this.clickLegendDoughnut(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) + if (this.chartInfo.type === 'doughnut' || this.chartInfo.type === 'rose') { + this.clickLegendD3(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) return } @@ -232,7 +232,7 @@ export default { }) } }, - clickLegendDoughnut (legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) { + clickLegendD3 (legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) { if (!hasGrey) { // 1.除当前legend外全置灰 this.isGrey = this.isGrey.map((g, i) => i !== index) } else if (currentIsTheOnlyOneHighlight) { // 2.全高亮 @@ -240,7 +240,7 @@ export default { } else { // 对应高亮 this.$set(this.isGrey, index, !this.isGrey[index]) } - this.$emit('clickLegendDoughnut', this.isGrey) + this.$emit('clickLegendD3', this.isGrey) }, // 四舍五入保留2位小数(不够位数,则用0替补) keepTwoDecimalFull (num) { diff --git a/nezha-fronted/src/components/chart/chart/tools.js b/nezha-fronted/src/components/chart/chart/tools.js index d715b36cb..bf17cd1f4 100644 --- a/nezha-fronted/src/components/chart/chart/tools.js +++ b/nezha-fronted/src/components/chart/chart/tools.js @@ -76,6 +76,9 @@ export function isChartPie (type) { export function isDoughnut (type) { return type === chartType.doughnut } +export function isRose (type) { + return type === chartType.rose +} export function isChartBar (type) { return type === chartType.bar } diff --git a/nezha-fronted/src/components/common/js/constants.js b/nezha-fronted/src/components/common/js/constants.js index fbb47076c..b53e90f6d 100644 --- a/nezha-fronted/src/components/common/js/constants.js +++ b/nezha-fronted/src/components/common/js/constants.js @@ -289,6 +289,10 @@ export const chart = { value: 'doughnut', label: i18n.t('dashboard.dashboard.chartForm.typeVal.doughnut.label') }, + { + value: 'rose', + label: i18n.t('dashboard.dashboard.chartForm.typeVal.rose.label') + }, { value: 'table', label: i18n.t('dashboard.dashboard.chartForm.typeVal.table.label') @@ -475,6 +479,7 @@ export const chartType = { gauge: 'gauge', pie: 'pie', doughnut: 'doughnut', + rose: 'rose', treemap: 'treemap', log: 'log', text: 'text', diff --git a/nezha-fronted/src/components/common/rightBox/chart/chartConfig.vue b/nezha-fronted/src/components/common/rightBox/chart/chartConfig.vue index 7b88b2573..8dffebfcf 100644 --- a/nezha-fronted/src/components/common/rightBox/chart/chartConfig.vue +++ b/nezha-fronted/src/components/common/rightBox/chart/chartConfig.vue @@ -1272,7 +1272,8 @@ export default { case 'treemap': case 'pie': case 'doughnut': - if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut') { + case 'rose': + if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut' || this.oldType === 'rose') { break } this.chartConfig.param = { diff --git a/nezha-fronted/src/components/common/rightBox/chart/chartTypeShow.js b/nezha-fronted/src/components/common/rightBox/chart/chartTypeShow.js index 7eb5fcfcd..1311170bd 100644 --- a/nezha-fronted/src/components/common/rightBox/chart/chartTypeShow.js +++ b/nezha-fronted/src/components/common/rightBox/chart/chartTypeShow.js @@ -56,6 +56,7 @@ export default { case 'gauge': case 'pie': case 'doughnut': + case 'rose': return false default: return false } @@ -74,6 +75,7 @@ export default { case 'gauge': case 'pie': case 'doughnut': + case 'rose': case 'bubble': case 'rank': case 'sankey': @@ -90,6 +92,7 @@ export default { case 'treemap': case 'pie': case 'doughnut': + case 'rose': case 'bar': return true case 'table': @@ -113,6 +116,7 @@ export default { case 'treemap': case 'pie': case 'doughnut': + case 'rose': case 'bar': return false default: return false @@ -141,6 +145,7 @@ export default { case 'treemap': case 'pie': case 'doughnut': + case 'rose': case 'bubble': case 'rank': case 'sankey': @@ -156,6 +161,7 @@ export default { case 'treemap': case 'pie': case 'doughnut': + case 'rose': case 'stat': case 'hexagon': case 'gauge': @@ -174,6 +180,7 @@ export default { case 'treemap': case 'pie': case 'doughnut': + case 'rose': case 'stat': case 'hexagon': case 'gauge': @@ -210,6 +217,7 @@ export default { case 'treemap': case 'pie': case 'doughnut': + case 'rose': case 'stat': case 'hexagon': case 'gauge': diff --git a/nezha-fronted/src/components/common/rightBox/chart/publicConfig.js b/nezha-fronted/src/components/common/rightBox/chart/publicConfig.js index 58b58519d..70c00e494 100644 --- a/nezha-fronted/src/components/common/rightBox/chart/publicConfig.js +++ b/nezha-fronted/src/components/common/rightBox/chart/publicConfig.js @@ -251,6 +251,10 @@ export default { id: 'doughnut', name: this.$t('dashboard.dashboard.chartForm.typeVal.doughnut.label') }, + { + id: 'rose', + name: this.$t('dashboard.dashboard.chartForm.typeVal.rose.label') + }, { id: 'bubble', name: this.$t('dashboard.dashboard.chartForm.typeVal.bubble.label') @@ -314,6 +318,10 @@ export default { id: 'doughnut', name: this.$t('dashboard.dashboard.chartForm.typeVal.doughnut.label') }, + { + id: 'rose', + name: this.$t('dashboard.dashboard.chartForm.typeVal.rose.label') + }, { id: 'bubble', name: this.$t('dashboard.dashboard.chartForm.typeVal.bubble.label') diff --git a/nezha-fronted/src/components/common/rightBox/chart/systemChartConfig.vue b/nezha-fronted/src/components/common/rightBox/chart/systemChartConfig.vue index 37e36af08..39a2c8917 100644 --- a/nezha-fronted/src/components/common/rightBox/chart/systemChartConfig.vue +++ b/nezha-fronted/src/components/common/rightBox/chart/systemChartConfig.vue @@ -894,6 +894,10 @@ export default { id: 'doughnut', name: this.$t('dashboard.dashboard.chartForm.typeVal.doughnut.label') }, + { + id: 'rose', + name: this.$t('dashboard.dashboard.chartForm.typeVal.rose.label') + }, { id: 'bubble', name: this.$t('dashboard.dashboard.chartForm.typeVal.bubble.label') @@ -1006,7 +1010,8 @@ export default { case 'treemap': case 'pie': case 'doughnut': - if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut') { + case 'rose': + if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut' || this.oldType === 'rose') { break } this.chartConfig.param = {