diff --git a/src/assets/styles/antd.scss b/src/assets/styles/antd.scss index 84db77da..479b6575 100644 --- a/src/assets/styles/antd.scss +++ b/src/assets/styles/antd.scss @@ -13,6 +13,10 @@ } .ant-btn { font-size: 13px !important; + + &.no-padding { + padding: 0; + } } .ant-radio-group { font-size: 13px !important; diff --git a/src/store/constants.ts b/src/store/constants.ts index d750a7ec..6685e65b 100644 --- a/src/store/constants.ts +++ b/src/store/constants.ts @@ -22,7 +22,7 @@ export enum MutationTypes { UPDATE_SLIDE_INDEX = 'updateSlideIndex', ADD_ELEMENT = 'addElement', UPDATE_ELEMENT = 'updateElement', - REMOVE_ELEMENT_PROP = 'removeElementProp', + REMOVE_ELEMENT_PROPS = 'removeElementProps', // snapshot SET_SNAPSHOT_CURSOR = 'setSnapshotCursor', diff --git a/src/store/mutations.ts b/src/store/mutations.ts index daafee14..2f08df9d 100644 --- a/src/store/mutations.ts +++ b/src/store/mutations.ts @@ -1,4 +1,5 @@ import { MutationTree } from 'vuex' +import omit from 'lodash/omit' import { MutationTypes } from './constants' import { State } from './index' import { Slide, PPTElement } from '@/types/slides' @@ -8,7 +9,7 @@ import { isSupportFontFamily } from '@/utils/fontFamily' interface RemoveElementPropData { id: string; - propName: string; + propName: string | string[]; } interface UpdateElementData { @@ -120,14 +121,14 @@ export const mutations: MutationTree = { state.slides[slideIndex].elements = (elements as PPTElement[]) }, - [MutationTypes.REMOVE_ELEMENT_PROP](state, data: RemoveElementPropData) { + [MutationTypes.REMOVE_ELEMENT_PROPS](state, data: RemoveElementPropData) { const { id, propName } = data + const propsNames = typeof propName === 'string' ? [propName] : propName const slideIndex = state.slideIndex const slide = state.slides[slideIndex] const elements = slide.elements.map(el => { - if(el.id === id) delete el[propName] - return el + return el.id === id ? omit(el, propsNames) : el }) state.slides[slideIndex].elements = (elements as PPTElement[]) }, diff --git a/src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue b/src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue index e3691316..7c487eda 100644 --- a/src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue +++ b/src/views/Editor/Toolbar/ElementStylePanel/ImageStylePanel.vue @@ -5,38 +5,39 @@ :style="{ backgroundImage: `url(${handleElement.src})` }" > - - + + + @@ -94,6 +97,7 @@ import { useStore } from 'vuex' import { MutationTypes, State } from '@/store' import { PPTImageElement } from '@/types/slides' import { CLIPPATHS } from '@/configs/imageClip' +import { getImageDataURL } from '@/utils/image' import useHistorySnapshot from '@/hooks/useHistorySnapshot' import ElementOutline from '../common/ElementOutline.vue' @@ -213,7 +217,7 @@ export default defineComponent({ clipPanelVisible.value = false } - const presetImageClip = (shape: string, ratio = 0) => { + const getImageElementDataBeforeClip = () => { // 图片当前宽高位置、裁剪范围 const imgWidth = handleElement.value.width const imgHeight = handleElement.value.height @@ -226,27 +230,27 @@ export default defineComponent({ const originHeight = imgHeight / ((originClipRange[1][1] - originClipRange[0][1]) / 100) const originLeft = imgLeft - originWidth * (originClipRange[0][0] / 100) const originTop = imgTop - originHeight * (originClipRange[0][1] / 100) - - // 取消裁剪(移除裁剪属性,并将宽高位置设置为原本未裁剪过时的状态) - if(shape === 'none') { - store.commit(MutationTypes.UPDATE_ELEMENT, { - id: handleElement.value.id, - props: { - left: originLeft, - top: originTop, - width: originWidth, - height: originHeight, - }, - }) - store.commit(MutationTypes.REMOVE_ELEMENT_PROP, { - id: handleElement.value.id, - propName: 'clip', - }) - clipPanelVisible.value = false - } + return { + originClipRange, + originWidth, + originHeight, + originLeft, + originTop, + } + } + + const presetImageClip = (shape: string, ratio = 0) => { + const { + originClipRange, + originWidth, + originHeight, + originLeft, + originTop, + } = getImageElementDataBeforeClip() + // 设置形状和纵横比 - else if(ratio) { + if(ratio) { const imageRatio = originHeight / originWidth const min = 0 @@ -271,9 +275,7 @@ export default defineComponent({ height: originHeight * (range[1][1] - range[0][1]) / 100, }, }) - clipImage() } - // 仅设置形状(维持目前的裁剪范围) else { store.commit(MutationTypes.UPDATE_ELEMENT, { @@ -282,8 +284,46 @@ export default defineComponent({ clip: { ...handleElement.value.clip, shape, range: originClipRange } }, }) - clipImage() } + clipImage() + addHistorySnapshot() + } + + const replaceImage = (files: File[]) => { + const imageFile = files[0] + if(!imageFile) return + getImageDataURL(imageFile).then(dataURL => { + const props = { src: dataURL } + store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.value.id, props }) + }) + addHistorySnapshot() + } + + const resetImage = () => { + if(handleElement.value.clip) { + const { + originWidth, + originHeight, + originLeft, + originTop, + } = getImageElementDataBeforeClip() + + store.commit(MutationTypes.UPDATE_ELEMENT, { + id: handleElement.value.id, + props: { + left: originLeft, + top: originTop, + width: originWidth, + height: originHeight, + }, + }) + } + + store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { + id: handleElement.value.id, + propName: ['clip', 'outline', 'flip', 'shadow', 'filter'], + }) + addHistorySnapshot() } return { @@ -297,6 +337,8 @@ export default defineComponent({ updateFilter, clipImage, presetImageClip, + replaceImage, + resetImage, } }, }) diff --git a/src/views/Editor/Toolbar/common/ElementShadow.vue b/src/views/Editor/Toolbar/common/ElementShadow.vue index 4c695272..2a67ea8e 100644 --- a/src/views/Editor/Toolbar/common/ElementShadow.vue +++ b/src/views/Editor/Toolbar/common/ElementShadow.vue @@ -10,7 +10,7 @@
水平阴影:
垂直阴影: