Merge pull request #559 from dataease/pr@dev@feat_矩形树图

feat: 矩形树图
This commit is contained in:
XiaJunjie2020 2021-08-09 16:38:14 +08:00 committed by GitHub
commit 1d04c5c9fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 188 additions and 32 deletions

View File

@ -367,6 +367,9 @@ public class ChartViewService {
mapChart = transScatterData(xAxis, yAxis, view, data, extBubble);
} else if (StringUtils.containsIgnoreCase(view.getType(), "radar")) {
mapChart = transRadarChartData(xAxis, yAxis, view, data);
} else if (StringUtils.containsIgnoreCase(view.getType(), "text")
|| StringUtils.containsIgnoreCase(view.getType(), "gauge")) {
mapChart = transNormalChartData(xAxis, yAxis, view, data);
} else {
mapChart = transChartData(xAxis, yAxis, view, data);
}
@ -476,6 +479,44 @@ public class ChartViewService {
return map;
}
// 常规图形
private Map<String, Object> transNormalChartData(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, ChartViewWithBLOBs view, List<String[]> data) {
Map<String, Object> map = new HashMap<>();
List<String> x = new ArrayList<>();
List<Series> series = new ArrayList<>();
for (ChartViewFieldDTO y : yAxis) {
Series series1 = new Series();
series1.setName(y.getName());
series1.setType(view.getType());
series1.setData(new ArrayList<>());
series.add(series1);
}
for (String[] d : data) {
StringBuilder a = new StringBuilder();
for (int i = 0; i < xAxis.size(); i++) {
if (i == xAxis.size() - 1) {
a.append(d[i]);
} else {
a.append(d[i]).append("\n");
}
}
x.add(a.toString());
for (int i = xAxis.size(); i < xAxis.size() + yAxis.size(); i++) {
int j = i - xAxis.size();
try {
series.get(j).getData().add(new BigDecimal(StringUtils.isEmpty(d[i]) ? "0" : d[i]));
} catch (Exception e) {
series.get(j).getData().add(new BigDecimal(0));
}
}
}
map.put("x", x);
map.put("series", series);
return map;
}
// radar图
private Map<String, Object> transRadarChartData(List<ChartViewFieldDTO> xAxis, List<ChartViewFieldDTO> yAxis, ChartViewWithBLOBs view, List<String[]> data) {
Map<String, Object> map = new HashMap<>();

View File

@ -0,0 +1 @@
<svg t="1628490858856" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2380" width="200" height="200"><path d="M64 128h512v448H64z m0 512h512v256H64z m576-192h320v448H640z m0-320h320v256H640z" p-id="2381"></path></svg>

After

Width:  |  Height:  |  Size: 263 B

View File

@ -832,7 +832,11 @@ export default {
axis_label_rotate: 'Label Rotate',
chart_scatter_bubble: 'Bubble',
chart_scatter: 'Scatter',
bubble_size: 'Bubble Size'
bubble_size: 'Bubble Size',
chart_treemap: 'Tree Map',
drill: 'Drill',
drag_block_treemap_label: 'Color Label',
drag_block_treemap_size: 'Color Size'
},
dataset: {
sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default',

View File

@ -832,7 +832,11 @@ export default {
axis_label_rotate: '標簽角度',
chart_scatter_bubble: '氣泡圖',
chart_scatter: '散點圖',
bubble_size: '氣泡大小'
bubble_size: '氣泡大小',
chart_treemap: '矩形樹圖',
drill: '鉆取',
drag_block_treemap_label: '色塊標簽',
drag_block_treemap_size: '色塊大小'
},
dataset: {
sheet_warn: '有多個sheet頁面默認抽取第一個',

View File

@ -832,7 +832,11 @@ export default {
axis_label_rotate: '标签角度',
chart_scatter_bubble: '气泡图',
chart_scatter: '散点图',
bubble_size: '气泡大小'
bubble_size: '气泡大小',
chart_treemap: '矩形树图',
drill: '钻取',
drag_block_treemap_label: '色块标签',
drag_block_treemap_size: '色块大小'
},
dataset: {
sheet_warn: '有多个 Sheet 页,默认抽取第一个',

View File

@ -689,3 +689,39 @@ export const BASE_SCATTER = {
}
]
}
export const BASE_TREEMAP = {
title: {
text: '',
textStyle: {
fontWeight: 'normal'
}
},
grid: {
containLabel: true
},
tooltip: {},
legend: {
show: true,
type: 'scroll',
itemWidth: 10,
itemHeight: 10,
icon: 'rect'
},
series: [
{
// name: '',
type: 'treemap',
// radius: ['0%', '60%'],
// avoidLabelOverlap: false,
// emphasis: {
// itemStyle: {
// shadowBlur: 10,
// shadowOffsetX: 0,
// shadowColor: 'rgba(0, 0, 0, 0.5)'
// }
// },
data: []
}
]
}

View File

@ -31,8 +31,6 @@ export function baseFunnelOption(chart_option, chart) {
chart_option.series[0].label = customAttr.label
}
const valueArr = chart.data.series[0].data
// max value
chart_option.series[0].max = Math.max.apply(Math, valueArr)
for (let i = 0; i < valueArr.length; i++) {
// const y = {
// name: chart.data.x[i],
@ -44,7 +42,7 @@ export function baseFunnelOption(chart_option, chart) {
y.itemStyle = {
color: hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)
}
y.type = 'funnel'
// y.type = 'funnel'
chart_option.series[0].data.push(y)
}
}

View File

@ -0,0 +1,53 @@
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { componentStyle } from '../common/common'
export function baseTreemapOption(chart_option, chart) {
// 处理shape attr
let customAttr = {}
if (chart.customAttr) {
customAttr = JSON.parse(chart.customAttr)
if (customAttr.color) {
chart_option.color = customAttr.color.colors
}
// tooltip
if (customAttr.tooltip) {
const tooltip = JSON.parse(JSON.stringify(customAttr.tooltip))
const reg = new RegExp('\n', 'g')
tooltip.formatter = tooltip.formatter.replace(reg, '<br/>')
chart_option.tooltip = tooltip
}
}
// 处理data
if (chart.data) {
chart_option.title.text = chart.title
if (chart.data.series.length > 0) {
// chart_option.series[0].name = chart.data.series[0].name
// size
if (customAttr.size) {
// chart_option.series[0].radius = [customAttr.size.pieInnerRadius + '%', customAttr.size.pieOuterRadius + '%']
}
// label
if (customAttr.label) {
// chart_option.series[0].label = customAttr.label
}
const valueArr = chart.data.series[0].data
for (let i = 0; i < valueArr.length; i++) {
// const y = {
// name: chart.data.x[i],
// value: valueArr[i]
// }
const y = valueArr[i]
y.name = chart.data.x[i]
// color
y.itemStyle = {
color: hexColorToRGBA(customAttr.color.colors[i % 9], customAttr.color.alpha)
}
// y.type = 'treemap'
chart_option.series[0].data.push(y)
}
}
}
// console.log(chart_option);
componentStyle(chart_option, chart)
return chart_option
}

View File

@ -5,7 +5,7 @@
</template>
<script>
import { BASE_BAR, BASE_LINE, HORIZONTAL_BAR, BASE_PIE, BASE_FUNNEL, BASE_RADAR, BASE_GAUGE, BASE_MAP, BASE_SCATTER } from '../chart/chart'
import { BASE_BAR, BASE_LINE, HORIZONTAL_BAR, BASE_PIE, BASE_FUNNEL, BASE_RADAR, BASE_GAUGE, BASE_MAP, BASE_SCATTER, BASE_TREEMAP } from '../chart/chart'
import { baseBarOption, stackBarOption, horizontalBarOption, horizontalStackBarOption } from '../chart/bar/bar'
import { baseLineOption, stackLineOption } from '../chart/line/line'
import { basePieOption, rosePieOption } from '../chart/pie/pie'
@ -14,6 +14,7 @@ import { baseFunnelOption } from '../chart/funnel/funnel'
import { baseRadarOption } from '../chart/radar/radar'
import { baseGaugeOption } from '../chart/gauge/gauge'
import { baseScatterOption } from '../chart/scatter/scatter'
import { baseTreemapOption } from '../chart/treemap/treemap'
// import eventBus from '@/components/canvas/utils/eventBus'
import { uuid } from 'vue-uuid'
import { geoJson } from '@/api/map/map'
@ -98,6 +99,8 @@ export default {
chart_option = baseGaugeOption(JSON.parse(JSON.stringify(BASE_GAUGE)), chart)
} else if (chart.type === 'scatter') {
chart_option = baseScatterOption(JSON.parse(JSON.stringify(BASE_SCATTER)), chart)
} else if (chart.type === 'treemap') {
chart_option = baseTreemapOption(JSON.parse(JSON.stringify(BASE_TREEMAP)), chart)
}
if (chart.type === 'map') {
@ -145,6 +148,9 @@ export default {
window.onresize = function() {
chart.resize()
}
chart.on('click',function(param) {
console.log(param)
})
},
chartResize() {
//

View File

@ -163,23 +163,18 @@
<svg-icon icon-class="line-stack" class="chart-icon" />
</span>
</el-radio>
<el-radio value="pie" label="pie">
<span :title="$t('chart.chart_pie')">
<svg-icon icon-class="pie" class="chart-icon" />
<el-radio value="scatter" label="scatter">
<span :title="$t('chart.chart_scatter')">
<svg-icon icon-class="scatter" class="chart-icon" />
</span>
</el-radio>
<el-radio value="pie-rose" label="pie-rose">
<span :title="$t('chart.chart_pie_rose')">
<svg-icon icon-class="pie-rose" class="chart-icon" />
<el-radio value="map" label="map">
<span :title="$t('chart.chart_map')">
<svg-icon icon-class="map" class="chart-icon" />
</span>
</el-radio>
</div>
<div style="width: 100%;display: flex;display: -webkit-flex;justify-content: space-between;flex-direction: row;flex-wrap: wrap;">
<el-radio value="funnel" label="funnel">
<span :title="$t('chart.chart_funnel')">
<svg-icon icon-class="funnel" class="chart-icon" />
</span>
</el-radio>
<el-radio value="radar" label="radar">
<span :title="$t('chart.chart_radar')">
<svg-icon icon-class="radar" class="chart-icon" />
@ -190,19 +185,28 @@
<svg-icon icon-class="gauge" class="chart-icon" />
</span>
</el-radio>
<el-radio value="map" label="map">
<span :title="$t('chart.chart_map')">
<svg-icon icon-class="map" class="chart-icon" />
<el-radio value="pie" label="pie">
<span :title="$t('chart.chart_pie')">
<svg-icon icon-class="pie" class="chart-icon" />
</span>
</el-radio>
<el-radio value="scatter" label="scatter">
<span :title="$t('chart.chart_scatter')">
<svg-icon icon-class="scatter" class="chart-icon" />
<el-radio value="pie-rose" label="pie-rose">
<span :title="$t('chart.chart_pie_rose')">
<svg-icon icon-class="pie-rose" class="chart-icon" />
</span>
</el-radio>
<el-radio value="funnel" label="funnel">
<span :title="$t('chart.chart_funnel')">
<svg-icon icon-class="funnel" class="chart-icon" />
</span>
</el-radio>
</div>
<div style="width: 100%;display: flex;display: -webkit-flex;justify-content: space-between;flex-direction: row;flex-wrap: wrap;">
<el-radio value="" label="" disabled class="disabled-none-cursor"><svg-icon icon-class="" class="chart-icon" /></el-radio>
<el-radio value="treemap" label="treemap">
<span :title="$t('chart.chart_treemap')">
<svg-icon icon-class="treemap" class="chart-icon" />
</span>
</el-radio>
<el-radio value="" label="" disabled class="disabled-none-cursor"><svg-icon icon-class="" class="chart-icon" /></el-radio>
<el-radio value="" label="" disabled class="disabled-none-cursor"><svg-icon icon-class="" class="chart-icon" /></el-radio>
<el-radio value="" label="" disabled class="disabled-none-cursor"><svg-icon icon-class="" class="chart-icon" /></el-radio>
@ -213,7 +217,7 @@
</el-row>
<el-row style="color: #909399;">
<span>
<span v-show="chart.type && (chart.type.includes('pie') || chart.type.includes('funnel') || chart.type.includes('text') || chart.type.includes('gauge'))">
<span v-show="chart.type && (chart.type.includes('pie') || chart.type.includes('funnel') || chart.type.includes('text') || chart.type.includes('gauge') || chart.type.includes('treemap'))">
Tips: {{ $t('chart.only_one_quota') }}
</span>
<!-- <span v-show="chart.type && (chart.type.includes('text'))">-->
@ -245,7 +249,7 @@
</el-row>
<el-row class="padding-lr">
<span style="width: 80px;text-align: right;">
<span>钻取</span>
<span>{{ $t('chart.drill') }}</span>
/
<span>{{ $t('chart.dimension') }}</span>
</span>
@ -274,7 +278,8 @@
<span v-else-if="view.type && view.type.includes('pie')">{{ $t('chart.drag_block_pie_label') }}</span>
<span v-else-if="view.type && view.type.includes('funnel')">{{ $t('chart.drag_block_funnel_split') }}</span>
<span v-else-if="view.type && view.type.includes('radar')">{{ $t('chart.drag_block_radar_label') }}</span>
<span v-else-if="view.type && view.type.includes('map')">{{ $t('chart.area') }}</span>
<span v-else-if="view.type && view.type === 'map'">{{ $t('chart.area') }}</span>
<span v-else-if="view.type && view.type.includes('treemap')">{{ $t('chart.drag_block_treemap_label') }}</span>
/
<span>{{ $t('chart.dimension') }}</span>
</span>
@ -305,7 +310,8 @@
<span v-else-if="view.type && view.type.includes('radar')">{{ $t('chart.drag_block_radar_length') }}</span>
<span v-else-if="view.type && view.type.includes('gauge')">{{ $t('chart.drag_block_gauge_angel') }}</span>
<span v-else-if="view.type && view.type.includes('text')">{{ $t('chart.drag_block_label_value') }}</span>
<span v-else-if="view.type && view.type.includes('map')">{{ $t('chart.chart_data') }}</span>
<span v-else-if="view.type && view.type === 'map'">{{ $t('chart.chart_data') }}</span>
<span v-else-if="view.type && view.type.includes('tree')">{{ $t('chart.drag_block_treemap_size') }}</span>
/
<span>{{ $t('chart.quota') }}</span>
</span>
@ -421,10 +427,10 @@
<el-collapse-item name="color" :title="$t('chart.color')">
<color-selector :param="param" class="attr-selector" :chart="chart" @onColorChange="onColorChange" />
</el-collapse-item>
<el-collapse-item v-show="chart.type !== 'map'" name="size" :title="$t('chart.size')">
<el-collapse-item v-show="chart.type !== 'map' && chart.type !== 'treemap'" name="size" :title="$t('chart.size')">
<size-selector :param="param" class="attr-selector" :chart="chart" @onSizeChange="onSizeChange" />
</el-collapse-item>
<el-collapse-item v-show="!view.type.includes('table') && !view.type.includes('text')" name="label" :title="$t('chart.label')">
<el-collapse-item v-show="!view.type.includes('table') && !view.type.includes('text') && view.type !== 'treemap'" name="label" :title="$t('chart.label')">
<label-selector :param="param" class="attr-selector" :chart="chart" @onLabelChange="onLabelChange" />
</el-collapse-item>
<el-collapse-item v-show="!view.type.includes('table') && !view.type.includes('text')" name="tooltip" :title="$t('chart.tooltip')">
@ -453,7 +459,7 @@
<el-collapse-item name="title" :title="$t('chart.title')">
<title-selector :param="param" class="attr-selector" :chart="chart" @onTextChange="onTextChange" />
</el-collapse-item>
<el-collapse-item v-show="view.type && !view.type.includes('map') && !view.type.includes('table') && !view.type.includes('text')" name="legend" :title="$t('chart.legend')">
<el-collapse-item v-show="view.type && view.type !== 'map' && !view.type.includes('table') && !view.type.includes('text') && chart.type !== 'treemap'" name="legend" :title="$t('chart.legend')">
<legend-selector :param="param" class="attr-selector" :chart="chart" @onLegendChange="onLegendChange" />
</el-collapse-item>
<el-collapse-item name="background" :title="$t('chart.background')">
@ -864,6 +870,9 @@ export default {
if (view.type === 'line-stack' && trigger === 'chart') {
view.customAttr.size.lineArea = true
}
if (view.type === 'treemap' && trigger === 'chart') {
view.customAttr.label.show = true
}
view.customFilter.forEach(function(ele) {
if (ele && !ele.filter) {
ele.filter = []