环形占比图
This commit is contained in:
parent
ad1fa0ee92
commit
3f7f96bf2c
@ -76,6 +76,7 @@ const iconChartMap = {
|
|||||||
'percentage-bar-stack': percentageBarStack,
|
'percentage-bar-stack': percentageBarStack,
|
||||||
'pie-donut-rose': pieDonutRose,
|
'pie-donut-rose': pieDonutRose,
|
||||||
'pie-donut': pieDonut,
|
'pie-donut': pieDonut,
|
||||||
|
'pie-proportion': pieDonut,
|
||||||
'pie-rose': pieRose,
|
'pie-rose': pieRose,
|
||||||
pie: pie,
|
pie: pie,
|
||||||
'progress-bar': progressBar,
|
'progress-bar': progressBar,
|
||||||
|
@ -1440,6 +1440,7 @@ export default {
|
|||||||
chart_area_stack: 'Stacked line chart',
|
chart_area_stack: 'Stacked line chart',
|
||||||
chart_pie: 'Pie chart',
|
chart_pie: 'Pie chart',
|
||||||
chart_pie_donut: 'Ring chart',
|
chart_pie_donut: 'Ring chart',
|
||||||
|
chart_pie_proportion: 'Ring proportion chart',
|
||||||
chart_pie_rose: 'Rose chart',
|
chart_pie_rose: 'Rose chart',
|
||||||
chart_pie_donut_rose: 'Rose ring chart',
|
chart_pie_donut_rose: 'Rose ring chart',
|
||||||
chart_funnel: 'Funnel chart',
|
chart_funnel: 'Funnel chart',
|
||||||
|
@ -1402,6 +1402,7 @@ export default {
|
|||||||
chart_area_stack: '堆疊折線圖',
|
chart_area_stack: '堆疊折線圖',
|
||||||
chart_pie: '餅圖',
|
chart_pie: '餅圖',
|
||||||
chart_pie_donut: '環形圖',
|
chart_pie_donut: '環形圖',
|
||||||
|
chart_pie_proportion: '环形占比图',
|
||||||
chart_pie_rose: '玫瑰圖',
|
chart_pie_rose: '玫瑰圖',
|
||||||
chart_pie_donut_rose: '玫瑰環形圖',
|
chart_pie_donut_rose: '玫瑰環形圖',
|
||||||
chart_funnel: '漏斗圖',
|
chart_funnel: '漏斗圖',
|
||||||
|
@ -1407,6 +1407,7 @@ export default {
|
|||||||
chart_area_stack: '堆叠折线图',
|
chart_area_stack: '堆叠折线图',
|
||||||
chart_pie: '饼图',
|
chart_pie: '饼图',
|
||||||
chart_pie_donut: '环形图',
|
chart_pie_donut: '环形图',
|
||||||
|
chart_pie_proportion: '环形占比图',
|
||||||
chart_pie_rose: '玫瑰图',
|
chart_pie_rose: '玫瑰图',
|
||||||
chart_pie_donut_rose: '玫瑰环形图',
|
chart_pie_donut_rose: '玫瑰环形图',
|
||||||
chart_funnel: '漏斗图',
|
chart_funnel: '漏斗图',
|
||||||
|
@ -92,7 +92,7 @@ init()
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-form ref="colorForm" :model="state.colorForm" label-width="80px" size="small">
|
<el-form ref="colorForm" :model="state.colorForm" label-width="80px" size="small">
|
||||||
<div>
|
<div>11
|
||||||
<el-form-item :label="t('chart.color_case')" class="form-item">
|
<el-form-item :label="t('chart.color_case')" class="form-item">
|
||||||
<el-popover placement="bottom" width="400" trigger="click">
|
<el-popover placement="bottom" width="400" trigger="click">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
|
@ -160,6 +160,7 @@ const switchSeriesColor = (seriesColor, index) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const changeSeriesColor = () => {
|
const changeSeriesColor = () => {
|
||||||
|
// 选中颜色 seriesColorState.curSeriesColor.color
|
||||||
let changed = false
|
let changed = false
|
||||||
seriesColorState.seriesColor.forEach(c => {
|
seriesColorState.seriesColor.forEach(c => {
|
||||||
if (
|
if (
|
||||||
@ -419,7 +420,6 @@ const colorItemBorderColor = (index, state) => {
|
|||||||
{{ t('chart.reset') }}
|
{{ t('chart.reset') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="!((!sub && showProperty('seriesColor')) || (sub && showProperty('subSeriesColor')))"
|
v-if="!((!sub && showProperty('seriesColor')) || (sub && showProperty('subSeriesColor')))"
|
||||||
class="custom-color-extend-setting colors"
|
class="custom-color-extend-setting colors"
|
||||||
|
@ -322,8 +322,6 @@ const chartStyleShow = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const chartViewInstance = computed(() => {
|
const chartViewInstance = computed(() => {
|
||||||
// console.log(chartViewManager.getChartView(view.value.render, view.value.type))
|
|
||||||
// debugger
|
|
||||||
return chartViewManager.getChartView(view.value.render, view.value.type)
|
return chartViewManager.getChartView(view.value.render, view.value.type)
|
||||||
})
|
})
|
||||||
const showAxis = (axis: AxisType) => chartViewInstance.value?.axis?.includes(axis)
|
const showAxis = (axis: AxisType) => chartViewInstance.value?.axis?.includes(axis)
|
||||||
|
@ -1460,6 +1460,13 @@ export const CHART_TYPE_CONFIGS = [
|
|||||||
title: t('chart.chart_pie_donut'),
|
title: t('chart.chart_pie_donut'),
|
||||||
icon: 'pie-donut'
|
icon: 'pie-donut'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
render: 'antv',
|
||||||
|
category: 'distribute',
|
||||||
|
value: 'pie-proportion',
|
||||||
|
title: t('chart.chart_pie_proportion'),
|
||||||
|
icon: 'pie-proportion'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
render: 'antv',
|
render: 'antv',
|
||||||
category: 'distribute',
|
category: 'distribute',
|
||||||
|
@ -11,7 +11,7 @@ const CHART_CATEGORY = {
|
|||||||
COLUMN: ['bar', 'bar-stack', 'bar-group', 'bar-group-stack', 'percentage-bar-stack'],
|
COLUMN: ['bar', 'bar-stack', 'bar-group', 'bar-group-stack', 'percentage-bar-stack'],
|
||||||
LINE: ['line', 'area', 'area-stack'],
|
LINE: ['line', 'area', 'area-stack'],
|
||||||
MIX: ['chart-mix', 'chart-mix-group', 'chart-mix-stack', 'chart-mix-dual-line'],
|
MIX: ['chart-mix', 'chart-mix-group', 'chart-mix-stack', 'chart-mix-dual-line'],
|
||||||
PIE: ['pie', 'pie-donut']
|
PIE: ['pie', 'pie-proportion', 'pie-donut']
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -464,7 +464,6 @@ class ChartCarouselTooltip {
|
|||||||
mouseX <= rect.right - 10 &&
|
mouseX <= rect.right - 10 &&
|
||||||
mouseY >= rect.top + 10 &&
|
mouseY >= rect.top + 10 &&
|
||||||
mouseY <= rect.bottom - 10
|
mouseY <= rect.bottom - 10
|
||||||
console.log(isInside)
|
|
||||||
if (!isInside) {
|
if (!isInside) {
|
||||||
this.paused()
|
this.paused()
|
||||||
this.resume()
|
this.resume()
|
||||||
|
@ -0,0 +1,141 @@
|
|||||||
|
// G2Pie.ts
|
||||||
|
import { Chart } from '@antv/g2'
|
||||||
|
import {
|
||||||
|
G2ChartView
|
||||||
|
} from '@/views/chart/components/js/panel/types/impl/g2'
|
||||||
|
import {
|
||||||
|
parseJson,
|
||||||
|
hexColorToRGBA,
|
||||||
|
setUpSingleDimensionSeriesColor
|
||||||
|
} from '@/views/chart/components/js/util'
|
||||||
|
import { getPadding } from '@/views/chart/components/js/panel/common/common_antv'
|
||||||
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
import {
|
||||||
|
PIE_AXIS_CONFIG,
|
||||||
|
PIE_AXIS_TYPE,
|
||||||
|
PIE_EDITOR_PROPERTY,
|
||||||
|
PIE_EDITOR_PROPERTY_INNER
|
||||||
|
} from "@/views/chart/components/js/panel/charts/pie/common";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G2 Chart 封装器,支持统一销毁和渲染
|
||||||
|
*/
|
||||||
|
class ChartWrapper {
|
||||||
|
chartInstance: Chart
|
||||||
|
|
||||||
|
constructor(chartInstance: Chart) {
|
||||||
|
this.chartInstance = chartInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.chartInstance?.destroy?.()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.chartInstance?.render?.()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class G2Pie extends G2ChartView {
|
||||||
|
|
||||||
|
axis: AxisType[] = PIE_AXIS_TYPE
|
||||||
|
properties = PIE_EDITOR_PROPERTY
|
||||||
|
propertyInner: EditorPropertyInner = {
|
||||||
|
...PIE_EDITOR_PROPERTY_INNER,
|
||||||
|
'basic-style-selector': ['colors', 'alpha', 'radius','innerRadius', 'seriesColor'],
|
||||||
|
'tooltip-selector': [...PIE_EDITOR_PROPERTY_INNER['tooltip-selector'], 'carousel']
|
||||||
|
}
|
||||||
|
axisConfig = PIE_AXIS_CONFIG
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.name = 'pie-proportion'
|
||||||
|
}
|
||||||
|
|
||||||
|
async drawChart({ container, chart }: { container: HTMLElement; chart: ChartObj }) {
|
||||||
|
const customAttr = parseJson(chart.customAttr)
|
||||||
|
const innerRadius = customAttr.basicStyle.innerRadius ?? 60
|
||||||
|
const data = cloneDeep(chart.data?.data || [])
|
||||||
|
const { radius = 0.75, alpha = 1, colors = [] } = customAttr.basicStyle
|
||||||
|
|
||||||
|
const colorList = customAttr.basicStyle.colors.map(i =>
|
||||||
|
hexColorToRGBA(i, customAttr.basicStyle.alpha)
|
||||||
|
)
|
||||||
|
const g2 = new Chart({
|
||||||
|
container,
|
||||||
|
autoFit: true,
|
||||||
|
height: 300
|
||||||
|
})
|
||||||
|
g2.coordinate('theta', {
|
||||||
|
radius: customAttr.basicStyle.radius / 100,
|
||||||
|
innerRadius: innerRadius / 100
|
||||||
|
})
|
||||||
|
|
||||||
|
g2.data(data)
|
||||||
|
|
||||||
|
g2.legend(false)
|
||||||
|
g2.tooltip({
|
||||||
|
showMarkers: false
|
||||||
|
})
|
||||||
|
|
||||||
|
g2.facet('rect', {
|
||||||
|
fields: ['name'],
|
||||||
|
padding: 20,
|
||||||
|
showTitle: false,
|
||||||
|
eachView: (view, facet) => {
|
||||||
|
const data:any = facet.data
|
||||||
|
let color
|
||||||
|
color = colorList[0];
|
||||||
|
data.push({ name: '其他', value: 100 - data[0].value })
|
||||||
|
view.data(data)
|
||||||
|
view.coordinate('theta', {
|
||||||
|
radius: customAttr.basicStyle.radius / 100,
|
||||||
|
innerRadius: customAttr.basicStyle.innerRadius / 100
|
||||||
|
})
|
||||||
|
view
|
||||||
|
.interval()
|
||||||
|
.adjust('stack')
|
||||||
|
.position('value')
|
||||||
|
.color('name', (name) => {
|
||||||
|
return name === '其他' ? colorList[1] : colorList[0];
|
||||||
|
})
|
||||||
|
.style({
|
||||||
|
opacity: 1,
|
||||||
|
});
|
||||||
|
view.annotation().text({
|
||||||
|
position: [ '50%', '50%' ],
|
||||||
|
content: data[0].name,
|
||||||
|
style: {
|
||||||
|
fontSize: 12,
|
||||||
|
fill: '#8c8c8c',
|
||||||
|
fontWeight: 300,
|
||||||
|
textBaseline: 'bottom',
|
||||||
|
textAlign: 'center'
|
||||||
|
},
|
||||||
|
offsetY: -12,
|
||||||
|
})
|
||||||
|
|
||||||
|
view.annotation().text({
|
||||||
|
position: ['50%', '50%'],
|
||||||
|
content: data[0].value,
|
||||||
|
style: {
|
||||||
|
fontSize: 18,
|
||||||
|
fill: '#fff',
|
||||||
|
fontWeight: 500,
|
||||||
|
textAlign: 'center'
|
||||||
|
},
|
||||||
|
offsetY: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
g2.render()
|
||||||
|
|
||||||
|
return new ChartWrapper(g2)
|
||||||
|
}
|
||||||
|
|
||||||
|
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
|
||||||
|
return setUpSingleDimensionSeriesColor(chart, data)
|
||||||
|
}
|
||||||
|
}
|
@ -1792,7 +1792,7 @@ export function configPlotTooltipEvent<O extends PickOptions, P extends Plot<O>>
|
|||||||
chart.customAttr?.tooltip?.carousel &&
|
chart.customAttr?.tooltip?.carousel &&
|
||||||
(!event || // 事件触发时,使用event的client坐标
|
(!event || // 事件触发时,使用event的client坐标
|
||||||
['plot:leave', 'plot:mouseleave'].includes(event?.type) || //鼠标离开时,使用tooltipCtl.point
|
['plot:leave', 'plot:mouseleave'].includes(event?.type) || //鼠标离开时,使用tooltipCtl.point
|
||||||
['pie', 'pie-rose', 'pie-donut'].includes(chart.type)) // 饼图时,使用tooltipCtl.point
|
['pie', 'pie-proportion', 'pie-rose', 'pie-donut'].includes(chart.type)) // 饼图时,使用tooltipCtl.point
|
||||||
plot.options.tooltip.showMarkers = isCarousel ? true : false
|
plot.options.tooltip.showMarkers = isCarousel ? true : false
|
||||||
const wrapperDom = document.getElementById(G2_TOOLTIP_WRAPPER)
|
const wrapperDom = document.getElementById(G2_TOOLTIP_WRAPPER)
|
||||||
wrapperDom.style.zIndex = isCarousel && wrapperDom ? carousel_zIndex : '9999'
|
wrapperDom.style.zIndex = isCarousel && wrapperDom ? carousel_zIndex : '9999'
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
// G2ChartView.ts
|
||||||
|
import { Chart } from '@antv/g2'
|
||||||
|
import {
|
||||||
|
AntVAbstractChartView,
|
||||||
|
ChartLibraryType,
|
||||||
|
ChartWrapper
|
||||||
|
} from '@/views/chart/components/js/panel/types'
|
||||||
|
|
||||||
|
export abstract class G2ChartView extends AntVAbstractChartView {
|
||||||
|
constructor(name: string, defaultData: any[] = []) {
|
||||||
|
super(ChartLibraryType.G2, name, defaultData)
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract drawChart(drawOptions: {
|
||||||
|
container: HTMLElement
|
||||||
|
chart: ChartObj
|
||||||
|
}): Promise<ChartWrapper<Chart> | void>
|
||||||
|
|
||||||
|
public destroyChart(chart: Chart) {
|
||||||
|
chart?.destroy()
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ export enum ChartRenderType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum ChartLibraryType {
|
export enum ChartLibraryType {
|
||||||
|
G2 = 'g2',
|
||||||
G2_PLOT = 'g2plot',
|
G2_PLOT = 'g2plot',
|
||||||
L7_PLOT = 'l7plot',
|
L7_PLOT = 'l7plot',
|
||||||
L7 = 'l7',
|
L7 = 'l7',
|
||||||
|
@ -246,6 +246,7 @@ const mapChartTypes = ['bubble-map', 'flow-map', 'heat-map', 'map', 'symbolic-ma
|
|||||||
const distributionChartTypes = [
|
const distributionChartTypes = [
|
||||||
'pie',
|
'pie',
|
||||||
'pie-donut',
|
'pie-donut',
|
||||||
|
'pie-proportion',
|
||||||
'pie-rose',
|
'pie-rose',
|
||||||
'pie-donut-rose',
|
'pie-donut-rose',
|
||||||
'radar',
|
'radar',
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
import { getData } from '@/api/chart'
|
import { getData } from '@/api/chart'
|
||||||
import { ChartLibraryType } from '@/views/chart/components/js/panel/types'
|
import { ChartLibraryType } from '@/views/chart/components/js/panel/types'
|
||||||
import { G2PlotChartView } from '@/views/chart/components/js/panel/types/impl/g2plot'
|
import { G2PlotChartView } from '@/views/chart/components/js/panel/types/impl/g2plot'
|
||||||
|
import { G2ChartView } from '@/views/chart/components/js/panel/types/impl/g2'
|
||||||
import { L7PlotChartView } from '@/views/chart/components/js/panel/types/impl/l7plot'
|
import { L7PlotChartView } from '@/views/chart/components/js/panel/types/impl/l7plot'
|
||||||
import chartViewManager from '@/views/chart/components/js/panel'
|
import chartViewManager from '@/views/chart/components/js/panel'
|
||||||
import { useAppStoreWithOut } from '@/store/modules/app'
|
import { useAppStoreWithOut } from '@/store/modules/app'
|
||||||
@ -239,25 +240,47 @@ const calcData = async (view, callback) => {
|
|||||||
callback?.()
|
callback?.()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let g2VTimer: any
|
||||||
|
const renderG2 = async (chart, chartView: G2ChartView<any, any>) => {
|
||||||
|
g2VTimer && clearTimeout(g2VTimer)
|
||||||
|
g2VTimer = setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
myChart?.destroy?.()
|
||||||
|
myChart = await chartView.drawChart({
|
||||||
|
chartObj: myChart,
|
||||||
|
container: containerId,
|
||||||
|
chart,
|
||||||
|
scale: 1,
|
||||||
|
action,
|
||||||
|
quadrantDefaultBaseline
|
||||||
|
})
|
||||||
|
// G2 图表实例可能是 Chart 对象,不一定有 render 方法(部分内部已自动渲染)
|
||||||
|
myChart?.render?.()
|
||||||
|
} catch (e) {
|
||||||
|
console.error('renderG2 error', e)
|
||||||
|
}
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
let curView
|
let curView
|
||||||
const renderChart = async (view, callback?) => {
|
const renderChart = async (view, callback?) => {
|
||||||
console.log('renderChart',view.type, callback)
|
// console.log('renderChart',view, callback)
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
curView = view
|
curView = view
|
||||||
// view 为引用对象 需要存库 view.data 直接赋值会导致保存不必要的数据
|
// view 为引用对象 需要存库 view.data 直接赋值会导致保存不必要的数据
|
||||||
// 与默认图表对象合并,方便增加配置项
|
// 与默认图表对象合并,方便增加配置项
|
||||||
|
console.log(view,998779)
|
||||||
const chart = deepCopy({
|
const chart = deepCopy({
|
||||||
...defaultsDeep(view, cloneDeep(BASE_VIEW_CONFIG)),
|
...defaultsDeep(view, cloneDeep(BASE_VIEW_CONFIG)),
|
||||||
data: chartData.value,
|
data: chartData.value,
|
||||||
...(props.fontFamily && props.fontFamily !== 'inherit' ? { fontFamily: props.fontFamily } : {})
|
...(props.fontFamily && props.fontFamily !== 'inherit' ? { fontFamily: props.fontFamily } : {})
|
||||||
})
|
})
|
||||||
|
console.log('chart1', chart.customAttr.basicStyle.colors)
|
||||||
const chartView = chartViewManager.getChartView(view.render, view.type)
|
const chartView = chartViewManager.getChartView(view.render, view.type)
|
||||||
recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value)
|
recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value)
|
||||||
recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value)
|
recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value)
|
||||||
console.log('chart', chart)
|
console.log('chart', chart)
|
||||||
console.log( chartView)
|
|
||||||
switch (chartView.library) {
|
switch (chartView.library) {
|
||||||
case ChartLibraryType.L7_PLOT:
|
case ChartLibraryType.L7_PLOT:
|
||||||
await renderL7Plot(chart, chartView as L7PlotChartView<any, any>, callback)
|
await renderL7Plot(chart, chartView as L7PlotChartView<any, any>, callback)
|
||||||
@ -269,6 +292,10 @@ const renderChart = async (view, callback?) => {
|
|||||||
await renderG2Plot(chart, chartView as G2PlotChartView<any, any>)
|
await renderG2Plot(chart, chartView as G2PlotChartView<any, any>)
|
||||||
callback?.()
|
callback?.()
|
||||||
break
|
break
|
||||||
|
case ChartLibraryType.G2:
|
||||||
|
await renderG2(chart, chartView as G2ChartView<any, any>)
|
||||||
|
callback?.()
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -336,7 +363,6 @@ const renderL7Plot = async (chart: ChartObj, chartView: L7PlotChartView<any, any
|
|||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
// let satelliteLayer: any = null;
|
// let satelliteLayer: any = null;
|
||||||
|
|
||||||
class SatelliteControl extends Control {
|
class SatelliteControl extends Control {
|
||||||
protected onAdd() {
|
protected onAdd() {
|
||||||
const btn = document.createElement('button');
|
const btn = document.createElement('button');
|
||||||
|
@ -1231,7 +1231,7 @@ const clearG2Tooltip = () => {
|
|||||||
:font-family="fontFamily"
|
:font-family="fontFamily"
|
||||||
:active="active"
|
:active="active"
|
||||||
v-else-if="
|
v-else-if="
|
||||||
showChartView(ChartLibraryType.G2_PLOT, ChartLibraryType.L7_PLOT, ChartLibraryType.L7) || view.type == 'three-map'
|
showChartView(ChartLibraryType.G2,ChartLibraryType.G2_PLOT, ChartLibraryType.L7_PLOT, ChartLibraryType.L7) || view.type == 'three-map'
|
||||||
"
|
"
|
||||||
ref="chartComponent"
|
ref="chartComponent"
|
||||||
@onChartClick="chartClick"
|
@onChartClick="chartClick"
|
||||||
|
Loading…
Reference in New Issue
Block a user