forked from github/dataease
feat(图表-词云图): 支持自定义数据区间
This commit is contained in:
parent
ee48b0236d
commit
b3fd99036c
@ -705,6 +705,28 @@ declare interface ChartMiscAttr {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 词云图轴值配置
|
||||
*/
|
||||
wordCloudAxisValueRange: {
|
||||
/**
|
||||
* 自动轴值
|
||||
*/
|
||||
auto: boolean
|
||||
/**
|
||||
* 最小值
|
||||
*/
|
||||
min: number
|
||||
/**
|
||||
* 最大值
|
||||
*/
|
||||
max: number
|
||||
/**
|
||||
* 轴值字段
|
||||
*/
|
||||
fieldId: string
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 动态极值配置
|
||||
|
@ -318,29 +318,32 @@ export function recursionTransObj(template, infoObj, scale, terminal) {
|
||||
for (const templateKey in template) {
|
||||
// 如果是数组 进行赋值计算
|
||||
if (template[templateKey] instanceof Array) {
|
||||
template[templateKey].forEach(templateProp => {
|
||||
if (
|
||||
infoObj[templateKey] &&
|
||||
(infoObj[templateKey][templateProp] || infoObj[templateKey].length)
|
||||
) {
|
||||
// 移动端特殊属性值设置
|
||||
if (terminal === 'mobile' && mobileSpecialProps[templateProp] !== undefined) {
|
||||
infoObj[templateKey][templateProp] = mobileSpecialProps[templateProp]
|
||||
} else {
|
||||
// 数组依次设置
|
||||
if (infoObj[templateKey] instanceof Array) {
|
||||
infoObj[templateKey].forEach(v => {
|
||||
v[templateProp] = getScaleValue(v[templateProp], scale)
|
||||
})
|
||||
// 词云图的大小区间,不需要缩放
|
||||
template[templateKey]
|
||||
.filter(field => field !== 'wordSizeRange')
|
||||
.forEach(templateProp => {
|
||||
if (
|
||||
infoObj[templateKey] &&
|
||||
(infoObj[templateKey][templateProp] || infoObj[templateKey].length)
|
||||
) {
|
||||
// 移动端特殊属性值设置
|
||||
if (terminal === 'mobile' && mobileSpecialProps[templateProp] !== undefined) {
|
||||
infoObj[templateKey][templateProp] = mobileSpecialProps[templateProp]
|
||||
} else {
|
||||
infoObj[templateKey][templateProp] = getScaleValue(
|
||||
infoObj[templateKey][templateProp],
|
||||
scale
|
||||
)
|
||||
// 数组依次设置
|
||||
if (infoObj[templateKey] instanceof Array) {
|
||||
infoObj[templateKey].forEach(v => {
|
||||
v[templateProp] = getScaleValue(v[templateProp], scale)
|
||||
})
|
||||
} else {
|
||||
infoObj[templateKey][templateProp] = getScaleValue(
|
||||
infoObj[templateKey][templateProp],
|
||||
scale
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
} else if (typeof template[templateKey] === 'string') {
|
||||
// 一级字段为字符串直接赋值
|
||||
infoObj[templateKey] = getScaleValue(infoObj[templateKey], scale)
|
||||
|
@ -5,6 +5,7 @@ import { DEFAULT_MISC } from '@/views/chart/components/editor/util/chart'
|
||||
import { ElMessage, ElRow } from 'element-plus-secondary'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
import { cloneDeep, defaultsDeep } from 'lodash-es'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -18,6 +19,10 @@ const props = withDefaults(
|
||||
{ themes: 'dark' }
|
||||
)
|
||||
|
||||
useEmitt({
|
||||
name: 'word-cloud-default-data-range',
|
||||
callback: args => wordCloudDefaultDataRange(args)
|
||||
})
|
||||
const emit = defineEmits(['onMiscChange'])
|
||||
|
||||
watch(
|
||||
@ -175,7 +180,11 @@ const isValidField = field => {
|
||||
}
|
||||
|
||||
const showProperty = prop => props.propertyInner?.includes(prop)
|
||||
|
||||
const wordCloudDefaultDataRange = args => {
|
||||
state.miscForm.wordCloudAxisValueRange.max = args.data.max
|
||||
state.miscForm.wordCloudAxisValueRange.min = args.data.min
|
||||
state.miscForm.wordCloudAxisValueRange.fieldId = props.chart.yAxis?.[0]?.id
|
||||
}
|
||||
onMounted(() => {
|
||||
initField()
|
||||
init()
|
||||
@ -561,35 +570,109 @@ onMounted(() => {
|
||||
<!--liquid-end-->
|
||||
|
||||
<!-- word-cloud start -->
|
||||
<el-form-item
|
||||
v-show="showProperty('wordSizeRange')"
|
||||
class="form-item"
|
||||
:label="t('chart.word_size_range')"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-slider
|
||||
v-model="state.miscForm.wordSizeRange"
|
||||
range
|
||||
size="small"
|
||||
:effect="themes"
|
||||
:min="1"
|
||||
:max="100"
|
||||
@change="changeMisc('wordSizeRange')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="showProperty('wordSpacing')"
|
||||
class="form-item form-item-slider"
|
||||
:label="t('chart.word_spacing')"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-slider
|
||||
v-model="state.miscForm.wordSpacing"
|
||||
:min="0"
|
||||
:max="20"
|
||||
@change="changeMisc('wordSpacing')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<template v-if="showProperty('wordCloudAxisValueRange')">
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between">
|
||||
<label class="custom-form-item-label" :class="'custom-form-item-label--' + themes">
|
||||
{{ t('chart.axis_value') }}
|
||||
<el-tooltip class="item" :effect="toolTip" placement="top">
|
||||
<template #content><span v-html="t('chart.axis_tip')"></span></template>
|
||||
<span style="vertical-align: middle">
|
||||
<el-icon style="cursor: pointer">
|
||||
<Icon name="icon_info_outlined" />
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</label>
|
||||
|
||||
<el-form-item class="form-item" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="props.themes"
|
||||
v-model="state.miscForm.wordCloudAxisValueRange.auto"
|
||||
@change="changeMisc()"
|
||||
>
|
||||
{{ t('chart.axis_auto') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<template
|
||||
v-if="
|
||||
showProperty('wordCloudAxisValueRange') && !state.miscForm.wordCloudAxisValueRange.auto
|
||||
"
|
||||
>
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
:label="t('chart.axis_value_max')"
|
||||
>
|
||||
<el-input-number
|
||||
controls-position="right"
|
||||
:effect="props.themes"
|
||||
v-model="state.miscForm.wordCloudAxisValueRange.max"
|
||||
@change="changeMisc()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
:label="t('chart.axis_value_min')"
|
||||
>
|
||||
<el-input-number
|
||||
:effect="props.themes"
|
||||
controls-position="right"
|
||||
v-model="state.miscForm.wordCloudAxisValueRange.min"
|
||||
@change="changeMisc()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</template>
|
||||
<div class="alpha-setting" v-if="showProperty('wordSizeRange')">
|
||||
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
||||
{{ t('chart.word_size_range') }}
|
||||
</label>
|
||||
<el-row style="flex: 1" :gutter="8">
|
||||
<el-col :span="24">
|
||||
<el-form-item class="form-item alpha-slider" :class="'form-item-' + themes">
|
||||
<el-slider
|
||||
v-model="state.miscForm.wordSizeRange"
|
||||
range
|
||||
:effect="themes"
|
||||
:min="1"
|
||||
:max="100"
|
||||
@change="changeMisc()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<div class="alpha-setting" v-if="showProperty('wordSpacing')">
|
||||
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
||||
{{ t('chart.word_spacing') }}
|
||||
</label>
|
||||
<el-row style="flex: 1" :gutter="8">
|
||||
<el-col :span="24">
|
||||
<el-form-item
|
||||
v-show="showProperty('wordSpacing')"
|
||||
class="form-item alpha-slider"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-slider
|
||||
v-model="state.miscForm.wordSpacing"
|
||||
:min="0"
|
||||
:max="20"
|
||||
@change="changeMisc()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- word-cloud end -->
|
||||
</el-form>
|
||||
</template>
|
||||
@ -628,4 +711,34 @@ onMounted(() => {
|
||||
box-shadow: 0 0 0 1px rgb(245, 74, 69) inset !important;
|
||||
}
|
||||
}
|
||||
|
||||
.alpha-setting {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.alpha-slider {
|
||||
padding: 0 8px;
|
||||
:deep(.ed-slider__button-wrapper) {
|
||||
--ed-slider-button-wrapper-size: 36px;
|
||||
--ed-slider-button-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.alpha-label {
|
||||
padding-right: 8px;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
display: inline-flex;
|
||||
align-items: flex-start;
|
||||
|
||||
min-width: 56px;
|
||||
|
||||
&.dark {
|
||||
color: #a6a6a6;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -298,6 +298,12 @@ export const DEFAULT_MISC: ChartMiscAttr = {
|
||||
speed: 0.01
|
||||
}
|
||||
}
|
||||
},
|
||||
wordCloudAxisValueRange: {
|
||||
auto: true,
|
||||
min: 0,
|
||||
max: 0,
|
||||
fieldId: undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,9 @@ import {
|
||||
flow,
|
||||
getDynamicColorScale,
|
||||
getGeoJsonFile,
|
||||
setMapChartDefaultMaxAndMinValueByData,
|
||||
hexColorToRGBA,
|
||||
parseJson
|
||||
parseJson,
|
||||
getMaxAndMinValueByData
|
||||
} from '@/views/chart/components/js/util'
|
||||
import {
|
||||
handleGeoJson,
|
||||
@ -81,7 +81,7 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
if (!misc.mapAutoLegend && legend.show) {
|
||||
let minValue = misc.mapLegendMin
|
||||
let maxValue = misc.mapLegendMax
|
||||
setMapChartDefaultMaxAndMinValueByData(sourceData, maxValue, minValue, (max, min) => {
|
||||
getMaxAndMinValueByData(sourceData, 'value', maxValue, minValue, (max, min) => {
|
||||
maxValue = max
|
||||
minValue = min
|
||||
action({
|
||||
@ -202,7 +202,7 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
let maxValue = misc.mapLegendMax
|
||||
if (legend.show) {
|
||||
let mapLegendNumber = misc.mapLegendNumber
|
||||
setMapChartDefaultMaxAndMinValueByData(sourceData, maxValue, minValue, (max, min) => {
|
||||
getMaxAndMinValueByData(sourceData, 'value', maxValue, minValue, (max, min) => {
|
||||
maxValue = max
|
||||
minValue = min
|
||||
mapLegendNumber = 9
|
||||
|
@ -3,7 +3,12 @@ import {
|
||||
G2PlotDrawOptions
|
||||
} from '@/views/chart/components/js/panel/types/impl/g2plot'
|
||||
import type { WordCloud as G2WordCloud, WordCloudOptions } from '@antv/g2plot/esm/plots/word-cloud'
|
||||
import { flow, parseJson } from '@/views/chart/components/js/util'
|
||||
import {
|
||||
filterChartDataByRange,
|
||||
flow,
|
||||
getMaxAndMinValueByData,
|
||||
parseJson
|
||||
} from '@/views/chart/components/js/util'
|
||||
import { getPadding } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
@ -42,7 +47,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
'letterSpace',
|
||||
'fontShadow'
|
||||
],
|
||||
'misc-selector': ['wordSizeRange', 'wordSpacing'],
|
||||
'misc-selector': ['wordSizeRange', 'wordSpacing', 'wordCloudAxisValueRange'],
|
||||
'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'seriesTooltipFormatter', 'show']
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'yAxis', 'filter']
|
||||
@ -58,12 +63,35 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
setDataRange = (action, maxValue, minValue) => {
|
||||
action({
|
||||
from: 'word-cloud',
|
||||
data: {
|
||||
max: maxValue,
|
||||
min: minValue
|
||||
}
|
||||
})
|
||||
}
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2WordCloud>): Promise<G2WordCloud> {
|
||||
const { chart, container, action } = drawOptions
|
||||
if (chart?.data) {
|
||||
// data
|
||||
const data = chart.data.data
|
||||
let data = chart.data.data
|
||||
const { misc } = parseJson(chart.customAttr)
|
||||
let minValue = 0
|
||||
let maxValue = 0
|
||||
if (
|
||||
!misc.wordCloudAxisValueRange?.auto &&
|
||||
misc.wordCloudAxisValueRange?.fieldId === chart.yAxis[0].id
|
||||
) {
|
||||
minValue = misc.wordCloudAxisValueRange.min
|
||||
maxValue = misc.wordCloudAxisValueRange.max
|
||||
}
|
||||
getMaxAndMinValueByData(data ?? [], 'value', maxValue, minValue, (max, min) => {
|
||||
maxValue = max
|
||||
minValue = min
|
||||
})
|
||||
data = filterChartDataByRange(data ?? [], maxValue, minValue)
|
||||
// options
|
||||
const initOptions: WordCloudOptions = {
|
||||
data: data,
|
||||
@ -84,6 +112,12 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
const options = this.setupOptions(chart, initOptions)
|
||||
const { WordCloud: G2WordCloud } = await import('@antv/g2plot/esm/plots/word-cloud')
|
||||
const newChart = new G2WordCloud(container, options)
|
||||
newChart.on('click', () => {
|
||||
this.setDataRange(action, maxValue, minValue)
|
||||
})
|
||||
newChart.on('afterrender', () => {
|
||||
this.setDataRange(action, maxValue, minValue)
|
||||
})
|
||||
newChart.on('point:click', param => {
|
||||
action({ x: param.x, y: param.y, data: { data: param.data.data.datum } })
|
||||
})
|
||||
|
@ -609,24 +609,26 @@ export const filterChartDataByRange = (data: any[], maxValue: number, minValue:
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取地图默认最大最小值根据数据
|
||||
* 获取数据最大最小值
|
||||
* @param data
|
||||
* @param field 值字段
|
||||
* @param maxValue
|
||||
* @param minValue
|
||||
* @param callback
|
||||
*/
|
||||
export const setMapChartDefaultMaxAndMinValueByData = (
|
||||
export const getMaxAndMinValueByData = (
|
||||
data: any[],
|
||||
field: string,
|
||||
maxValue: number,
|
||||
minValue: number,
|
||||
callback: (max: number, min: number) => void
|
||||
) => {
|
||||
if (minValue === 0 && maxValue === 0) {
|
||||
const maxResult = data.reduce((max, current) => {
|
||||
return current.value > max ? current.value : max
|
||||
return current[field] > max ? current[field] : max
|
||||
}, Number.MIN_SAFE_INTEGER)
|
||||
const minResult = data.reduce((min, current) => {
|
||||
return current.value < min ? current.value : min
|
||||
return current[field] < min ? current[field] : min
|
||||
}, Number.MAX_SAFE_INTEGER)
|
||||
callback(maxResult, minResult)
|
||||
}
|
||||
|
@ -313,6 +313,10 @@ const action = param => {
|
||||
emitter.emit('map-default-range', param)
|
||||
return
|
||||
}
|
||||
if (param.from === 'word-cloud') {
|
||||
emitter.emit('word-cloud-default-data-range', param)
|
||||
return
|
||||
}
|
||||
state.pointParam = param.data
|
||||
// 点击
|
||||
pointClickTrans()
|
||||
|
Loading…
Reference in New Issue
Block a user