占比图的提示

This commit is contained in:
jingna 2025-07-25 16:36:28 +08:00
parent a86e73f14b
commit 91edf326e7
3 changed files with 115 additions and 55 deletions

View File

@ -1,11 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
import icon_letterSpacing_outlined from '@/assets/svg/icon_letter-spacing_outlined.svg'
import icon_bold_outlined from '@/assets/svg/icon_bold_outlined.svg'
import icon_italic_outlined from '@/assets/svg/icon_italic_outlined.svg'
import icon_leftAlignment_outlined from '@/assets/svg/icon_left-alignment_outlined.svg'
import icon_centerAlignment_outlined from '@/assets/svg/icon_center-alignment_outlined.svg'
import icon_rightAlignment_outlined from '@/assets/svg/icon_right-alignment_outlined.svg'
import icon_edit_outlined from '@/assets/svg/icon_edit_outlined.svg'
import { PropType, computed, onMounted, reactive, toRefs, watch, nextTick, ref } from 'vue' import { PropType, computed, onMounted, reactive, toRefs, watch, nextTick, ref } from 'vue'
import { useAppearanceStoreWithOut } from '@/store/modules/appearance' import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
@ -167,8 +160,10 @@ watch(
</div> </div>
<div style="display: flex"> <div style="display: flex">
<el-form-item class="form-item" :class="'form-item-' + themes" :effect="themes" :label="'字体粗细'"> <el-form-item class="form-item" :class="'form-item-' + themes" :effect="themes" :label="'字体粗细'">
<el-input :effect="themes" v-model="item.fontWeight" size="small" <!-- <el-input :effect="themes" v-model="item.fontWeight" size="small"
:placeholder="'字体粗细'" :disabled="!item.show" @blur="changeTitleStyle('showContent')" /> :placeholder="'字体粗细'" :disabled="!item.show" @blur="changeTitleStyle('showContent')" /> -->
<el-input-number :min="100" :max="700" controls-position="right" :effect="themes" v-model="item.fontWeight" :placeholder="'字体粗细'"
:step="100" :disabled="!item.show" @change="changeTitleStyle('showContent')"/>
</el-form-item> </el-form-item>
</div> </div>
<div style="margin: 5px 0px;color: #D2D2D2;">文本位置</div> <div style="margin: 5px 0px;color: #D2D2D2;">文本位置</div>
@ -190,13 +185,17 @@ watch(
<div style="margin: 5px 0px;color: #D2D2D2;">文本偏移量</div> <div style="margin: 5px 0px;color: #D2D2D2;">文本偏移量</div>
<div style="display: flex"> <div style="display: flex">
<el-form-item class="form-item" :class="'form-item-' + themes" :effect="themes" :label="'X'"> <el-form-item class="form-item" :class="'form-item-' + themes" :effect="themes" :label="'X'">
<el-input :effect="themes" v-model="item.offsetX" :disabled="!item.show" size="small" :placeholder="''" <!-- <el-input :effect="themes" v-model="item.offsetX" :disabled="!item.show" size="small" :placeholder="''"
@blur="changeTitleStyle('showContent')" /> @blur="changeTitleStyle('showContent')" /> -->
<el-input-number :effect="themes" v-model="item.offsetX" :disabled="!item.show"
controls-position="right" :step="1" @change="changeTitleStyle('showContent')" />
</el-form-item> </el-form-item>
<el-form-item class="form-item" :class="'form-item-' + themes" :effect="themes" :label="'Y'" <el-form-item class="form-item" :class="'form-item-' + themes" :effect="themes" :label="'Y'"
style="margin-left: 10px;"> style="margin-left: 10px;">
<el-input :effect="themes" v-model="item.offsetY" :disabled="!item.show" size="small" :placeholder="''" <!-- <el-input :effect="themes" v-model="item.offsetY" :disabled="!item.show" size="small" :placeholder="''"
@blur="changeTitleStyle('showContent')" /> @blur="changeTitleStyle('showContent')" /> -->
<el-input-number :effect="themes" v-model="item.offsetY" :disabled="!item.show"
controls-position="right" :step="1" @change="changeTitleStyle('showContent')" />
</el-form-item> </el-form-item>
</div> </div>
</div> </div>

View File

@ -9,7 +9,9 @@ import {
setUpSingleDimensionSeriesColor setUpSingleDimensionSeriesColor
} from '@/views/chart/components/js/util' } from '@/views/chart/components/js/util'
import { getPadding } from '@/views/chart/components/js/panel/common/common_antv' import { getPadding } from '@/views/chart/components/js/panel/common/common_antv'
import { valueFormatter } from '@/views/chart/components/js/formatter'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
import isEmpty from 'lodash-es/isEmpty'
import { import {
PIE_AXIS_CONFIG, PIE_AXIS_CONFIG,
PIE_AXIS_TYPE, PIE_AXIS_TYPE,
@ -66,7 +68,6 @@ export class G2Pie extends G2ChartView {
} }
axisConfig = PIE_AXIS_CONFIG axisConfig = PIE_AXIS_CONFIG
constructor() { constructor() {
super('pie-proportion') super('pie-proportion')
this.name = 'pie-proportion' this.name = 'pie-proportion'
@ -76,7 +77,6 @@ export class G2Pie extends G2ChartView {
const element = document.getElementById(container) const element = document.getElementById(container)
const customAttr = parseJson(chart.customAttr) const customAttr = parseJson(chart.customAttr)
const customStyle = parseJson(chart.customStyle) const customStyle = parseJson(chart.customStyle)
console.log(chart,96564)
const innerRadius = customAttr.basicStyle.innerRadius ?? 60 const innerRadius = customAttr.basicStyle.innerRadius ?? 60
const data = cloneDeep(chart.data?.data || []) const data = cloneDeep(chart.data?.data || [])
const colorList = customAttr.basicStyle.colors.map(i => const colorList = customAttr.basicStyle.colors.map(i =>
@ -84,8 +84,7 @@ export class G2Pie extends G2ChartView {
) )
const g2 = new Chart({ const g2 = new Chart({
container, container,
autoFit: true, autoFit: true
height: 300
}) })
g2.coordinate('theta', { g2.coordinate('theta', {
radius: customAttr.basicStyle.radius / 100, radius: customAttr.basicStyle.radius / 100,
@ -94,33 +93,14 @@ export class G2Pie extends G2ChartView {
g2.data(data) g2.data(data)
g2.legend(false) g2.legend(false)
const formatterMap = customAttr.tooltip.seriesTooltipFormatter
?.filter(i => i.show)
.reduce((pre, next) => {
pre[next.id] = next
return pre
}, {}) as Record<string, SeriesFormatter>
if(customAttr.tooltip.show == true){ if(customAttr.tooltip.show == true){
g2.tooltip({ this.configTooltip(g2, customAttr, formatterMap);
showMarkers: false,
enterable:true,
showContent: (datum) => {
console.log(datum)
return !datum.some(item => item?.name === '其他');
},
domStyles: {
'g2-tooltip': {
backgroundColor: customAttr.tooltip.backgroundColor, // 背景色
color: customAttr.tooltip.color, // 文字颜色
boxShadow: '0 2px 2px rgba(0,0,0,0.15)', // 阴影
// borderRadius: '4px', // 圆角
// padding: '8px 12px' // 内边距
},
'g2-tooltip-title': {
fontSize: customAttr.tooltip.fontSize + 'px',
// fontWeight: 'bold',
// marginBottom: '4px'
},
'g2-tooltip-list-item': {
fontSize: customAttr.tooltip.fontSize + 'px'
}
}
})
}else{ }else{
g2.tooltip(false) g2.tooltip(false)
} }
@ -131,11 +111,15 @@ export class G2Pie extends G2ChartView {
eachView: (view, facet) => { eachView: (view, facet) => {
const data:any = facet.data const data:any = facet.data
let color let color
customAttr.basicStyle.seriesColor.forEach((item) => { if(customAttr.basicStyle.seriesColor.length>0){
if(data.name == item.name){ customAttr.basicStyle.seriesColor.forEach((item) => {
color = item.color if(data.name == item.name){
} color = item.color
}) }
})
}else{
color = colorList[0]
}
data.push({ name: '其他', value: 100 - data[0].value }) data.push({ name: '其他', value: 100 - data[0].value })
view.data(data) view.data(data)
view.coordinate('theta', { view.coordinate('theta', {
@ -148,11 +132,15 @@ export class G2Pie extends G2ChartView {
.position('value') .position('value')
.color('name', (name) => { .color('name', (name) => {
let colorval = '' let colorval = ''
customAttr.basicStyle.seriesColor.forEach((item) => { if(customAttr.basicStyle.seriesColor.length > 0){
if(name == item.name){ customAttr.basicStyle.seriesColor.forEach((item) => {
colorval = item.color if(name == item.name){
} colorval = item.color
}) }
})
}else{
colorval = colorList[0]
}
return name === '其他' ? customAttr.basicStyle.proportionBackgroundColor : colorval; return name === '其他' ? customAttr.basicStyle.proportionBackgroundColor : colorval;
}) })
.style({ .style({
@ -198,7 +186,7 @@ export class G2Pie extends G2ChartView {
g2.render() g2.render()
this.resizeObserver = new ResizeObserver(() => { this.resizeObserver = new ResizeObserver(() => {
g2.changeSize(element.offsetWidth, element.offsetHeight) g2.changeSize(element.offsetWidth, element.offsetHeight)
// g2.render() g2.render()
}) })
this.resizeObserver.observe(element) this.resizeObserver.observe(element)
@ -208,4 +196,77 @@ export class G2Pie extends G2ChartView {
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] { public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
return setUpSingleDimensionSeriesColor(chart, data) return setUpSingleDimensionSeriesColor(chart, data)
} }
protected configTooltip(g2: Chart, customAttr: CustomAttr, formatterMap: Record<string, SeriesFormatter>){
// 类型断言确保customAttr是ChartAttr类型
const attr = customAttr as ChartAttr;
g2.tooltip({
showMarkers: false,
enterable:true,
showContent: (datum) => {
return !datum.some(item => item?.name === '其他');
},
domStyles: {
'g2-tooltip': {
backgroundColor: attr.tooltip.backgroundColor, // 背景色
color: attr.tooltip.color, // 文字颜色
boxShadow: '0 2px 2px rgba(0,0,0,0.15)', // 阴影
// borderRadius: '4px', // 圆角
// padding: '8px 12px' // 内边距
},
'g2-tooltip-title': {
fontSize: attr.tooltip.fontSize + 'px',
// fontWeight: 'bold',
// marginBottom: '4px'
},
'g2-tooltip-list-item': {
fontSize: attr.tooltip.fontSize + 'px'
}
},
customContent: (title, data) => {
if (!data || data.length === 0) return null;
let tooltipContent = `<div style="padding: 8px; background: transparent; ">`;
tooltipContent += `<div style="font-weight: bold; margin-bottom: 10px;font-size:${attr.tooltip.fontSize + 'px'};">${data[0].name}</div>`;
// 勾选的提示信息 formatterMap data.dynamicTooltipValue id和值
let tooltipItems = data
if (attr.tooltip.seriesTooltipFormatter?.length) {
tooltipItems = data.filter(item => formatterMap[item.data.quotaList[0].id])
}
tooltipItems.forEach(item => {
const formatter = formatterMap[item.data.quotaList[0].id] ?? (data[0]?.data?.quotaList?.[0] || {})
const originValue = parseFloat(item.value as string)
const value = valueFormatter(originValue, formatter.formatterCfg)
const name = isEmpty(formatter.chartShowName) ? formatter.name : formatter.chartShowName
tooltipContent += `
<div style="display: flex; align-items: center;font-size:${attr.tooltip.fontSize + 'px'};">
<span style="width: 8px; height: 8px; background-color: ${item.color}; border-radius: 50%; margin-right: 8px;"></span>
<div>
<span> ${name}</span>
<span>: ${value}</span>
</div>
</div>
`;
})
const head = data[0]
head.data.dynamicTooltipValue?.forEach(item => {
const formatter = formatterMap[item.fieldId]
if (formatter) {
const value = valueFormatter(parseFloat(item.value), formatter.formatterCfg)
const name = isEmpty(formatter.chartShowName) ? formatter.name : formatter.chartShowName
tooltipContent += `
<div style="display: flex; align-items: center;margin-top:10px;font-size:${attr.tooltip.fontSize + 'px'}">
<span style="width: 8px; height: 8px; background-color: gray; border-radius: 50%; margin-right: 8px;"></span>
<div>
<span> ${name}</span>
<span>: ${value}</span>
</div>
</div>
`;
}
})
tooltipContent += '</div>';
return tooltipContent;
}
})
}
} }

View File

@ -255,7 +255,7 @@ const renderG2 = async (chart, chartView: G2ChartView<any, any>) => {
myChart = await chartView.drawChart({ myChart = await chartView.drawChart({
chartObj: myChart, chartObj: myChart,
container: containerId, container: containerId,
chart, chart: chart,
scale: 1, scale: 1,
action, action,
quadrantDefaultBaseline quadrantDefaultBaseline