perf: 图表插入优化、添加柱状图堆叠模式

This commit is contained in:
pipipi-pikachu 2022-04-22 10:59:41 +08:00
parent 962331100c
commit d8ea311945
10 changed files with 75 additions and 26 deletions

View File

@ -26,7 +26,7 @@ npm run serve
- 历史记录(撤销、重做) - 历史记录(撤销、重做)
- 快捷键 - 快捷键
- 右键菜单 - 右键菜单
- 导出本地文件PPTX、JSON - 导出本地文件PPTX、JSON、图片
### 幻灯片页面编辑 ### 幻灯片页面编辑
- 页面添加、删除 - 页面添加、删除
- 页面顺序调整 - 页面顺序调整
@ -84,12 +84,12 @@ npm run serve
- 宽度 - 宽度
- 样式 - 样式
- 端点样式 - 端点样式
#### 图表(柱状图、折线图、饼图) #### 图表(柱状图、条形图、折线图、面积图、散点图、图、环形图)
- 数据编辑 - 数据编辑
- 背景填充 - 背景填充
- 主题色 - 主题色
- 坐标系与坐标文字颜色 - 坐标系与坐标文字颜色
- 其他设置(柱状图转条形图、折线图转面积图、折线图转散点图、饼图转环形图、折线图开关平滑曲线) - 其他图表设置
- 边框 - 边框
- 图例 - 图例
#### 表格 #### 表格

6
package-lock.json generated
View File

@ -1491,9 +1491,9 @@
} }
}, },
"@icon-park/vue-next": { "@icon-park/vue-next": {
"version": "1.3.5", "version": "1.3.6",
"resolved": "https://registry.nlark.com/@icon-park/vue-next/download/@icon-park/vue-next-1.3.5.tgz", "resolved": "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.3.6.tgz",
"integrity": "sha1-TJy+bHfE9Nrb5g/Sa4axDtStGGs=" "integrity": "sha512-AZaCcjRPU9vTNVfcrG03CYJM+uv0SXx5lC4njanlRorFo+TV/x0ZTYGYGpTR/l6ek6QmFu9THmrgqKl7i/8yHg=="
}, },
"@intervolga/optimize-cssnano-plugin": { "@intervolga/optimize-cssnano-plugin": {
"version": "1.0.6", "version": "1.0.6",

View File

@ -9,7 +9,7 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@icon-park/vue-next": "^1.3.5", "@icon-park/vue-next": "^1.3.6",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"ant-design-vue": "^3.1.0", "ant-design-vue": "^3.1.0",
"chartist": "^0.11.4", "chartist": "^0.11.4",

15
src/configs/chartTypes.ts Normal file
View File

@ -0,0 +1,15 @@
import { ChartType } from '@/types/slides'
interface ChartTypes {
[propName: string]: ChartType;
}
export const CHART_TYPES: ChartTypes = {
bar: 'bar',
horizontalBar: 'bar',
line: 'line',
area: 'line',
scatter: 'line',
pie: 'pie',
ring: 'pie',
}

View File

@ -3,9 +3,10 @@ import { useMainStore, useSlidesStore } from '@/store'
import { createRandomCode } from '@/utils/common' import { createRandomCode } from '@/utils/common'
import { getImageSize } from '@/utils/image' import { getImageSize } from '@/utils/image'
import { VIEWPORT_SIZE } from '@/configs/canvas' import { VIEWPORT_SIZE } from '@/configs/canvas'
import { PPTLineElement, ChartType, PPTElement, TableCell, TableCellStyle, PPTShapeElement } from '@/types/slides' import { PPTLineElement, PPTElement, TableCell, TableCellStyle, PPTShapeElement, PPTChartElement, ChartOptions, PresetChartType } from '@/types/slides'
import { ShapePoolItem, SHAPE_PATH_FORMULAS } from '@/configs/shapes' import { ShapePoolItem, SHAPE_PATH_FORMULAS } from '@/configs/shapes'
import { LinePoolItem } from '@/configs/lines' import { LinePoolItem } from '@/configs/lines'
import { CHART_TYPES } from '@/configs/chartTypes'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
interface CommonElementPosition { interface CommonElementPosition {
@ -79,11 +80,11 @@ export default () => {
* *
* @param chartType * @param chartType
*/ */
const createChartElement = (chartType: ChartType) => { const createChartElement = (type: PresetChartType) => {
createElement({ const newElement: PPTChartElement = {
type: 'chart', type: 'chart',
id: createRandomCode(), id: createRandomCode(),
chartType, chartType: CHART_TYPES[type],
left: 300, left: 300,
top: 81.25, top: 81.25,
width: 400, width: 400,
@ -98,6 +99,17 @@ export default () => {
[12, 19, 5, 2, 18], [12, 19, 5, 2, 18],
], ],
}, },
}
let options: ChartOptions = {}
if (type === 'horizontalBar') options = { horizontalBars: true }
else if (type === 'area') options = { showArea: true }
else if (type === 'scatter') options = { showLine: false }
else if (type === 'ring') options = { donut: true }
createElement({
...newElement,
options,
}) })
} }

View File

@ -56,6 +56,10 @@ import {
Github, Github,
ChartProportion, ChartProportion,
ChartHistogram, ChartHistogram,
ChartHistogramOne,
ChartLineArea,
ChartRing,
ChartScatter,
ChartLine, ChartLine,
ChartPie, ChartPie,
Text, Text,
@ -185,6 +189,10 @@ export default {
app.component('IconChartHistogram', ChartHistogram) app.component('IconChartHistogram', ChartHistogram)
app.component('IconChartLine', ChartLine) app.component('IconChartLine', ChartLine)
app.component('IconChartPie', ChartPie) app.component('IconChartPie', ChartPie)
app.component('IconChartHistogramOne', ChartHistogramOne)
app.component('IconChartLineArea', ChartLineArea)
app.component('IconChartRing', ChartRing)
app.component('IconChartScatter', ChartScatter)
// 其他 // 其他
app.component('IconPlayOne', PlayOne) app.component('IconPlayOne', PlayOne)

View File

@ -354,7 +354,9 @@ export interface PPTLineElement extends Omit<PPTBaseElement, 'height' | 'rotate'
} }
export type PresetChartType = 'bar' | 'horizontalBar' | 'line' | 'area' | 'scatter' | 'pie' | 'ring'
export type ChartType = 'bar' | 'line' | 'pie' export type ChartType = 'bar' | 'line' | 'pie'
export type ChartOptions = ILineChartOptions & IBarChartOptions & IPieChartOptions
export interface ChartData { export interface ChartData {
labels: string[]; labels: string[];
legends: string[]; legends: string[];
@ -368,7 +370,7 @@ export interface ChartData {
* *
* fill?: 填充色 * fill?: 填充色
* *
* chartType: 图表类型 * chartType: 图表基础类型bar/line/pie
* *
* data: 图表数据 * data: 图表数据
* *
@ -387,7 +389,7 @@ export interface PPTChartElement extends PPTBaseElement {
fill?: string; fill?: string;
chartType: ChartType; chartType: ChartType;
data: ChartData; data: ChartData;
options?: ILineChartOptions & IBarChartOptions & IPieChartOptions; options?: ChartOptions;
outline?: PPTElementOutline; outline?: PPTElementOutline;
themeColor: string[]; themeColor: string[];
gridColor?: string; gridColor?: string;

View File

@ -5,21 +5,26 @@
<IconChartLine size="24" v-if="chart === 'line'" /> <IconChartLine size="24" v-if="chart === 'line'" />
<IconChartHistogram size="24" v-else-if="chart === 'bar'" /> <IconChartHistogram size="24" v-else-if="chart === 'bar'" />
<IconChartPie size="24" v-else-if="chart === 'pie'" /> <IconChartPie size="24" v-else-if="chart === 'pie'" />
<IconChartHistogramOne size="24" v-else-if="chart === 'horizontalBar'" />
<IconChartLineArea size="24" v-else-if="chart === 'area'" />
<IconChartRing size="24" v-else-if="chart === 'ring'" />
<IconChartScatter size="24" v-else-if="chart === 'scatter'" />
</div> </div>
</li> </li>
</ul> </ul>
</template> </template>
<script lang="ts"> <script lang="ts">
import { PresetChartType } from '@/types/slides'
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
export default defineComponent({ export default defineComponent({
name: 'chart-pool', name: 'chart-pool',
emits: ['select'], emits: ['select'],
setup(props, { emit }) { setup(props, { emit }) {
const chartList = ['bar', 'line', 'pie'] const chartList: PresetChartType[] = ['bar', 'horizontalBar', 'line', 'area', 'scatter', 'pie', 'ring']
const selectChart = (chart: string) => { const selectChart = (chart: PresetChartType) => {
emit('select', chart) emit('select', chart)
} }
@ -33,16 +38,16 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.chart-pool { .chart-pool {
width: 120px; width: 200px;
margin-bottom: -5px; margin-bottom: -5px;
@include flex-grid-layout(); @include flex-grid-layout();
} }
.chart-item { .chart-item {
@include flex-grid-layout-children(3, 32%); @include flex-grid-layout-children(5, 19%);
height: 0; height: 0;
padding-bottom: 32%; padding-bottom: 19%;
flex-shrink: 0; flex-shrink: 0;
position: relative; position: relative;
cursor: pointer; cursor: pointer;

View File

@ -31,6 +31,10 @@
@change="e => updateOptions({ horizontalBars: e.target.checked })" @change="e => updateOptions({ horizontalBars: e.target.checked })"
:checked="horizontalBars" :checked="horizontalBars"
>条形图样式</Checkbox> >条形图样式</Checkbox>
<Checkbox
@change="e => updateOptions({ stackBars: e.target.checked })"
:checked="stackBars"
>堆叠样式</Checkbox>
</div> </div>
<div class="row" v-if="handleElement.chartType === 'pie'"> <div class="row" v-if="handleElement.chartType === 'pie'">
<Checkbox <Checkbox
@ -149,10 +153,9 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, onUnmounted, ref, watch } from 'vue' import { defineComponent, onUnmounted, ref, watch } from 'vue'
import { IBarChartOptions, ILineChartOptions, IPieChartOptions } from 'chartist'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { ChartData, PPTChartElement } from '@/types/slides' import { 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'
@ -205,6 +208,7 @@ export default defineComponent({
const showArea = ref(false) const showArea = ref(false)
const horizontalBars = ref(false) const horizontalBars = ref(false)
const donut = ref(false) const donut = ref(false)
const stackBars = ref(false)
watch(handleElement, () => { watch(handleElement, () => {
if (!handleElement.value || handleElement.value.type !== 'chart') return if (!handleElement.value || handleElement.value.type !== 'chart') return
@ -217,6 +221,7 @@ export default defineComponent({
showArea: _showArea, showArea: _showArea,
horizontalBars: _horizontalBars, horizontalBars: _horizontalBars,
donut: _donut, donut: _donut,
stackBars: _stackBars,
} = handleElement.value.options } = handleElement.value.options
if (_lineSmooth !== undefined) lineSmooth.value = _lineSmooth as boolean if (_lineSmooth !== undefined) lineSmooth.value = _lineSmooth as boolean
@ -224,6 +229,7 @@ export default defineComponent({
if (_showArea !== undefined) showArea.value = _showArea if (_showArea !== undefined) showArea.value = _showArea
if (_horizontalBars !== undefined) horizontalBars.value = _horizontalBars if (_horizontalBars !== undefined) horizontalBars.value = _horizontalBars
if (_donut !== undefined) donut.value = _donut if (_donut !== undefined) donut.value = _donut
if (_stackBars !== undefined) stackBars.value = _stackBars
} }
themeColor.value = handleElement.value.themeColor themeColor.value = handleElement.value.themeColor
@ -248,7 +254,7 @@ export default defineComponent({
} }
// 线线线线 // 线线线线
const updateOptions = (optionProps: ILineChartOptions & IBarChartOptions & IPieChartOptions) => { const updateOptions = (optionProps: ChartOptions) => {
const _handleElement = handleElement.value as PPTChartElement const _handleElement = handleElement.value as PPTChartElement
const newOptions = { ..._handleElement.options, ...optionProps } const newOptions = { ..._handleElement.options, ...optionProps }
@ -316,6 +322,7 @@ export default defineComponent({
showArea, showArea,
horizontalBars, horizontalBars,
donut, donut,
stackBars,
updateOptions, updateOptions,
themeColor, themeColor,
gridColor, gridColor,
@ -333,6 +340,9 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chart-style-panel {
user-select: none;
}
.row { .row {
width: 100%; width: 100%;
display: flex; display: flex;

View File

@ -34,11 +34,8 @@ import Chartist, {
IChartistLineChart, IChartistLineChart,
IChartistBarChart, IChartistBarChart,
IChartistPieChart, IChartistPieChart,
ILineChartOptions,
IBarChartOptions,
IPieChartOptions,
} from 'chartist' } from 'chartist'
import { ChartData, ChartType } from '@/types/slides' import { ChartData, ChartOptions, ChartType } from '@/types/slides'
import { injectKeySlideScale } from '@/types/injectKey' import { injectKeySlideScale } from '@/types/injectKey'
import 'chartist/dist/scss/chartist.scss' import 'chartist/dist/scss/chartist.scss'
@ -63,7 +60,7 @@ export default defineComponent({
required: true, required: true,
}, },
options: { options: {
type: Object as PropType<ILineChartOptions & IBarChartOptions & IPieChartOptions>, type: Object as PropType<ChartOptions>,
}, },
themeColor: { themeColor: {
type: Array as PropType<string[]>, type: Array as PropType<string[]>,