feat: 允许图表设置多个主题色(#45)

This commit is contained in:
pipipi-pikachu 2021-08-27 13:52:01 +08:00
parent c1e56746f9
commit 1b31abb230
6 changed files with 97 additions and 24 deletions

View File

@ -90,7 +90,7 @@ export default () => {
top: 81.25, top: 81.25,
width: 400, width: 400,
height: 400, height: 400,
themeColor: themeColor.value, themeColor: [themeColor.value],
gridColor: fontColor.value, gridColor: fontColor.value,
data: { data: {
labels: ['类别1', '类别2', '类别3', '类别4', '类别5'], labels: ['类别1', '类别2', '类别3', '类别4', '类别5'],

View File

@ -382,7 +382,15 @@ export default () => {
}) })
} }
const chartColors = tinycolor(el.themeColor).analogous(10).map(item => item.toHexString()) let chartColors: string[] = []
if (el.themeColor.length === 10) chartColors = el.themeColor.map(color => formatColor(color).color)
else if (el.themeColor.length === 1) chartColors = tinycolor(el.themeColor[0]).analogous(10).map(color => formatColor(color.toHexString()).color)
else {
const len = el.themeColor.length
const supplement = tinycolor(el.themeColor[len - 1]).analogous(10 + 1 - len).map(color => color.toHexString())
chartColors = [...el.themeColor.slice(0, len - 1), ...supplement].map(color => formatColor(color).color)
}
const options: pptxgen.IChartOpts = { const options: pptxgen.IChartOpts = {
x: el.left / 100, x: el.left / 100,
y: el.top / 100, y: el.top / 100,

View File

@ -354,7 +354,7 @@ export interface PPTChartElement extends PPTBaseElement {
data: ChartData; data: ChartData;
options?: ILineChartOptions & IBarChartOptions & IPieChartOptions; options?: ILineChartOptions & IBarChartOptions & IPieChartOptions;
outline?: PPTElementOutline; outline?: PPTElementOutline;
themeColor: string; themeColor: string[];
gridColor?: string; gridColor?: string;
} }

View File

@ -53,18 +53,6 @@
<ColorButton :color="fill" style="flex: 3;" /> <ColorButton :color="fill" style="flex: 3;" />
</Popover> </Popover>
</div> </div>
<div class="row">
<div style="flex: 2;">主题配色</div>
<Popover trigger="click">
<template #content>
<ColorPicker
:modelValue="themeColor"
@update:modelValue="value => updateTheme(value)"
/>
</template>
<ColorButton :color="themeColor" style="flex: 3;" />
</Popover>
</div>
<div class="row"> <div class="row">
<div style="flex: 2;">网格颜色</div> <div style="flex: 2;">网格颜色</div>
<Popover trigger="click"> <Popover trigger="click">
@ -79,6 +67,33 @@
</div> </div>
<Divider /> <Divider />
<div class="row" v-for="(color, index) in themeColor" :key="index">
<div style="flex: 2;">{{index === 0 ? '主题配色:' : ''}}</div>
<Popover trigger="click">
<template #content>
<ColorPicker
:modelValue="color"
@update:modelValue="value => updateTheme(value, index)"
/>
</template>
<div class="color-btn-wrap" style="flex: 3;">
<ColorButton :color="color" style="width: 100%;" />
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="删除">
<div class="delete-color-btn" @click.stop="deleteThemeColor(index)" v-if="index !== 0"><IconCloseSmall /></div>
</Tooltip>
</div>
</Popover>
</div>
<div class="row" v-if="themeColor.length < 10">
<div style="flex: 2;"></div>
<Button class="add-color-btn" style="flex: 3;" @click="addThemeColor()">
<IconPlus />
</Button>
</div>
<Divider />
<ElementOutline /> <ElementOutline />
<Modal <Modal
@ -120,6 +135,7 @@ export default defineComponent({
setup() { setup() {
const store = useStore() const store = useStore()
const handleElement = computed<PPTChartElement>(() => store.getters.handleElement) const handleElement = computed<PPTChartElement>(() => store.getters.handleElement)
const theme = computed(() => store.state.theme)
const chartDataEditorVisible = ref(false) const chartDataEditorVisible = ref(false)
@ -127,7 +143,7 @@ export default defineComponent({
const fill = ref<string>() const fill = ref<string>()
const themeColor = ref<string>('') const themeColor = ref<string[]>([])
const gridColor = ref('') const gridColor = ref('')
const lineSmooth = ref(true) const lineSmooth = ref(true)
@ -185,8 +201,28 @@ export default defineComponent({
} }
// //
const updateTheme = (themeColor: string) => { const updateTheme = (color: string, index: number) => {
const props = { themeColor } const props = {
themeColor: themeColor.value.map((c, i) => i === index ? color : c),
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
}
//
const addThemeColor = () => {
const props = {
themeColor: [...themeColor.value, theme.value.themeColor],
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot()
}
//
const deleteThemeColor = (index: number) => {
const props = {
themeColor: themeColor.value.filter((c, i) => i !== index),
}
store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props }) store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props })
addHistorySnapshot() addHistorySnapshot()
} }
@ -220,6 +256,8 @@ export default defineComponent({
themeColor, themeColor,
gridColor, gridColor,
updateTheme, updateTheme,
addThemeColor,
deleteThemeColor,
updateGridColor, updateGridColor,
} }
}, },
@ -239,4 +277,23 @@ export default defineComponent({
.btn-icon { .btn-icon {
margin-right: 3px; margin-right: 3px;
} }
.add-color-btn {
padding: 0 !important;
}
.color-btn-wrap {
position: relative;
}
.delete-color-btn {
position: absolute;
width: 30px;
right: 2px;
top: 2px;
bottom: 2px;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
cursor: pointer;
}
</style> </style>

View File

@ -327,7 +327,7 @@ export default defineComponent({
} }
} }
else if (el.type === 'chart') { else if (el.type === 'chart') {
el.themeColor = themeColor el.themeColor = [themeColor]
el.gridColor = fontColor el.gridColor = fontColor
} }
} }

View File

@ -51,7 +51,7 @@ export default defineComponent({
type: Object as PropType<ILineChartOptions & IBarChartOptions & IPieChartOptions>, type: Object as PropType<ILineChartOptions & IBarChartOptions & IPieChartOptions>,
}, },
themeColor: { themeColor: {
type: String, type: Array as PropType<string[]>,
required: true, required: true,
}, },
gridColor: { gridColor: {
@ -101,14 +101,22 @@ export default defineComponent({
onMounted(renderChart) onMounted(renderChart)
// //
// 10
const updateTheme = () => { const updateTheme = () => {
if (!chartRef.value) return if (!chartRef.value) return
const colors = tinycolor(props.themeColor).analogous(10) let colors: string[] = []
if (props.themeColor.length === 10) colors = props.themeColor
else if (props.themeColor.length === 1) colors = tinycolor(props.themeColor[0]).analogous(10).map(color => color.toHexString())
else {
const len = props.themeColor.length
const supplement = tinycolor(props.themeColor[len - 1]).analogous(10 + 1 - len).map(color => color.toHexString())
colors = [...props.themeColor.slice(0, len - 1), ...supplement]
}
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
const color = colors[i].toRgbString() chartRef.value.style.setProperty(`--theme-color-${i + 1}`, colors[i])
chartRef.value.style.setProperty(`--theme-color-${i + 1}`, color)
} }
} }