mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
feat: 图表添加配置(平滑曲线、堆叠模式)
This commit is contained in:
parent
495799aafa
commit
2e4a3df988
@ -660,13 +660,16 @@ export default () => {
|
|||||||
if (el.chartType === 'bar') {
|
if (el.chartType === 'bar') {
|
||||||
type = pptx.ChartType.bar
|
type = pptx.ChartType.bar
|
||||||
options.barDir = 'col'
|
options.barDir = 'col'
|
||||||
|
if (el.options?.stack) options.barGrouping = 'stacked'
|
||||||
}
|
}
|
||||||
else if (el.chartType === 'column') {
|
else if (el.chartType === 'column') {
|
||||||
type = pptx.ChartType.bar
|
type = pptx.ChartType.bar
|
||||||
options.barDir = 'bar'
|
options.barDir = 'bar'
|
||||||
|
if (el.options?.stack) options.barGrouping = 'stacked'
|
||||||
}
|
}
|
||||||
else if (el.chartType === 'line') {
|
else if (el.chartType === 'line') {
|
||||||
type = pptx.ChartType.line
|
type = pptx.ChartType.line
|
||||||
|
if (el.options?.lineSmooth) options.lineSmooth = true
|
||||||
}
|
}
|
||||||
else if (el.chartType === 'area') {
|
else if (el.chartType === 'area') {
|
||||||
type = pptx.ChartType.area
|
type = pptx.ChartType.area
|
||||||
|
@ -19,6 +19,7 @@ import type {
|
|||||||
PPTLineElement,
|
PPTLineElement,
|
||||||
ShapeTextAlign,
|
ShapeTextAlign,
|
||||||
PPTTextElement,
|
PPTTextElement,
|
||||||
|
ChartOptions,
|
||||||
} from '@/types/slides'
|
} from '@/types/slides'
|
||||||
|
|
||||||
const convertFontSizePtToPx = (html: string, ratio: number) => {
|
const convertFontSizePtToPx = (html: string, ratio: number) => {
|
||||||
@ -398,6 +399,8 @@ export default () => {
|
|||||||
legends = data.map(item => item.key)
|
legends = data.map(item => item.key)
|
||||||
series = data.map(item => item.values.map(v => v.y))
|
series = data.map(item => item.values.map(v => v.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const options: ChartOptions = {}
|
||||||
|
|
||||||
let chartType: ChartType = 'bar'
|
let chartType: ChartType = 'bar'
|
||||||
|
|
||||||
@ -406,6 +409,7 @@ export default () => {
|
|||||||
case 'bar3DChart':
|
case 'bar3DChart':
|
||||||
chartType = 'bar'
|
chartType = 'bar'
|
||||||
if (el.barDir === 'bar') chartType = 'column'
|
if (el.barDir === 'bar') chartType = 'column'
|
||||||
|
if (el.grouping === 'stacked' || el.grouping === 'percentStacked') options.stack = true
|
||||||
break
|
break
|
||||||
case 'lineChart':
|
case 'lineChart':
|
||||||
case 'line3DChart':
|
case 'line3DChart':
|
||||||
@ -413,6 +417,7 @@ export default () => {
|
|||||||
break
|
break
|
||||||
case 'areaChart':
|
case 'areaChart':
|
||||||
case 'area3DChart':
|
case 'area3DChart':
|
||||||
|
if (el.grouping === 'stacked' || el.grouping === 'percentStacked') options.stack = true
|
||||||
chartType = 'area'
|
chartType = 'area'
|
||||||
break
|
break
|
||||||
case 'scatterChart':
|
case 'scatterChart':
|
||||||
@ -445,6 +450,7 @@ export default () => {
|
|||||||
legends,
|
legends,
|
||||||
series,
|
series,
|
||||||
},
|
},
|
||||||
|
options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else if (el.type === 'group' || el.type === 'diagram') {
|
else if (el.type === 'group' || el.type === 'diagram') {
|
||||||
|
@ -394,6 +394,12 @@ export interface PPTLineElement extends Omit<PPTBaseElement, 'height' | 'rotate'
|
|||||||
|
|
||||||
|
|
||||||
export type ChartType = 'bar' | 'column' | 'line' | 'pie' | 'ring' | 'area' | 'scatter'
|
export type ChartType = 'bar' | 'column' | 'line' | 'pie' | 'ring' | 'area' | 'scatter'
|
||||||
|
|
||||||
|
export interface ChartOptions {
|
||||||
|
lineSmooth?: boolean
|
||||||
|
stack?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface ChartData {
|
export interface ChartData {
|
||||||
labels: string[]
|
labels: string[]
|
||||||
legends: string[]
|
legends: string[]
|
||||||
@ -411,6 +417,8 @@ export interface ChartData {
|
|||||||
*
|
*
|
||||||
* data: 图表数据
|
* data: 图表数据
|
||||||
*
|
*
|
||||||
|
* options: 扩展选项
|
||||||
|
*
|
||||||
* outline?: 边框
|
* outline?: 边框
|
||||||
*
|
*
|
||||||
* themeColors: 主题色
|
* themeColors: 主题色
|
||||||
@ -422,6 +430,7 @@ export interface PPTChartElement extends PPTBaseElement {
|
|||||||
fill?: string
|
fill?: string
|
||||||
chartType: ChartType
|
chartType: ChartType
|
||||||
data: ChartData
|
data: ChartData
|
||||||
|
options?: ChartOptions
|
||||||
outline?: PPTElementOutline
|
outline?: PPTElementOutline
|
||||||
themeColors: string[]
|
themeColors: string[]
|
||||||
textColor?: string
|
textColor?: string
|
||||||
|
@ -6,6 +6,24 @@
|
|||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
|
<template v-if="['bar', 'column', 'area', 'line'].includes(handleChartElement.chartType)">
|
||||||
|
<div class="row">
|
||||||
|
<Checkbox
|
||||||
|
v-if="handleChartElement.chartType === 'line'"
|
||||||
|
@update:value="value => updateOptions({ lineSmooth: value })"
|
||||||
|
:value="lineSmooth"
|
||||||
|
>使用平滑曲线</Checkbox>
|
||||||
|
<Checkbox
|
||||||
|
v-if="['bar', 'column', 'area'].includes(handleChartElement.chartType)"
|
||||||
|
@update:value="value => updateOptions({ stack: value })"
|
||||||
|
:value="stack"
|
||||||
|
style="flex: 1;"
|
||||||
|
>堆叠样式</Checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div style="width: 40%;">背景填充:</div>
|
<div style="width: 40%;">背景填充:</div>
|
||||||
<Popover trigger="click" style="width: 60%;">
|
<Popover trigger="click" style="width: 60%;">
|
||||||
@ -99,7 +117,7 @@
|
|||||||
import { onUnmounted, ref, watch, type Ref } from 'vue'
|
import { onUnmounted, ref, watch, type Ref } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useMainStore, useSlidesStore } from '@/store'
|
import { useMainStore, useSlidesStore } from '@/store'
|
||||||
import type { ChartData, PPTChartElement } from '@/types/slides'
|
import type { ChartData, ChartOptions, PPTChartElement } from '@/types/slides'
|
||||||
import emitter, { EmitterEvents } from '@/utils/emitter'
|
import emitter, { EmitterEvents } from '@/utils/emitter'
|
||||||
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
|
||||||
import { CHART_PRESET_THEMES } from '@/configs/chart'
|
import { CHART_PRESET_THEMES } from '@/configs/chart'
|
||||||
@ -110,6 +128,7 @@ import ColorButton from '@/components/ColorButton.vue'
|
|||||||
import ColorPicker from '@/components/ColorPicker/index.vue'
|
import ColorPicker from '@/components/ColorPicker/index.vue'
|
||||||
import Modal from '@/components/Modal.vue'
|
import Modal from '@/components/Modal.vue'
|
||||||
import Divider from '@/components/Divider.vue'
|
import Divider from '@/components/Divider.vue'
|
||||||
|
import Checkbox from '@/components/Checkbox.vue'
|
||||||
import Button from '@/components/Button.vue'
|
import Button from '@/components/Button.vue'
|
||||||
import ButtonGroup from '@/components/ButtonGroup.vue'
|
import ButtonGroup from '@/components/ButtonGroup.vue'
|
||||||
import Popover from '@/components/Popover.vue'
|
import Popover from '@/components/Popover.vue'
|
||||||
@ -131,11 +150,26 @@ const fill = ref<string>('#000')
|
|||||||
|
|
||||||
const themeColors = ref<string[]>([])
|
const themeColors = ref<string[]>([])
|
||||||
const textColor = ref('')
|
const textColor = ref('')
|
||||||
|
const lineSmooth = ref(false)
|
||||||
|
const stack = ref(false)
|
||||||
|
|
||||||
watch(handleElement, () => {
|
watch(handleElement, () => {
|
||||||
if (!handleElement.value || handleElement.value.type !== 'chart') return
|
if (!handleElement.value || handleElement.value.type !== 'chart') return
|
||||||
fill.value = handleElement.value.fill || '#fff'
|
fill.value = handleElement.value.fill || '#fff'
|
||||||
|
|
||||||
|
lineSmooth.value = false
|
||||||
|
stack.value = false
|
||||||
|
|
||||||
|
if (handleElement.value.options) {
|
||||||
|
const {
|
||||||
|
lineSmooth: _lineSmooth,
|
||||||
|
stack: _stack,
|
||||||
|
} = handleElement.value.options
|
||||||
|
|
||||||
|
if (_lineSmooth !== undefined) lineSmooth.value = _lineSmooth
|
||||||
|
if (_stack !== undefined) stack.value = _stack
|
||||||
|
}
|
||||||
|
|
||||||
themeColors.value = handleElement.value.themeColors
|
themeColors.value = handleElement.value.themeColors
|
||||||
textColor.value = handleElement.value.textColor || '#333'
|
textColor.value = handleElement.value.textColor || '#333'
|
||||||
}, { deep: true, immediate: true })
|
}, { deep: true, immediate: true })
|
||||||
@ -156,6 +190,15 @@ const updateFill = (value: string) => {
|
|||||||
updateElement({ fill: value })
|
updateElement({ fill: value })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置扩展选项
|
||||||
|
const updateOptions = (optionProps: ChartOptions) => {
|
||||||
|
console.log(optionProps)
|
||||||
|
const _handleElement = handleElement.value as PPTChartElement
|
||||||
|
|
||||||
|
const newOptions = { ..._handleElement.options, ...optionProps }
|
||||||
|
updateElement({ options: newOptions })
|
||||||
|
}
|
||||||
|
|
||||||
// 设置主题色
|
// 设置主题色
|
||||||
const updateTheme = (color: string, index: number) => {
|
const updateTheme = (color: string, index: number) => {
|
||||||
const props = {
|
const props = {
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
:data="elementInfo.data"
|
:data="elementInfo.data"
|
||||||
:themeColors="elementInfo.themeColors"
|
:themeColors="elementInfo.themeColors"
|
||||||
:textColor="elementInfo.textColor"
|
:textColor="elementInfo.textColor"
|
||||||
:legends="elementInfo.data.legends"
|
:options="elementInfo.options"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import { onMounted, ref, computed, watch } from 'vue'
|
import { onMounted, ref, computed, watch } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import tinycolor from 'tinycolor2'
|
import tinycolor from 'tinycolor2'
|
||||||
import type { ChartData, ChartType } from '@/types/slides'
|
import type { ChartData, ChartOptions, ChartType } from '@/types/slides'
|
||||||
import { getChartOption } from './chartOption'
|
import { getChartOption } from './chartOption'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -15,8 +15,8 @@ const props = defineProps<{
|
|||||||
type: ChartType
|
type: ChartType
|
||||||
data: ChartData
|
data: ChartData
|
||||||
themeColors: string[]
|
themeColors: string[]
|
||||||
legends: string[]
|
|
||||||
textColor?: string
|
textColor?: string
|
||||||
|
options?: ChartOptions
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
let chart: echarts.ECharts | null = null
|
let chart: echarts.ECharts | null = null
|
||||||
@ -40,6 +40,8 @@ const updateOption = () => {
|
|||||||
data: props.data,
|
data: props.data,
|
||||||
themeColors: themeColors.value,
|
themeColors: themeColors.value,
|
||||||
textColor: props.textColor,
|
textColor: props.textColor,
|
||||||
|
lineSmooth: props.options?.lineSmooth || false,
|
||||||
|
stack: props.options?.stack || false,
|
||||||
})
|
})
|
||||||
if (option) chart!.setOption(option, true)
|
if (option) chart!.setOption(option, true)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ export interface ChartOptionPayload {
|
|||||||
data: ChartData
|
data: ChartData
|
||||||
themeColors: string[]
|
themeColors: string[]
|
||||||
textColor?: string
|
textColor?: string
|
||||||
|
lineSmooth?: boolean
|
||||||
|
stack?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getChartOption = ({
|
export const getChartOption = ({
|
||||||
@ -13,6 +15,8 @@ export const getChartOption = ({
|
|||||||
data,
|
data,
|
||||||
themeColors,
|
themeColors,
|
||||||
textColor,
|
textColor,
|
||||||
|
lineSmooth,
|
||||||
|
stack,
|
||||||
}: ChartOptionPayload): echarts.EChartsOption | null => {
|
}: ChartOptionPayload): echarts.EChartsOption | null => {
|
||||||
if(type === 'bar') {
|
if(type === 'bar') {
|
||||||
return {
|
return {
|
||||||
@ -39,14 +43,18 @@ export const getChartOption = ({
|
|||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
},
|
},
|
||||||
series: data.series.map((item, index) => ({
|
series: data.series.map((item, index) => {
|
||||||
data: item,
|
const seriesItem: echarts.SeriesOption = {
|
||||||
name: data.legends[index],
|
data: item,
|
||||||
type: 'bar',
|
name: data.legends[index],
|
||||||
label: {
|
type: 'bar',
|
||||||
show: true,
|
label: {
|
||||||
},
|
show: true,
|
||||||
})),
|
},
|
||||||
|
}
|
||||||
|
if (stack) seriesItem.stack = 'A'
|
||||||
|
return seriesItem
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(type === 'column') {
|
if(type === 'column') {
|
||||||
@ -74,14 +82,18 @@ export const getChartOption = ({
|
|||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
},
|
},
|
||||||
series: data.series.map((item, index) => ({
|
series: data.series.map((item, index) => {
|
||||||
data: item,
|
const seriesItem: echarts.SeriesOption = {
|
||||||
name: data.legends[index],
|
data: item,
|
||||||
type: 'bar',
|
name: data.legends[index],
|
||||||
label: {
|
type: 'bar',
|
||||||
show: true,
|
label: {
|
||||||
},
|
show: true,
|
||||||
})),
|
},
|
||||||
|
}
|
||||||
|
if (stack) seriesItem.stack = 'A'
|
||||||
|
return seriesItem
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(type === 'line') {
|
if(type === 'line') {
|
||||||
@ -113,6 +125,7 @@ export const getChartOption = ({
|
|||||||
data: item,
|
data: item,
|
||||||
name: data.legends[index],
|
name: data.legends[index],
|
||||||
type: 'line',
|
type: 'line',
|
||||||
|
smooth: lineSmooth,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
@ -230,15 +243,19 @@ export const getChartOption = ({
|
|||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
},
|
},
|
||||||
series: data.series.map((item, index) => ({
|
series: data.series.map((item, index) => {
|
||||||
data: item,
|
const seriesItem: echarts.SeriesOption = {
|
||||||
name: data.legends[index],
|
data: item,
|
||||||
type: 'line',
|
name: data.legends[index],
|
||||||
areaStyle: {},
|
type: 'line',
|
||||||
label: {
|
areaStyle: {},
|
||||||
show: true,
|
label: {
|
||||||
},
|
show: true,
|
||||||
})),
|
},
|
||||||
|
}
|
||||||
|
if (stack) seriesItem.stack = 'A'
|
||||||
|
return seriesItem
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(type === 'scatter') {
|
if(type === 'scatter') {
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
:data="elementInfo.data"
|
:data="elementInfo.data"
|
||||||
:themeColors="elementInfo.themeColors"
|
:themeColors="elementInfo.themeColors"
|
||||||
:textColor="elementInfo.textColor"
|
:textColor="elementInfo.textColor"
|
||||||
:legends="elementInfo.data.legends"
|
:options="elementInfo.options"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user