From 8fa35d464538d9ed81e391098da85f17eab61c69 Mon Sep 17 00:00:00 2001 From: pipipi-pikachu <1171051090@qq.com> Date: Sun, 20 Dec 2020 09:44:03 +0800 Subject: [PATCH] update --- src/store/constants.ts | 1 - src/store/index.ts | 2 - src/store/mutations.ts | 4 - .../Editor/Canvas/MultiSelectOperate.vue | 10 ++- .../Canvas/hooks/useAlignElementToCanvas.ts | 7 +- .../Editor/Canvas/hooks/useCombineElement.ts | 6 +- .../Canvas/hooks/useCopyAndPasteElement.ts | 6 +- .../Editor/Canvas/hooks/useDeleteElement.ts | 5 +- .../Canvas/hooks/useDropImageElement.ts} | 15 ++-- .../Editor/Canvas/hooks/useLockElement.ts | 5 +- .../Editor/Canvas/hooks/useMoveElement.ts | 4 +- .../Editor/Canvas/hooks/useRotateElement.ts | 10 ++- .../Editor/Canvas/hooks/useScaleElement.ts | 80 ++++++++++++++++- .../Editor/Canvas/hooks/useSelectElement.ts | 8 +- .../Editor/Canvas/hooks/useViewportSize.ts | 10 ++- src/views/Editor/Canvas/index.vue | 52 ++++-------- .../Editor/Canvas/utils/elementRotate.ts | 85 ------------------- .../_common/_element/EditableElement.vue | 12 ++- 18 files changed, 156 insertions(+), 166 deletions(-) rename src/{hooks/useDropImage.ts => views/Editor/Canvas/hooks/useDropImageElement.ts} (74%) delete mode 100644 src/views/Editor/Canvas/utils/elementRotate.ts diff --git a/src/store/constants.ts b/src/store/constants.ts index 3d673324..add3133f 100644 --- a/src/store/constants.ts +++ b/src/store/constants.ts @@ -4,7 +4,6 @@ export enum MutationTypes { SET_ACTIVE_ELEMENT_ID_LIST = 'setActiveElementIdList', SET_HANDLE_ELEMENT_ID = 'setHandleElementId', SET_EDITOR_AREA_SHOW_SCALE = 'setEditorAreaShowScale', - SET_CANVAS_SCALE = 'setCanvasScale', SET_THUMBNAILS_FOCUS = 'setThumbnailsFocus', SET_EDITORAREA_FOCUS = 'setEditorAreaFocus', SET_DISABLE_HOTKEYS_STATE = 'setDisableHotkeysState', diff --git a/src/store/index.ts b/src/store/index.ts index dc1e5aae..fc1c70e0 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -13,7 +13,6 @@ export interface State { activeElementIdList: string[]; handleElementId: string; editorAreaShowScale: number; - canvasScale: number; thumbnailsFocus: boolean; editorAreaFocus: boolean; disableHotkeys: boolean; @@ -30,7 +29,6 @@ const state: State = { activeElementIdList: [], handleElementId: '', editorAreaShowScale: 85, - canvasScale: 1, thumbnailsFocus: false, editorAreaFocus: false, disableHotkeys: false, diff --git a/src/store/mutations.ts b/src/store/mutations.ts index b7f490f9..4065d299 100644 --- a/src/store/mutations.ts +++ b/src/store/mutations.ts @@ -34,10 +34,6 @@ export const mutations: MutationTree = { state.editorAreaShowScale = scale }, - [MutationTypes.SET_CANVAS_SCALE](state, scale: number) { - state.canvasScale = scale - }, - [MutationTypes.SET_THUMBNAILS_FOCUS](state, isFocus: boolean) { state.thumbnailsFocus = isFocus }, diff --git a/src/views/Editor/Canvas/MultiSelectOperate.vue b/src/views/Editor/Canvas/MultiSelectOperate.vue index 9fdf9a1e..717b5e9e 100644 --- a/src/views/Editor/Canvas/MultiSelectOperate.vue +++ b/src/views/Editor/Canvas/MultiSelectOperate.vue @@ -41,6 +41,10 @@ export default defineComponent({ BorderLine, }, props: { + canvasScale: { + type: Number, + required: true, + }, elementList: { type: Array as PropType, required: true, @@ -52,7 +56,6 @@ export default defineComponent({ }, setup(props) { const store = useStore() - const canvasScale = computed(() => store.state.canvasScale) const activeElementIdList = computed(() => store.state.activeElementIdList) const localActiveElementList = computed(() => props.elementList.filter(el => activeElementIdList.value.includes(el.elId))) @@ -63,8 +66,8 @@ export default defineComponent({ maxY: 0, }) - const width = computed(() => (range.maxX - range.minX) * canvasScale.value) - const height = computed(() => (range.maxY - range.minY) * canvasScale.value) + const width = computed(() => (range.maxX - range.minX) * props.canvasScale) + const height = computed(() => (range.maxY - range.minY) * props.canvasScale) const resizablePoints = computed(() => { return [ @@ -110,7 +113,6 @@ export default defineComponent({ return { ...toRefs(range), - canvasScale, borderLines, disableResizablePoint, resizablePoints, diff --git a/src/views/Editor/Canvas/hooks/useAlignElementToCanvas.ts b/src/views/Editor/Canvas/hooks/useAlignElementToCanvas.ts index c39ae773..c52e0927 100644 --- a/src/views/Editor/Canvas/hooks/useAlignElementToCanvas.ts +++ b/src/views/Editor/Canvas/hooks/useAlignElementToCanvas.ts @@ -1,4 +1,4 @@ -import { Ref } from 'vue' +import { Ref, computed } from 'vue' import { useStore } from 'vuex' import { State, MutationTypes } from '@/store' import { PPTElement } from '@/types/slides' @@ -6,9 +6,12 @@ import { ElementAlignCommand, ElementAlignCommands } from '@/types/edit' import { getElementListRange } from '../utils/elementRange' import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas' -export default (elementList: Ref, activeElementList: Ref, activeElementIdList: Ref) => { +export default (elementList: Ref) => { const store = useStore() + const activeElementIdList = computed(() => store.state.activeElementIdList) + const activeElementList: Ref = computed(() => store.getters.activeElementList) + const alignElementToCanvas = (command: ElementAlignCommand) => { const viewportWidth = VIEWPORT_SIZE const viewportHeight = VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO diff --git a/src/views/Editor/Canvas/hooks/useCombineElement.ts b/src/views/Editor/Canvas/hooks/useCombineElement.ts index 06cc018d..8ad6e791 100644 --- a/src/views/Editor/Canvas/hooks/useCombineElement.ts +++ b/src/views/Editor/Canvas/hooks/useCombineElement.ts @@ -1,11 +1,13 @@ -import { Ref } from 'vue' +import { Ref, computed } from 'vue' import { useStore } from 'vuex' import { State, MutationTypes } from '@/store' import { PPTElement } from '@/types/slides' import { createRandomCode } from '@/utils/common' -export default (elementList: Ref, activeElementList: Ref, activeElementIdList: Ref) => { +export default (elementList: Ref) => { const store = useStore() + const activeElementIdList = computed(() => store.state.activeElementIdList) + const activeElementList: Ref = computed(() => store.getters.activeElementList) // 组合元素(为当前所有激活元素添加一个相同的groupId) const combineElements = () => { diff --git a/src/views/Editor/Canvas/hooks/useCopyAndPasteElement.ts b/src/views/Editor/Canvas/hooks/useCopyAndPasteElement.ts index b06d8aef..cb63374d 100644 --- a/src/views/Editor/Canvas/hooks/useCopyAndPasteElement.ts +++ b/src/views/Editor/Canvas/hooks/useCopyAndPasteElement.ts @@ -1,4 +1,4 @@ -import { Ref } from 'vue' +import { Ref, computed } from 'vue' import { useStore } from 'vuex' import { State, MutationTypes } from '@/store' import { PPTElement } from '@/types/slides' @@ -6,8 +6,10 @@ import { copyText, readClipboard } from '@/utils/clipboard' import { encrypt, decrypt } from '@/utils/crypto' import { message } from 'ant-design-vue' -export default (deleteElement: () => void, activeElementList: Ref, activeElementIdList: Ref) => { +export default (deleteElement: () => void) => { const store = useStore() + const activeElementIdList = computed(() => store.state.activeElementIdList) + const activeElementList: Ref = computed(() => store.getters.activeElementList) const copyElement = () => { if(!activeElementIdList.value.length) return diff --git a/src/views/Editor/Canvas/hooks/useDeleteElement.ts b/src/views/Editor/Canvas/hooks/useDeleteElement.ts index e8640c19..32f5be1c 100644 --- a/src/views/Editor/Canvas/hooks/useDeleteElement.ts +++ b/src/views/Editor/Canvas/hooks/useDeleteElement.ts @@ -1,10 +1,11 @@ -import { Ref } from 'vue' +import { Ref, computed } from 'vue' import { useStore } from 'vuex' import { State, MutationTypes } from '@/store' import { PPTElement } from '@/types/slides' -export default (elementList: Ref, activeElementIdList: Ref) => { +export default (elementList: Ref) => { const store = useStore() + const activeElementIdList = computed(() => store.state.activeElementIdList) const deleteElement = () => { if(!activeElementIdList.value.length) return diff --git a/src/hooks/useDropImage.ts b/src/views/Editor/Canvas/hooks/useDropImageElement.ts similarity index 74% rename from src/hooks/useDropImage.ts rename to src/views/Editor/Canvas/hooks/useDropImageElement.ts index a838f48f..df968ace 100644 --- a/src/hooks/useDropImage.ts +++ b/src/views/Editor/Canvas/hooks/useDropImageElement.ts @@ -1,14 +1,17 @@ -import { ref, onMounted, onUnmounted, Ref } from 'vue' +import { onMounted, onUnmounted, Ref } from 'vue' +import { getImageDataURL } from '@/utils/image' export default (elementRef: Ref) => { - const imageFile = ref(null) - const handleDrop = (e: DragEvent) => { if(!e.dataTransfer) return const file = e.dataTransfer.items[0] if( file.kind === 'file' && file.type.indexOf('image') !== -1 ) { - const _imageFile = file.getAsFile() - if(_imageFile) imageFile.value = _imageFile + const imageFile = file.getAsFile() + if(imageFile) { + getImageDataURL(imageFile).then(dataURL => { + console.log(dataURL) + }) + } } } @@ -28,6 +31,4 @@ export default (elementRef: Ref) => { document.ondragenter = null document.ondragover = null }) - - return imageFile } \ No newline at end of file diff --git a/src/views/Editor/Canvas/hooks/useLockElement.ts b/src/views/Editor/Canvas/hooks/useLockElement.ts index 92582808..16ee5ddb 100644 --- a/src/views/Editor/Canvas/hooks/useLockElement.ts +++ b/src/views/Editor/Canvas/hooks/useLockElement.ts @@ -1,10 +1,11 @@ import { useStore } from 'vuex' -import { Ref } from 'vue' +import { Ref, computed } from 'vue' import { State, MutationTypes } from '@/store' import { PPTElement } from '@/types/slides' -export default (elementList: Ref, activeElementIdList: Ref) => { +export default (elementList: Ref) => { const store = useStore() + const activeElementIdList = computed(() => store.state.activeElementIdList) const lockElement = (handleElement: PPTElement) => { const newElementList: PPTElement[] = JSON.parse(JSON.stringify(elementList.value)) diff --git a/src/views/Editor/Canvas/hooks/useMoveElement.ts b/src/views/Editor/Canvas/hooks/useMoveElement.ts index 32edf766..acb4fb18 100644 --- a/src/views/Editor/Canvas/hooks/useMoveElement.ts +++ b/src/views/Editor/Canvas/hooks/useMoveElement.ts @@ -1,4 +1,4 @@ -import { Ref } from 'vue' +import { Ref, computed } from 'vue' import { useStore } from 'vuex' import { State, MutationTypes } from '@/store' import { ElementTypes, PPTElement } from '@/types/slides' @@ -9,12 +9,12 @@ import { AlignLine, uniqAlignLines } from '../utils/alignLines' export default ( elementList: Ref, - activeElementIdList: Ref, activeGroupElementId: Ref, canvasScale: Ref, alignmentLines: Ref, ) => { const store = useStore() + const activeElementIdList = computed(() => store.state.activeElementIdList) const moveElement = (e: MouseEvent, element: PPTElement) => { if(!activeElementIdList.value.includes(element.elId)) return diff --git a/src/views/Editor/Canvas/hooks/useRotateElement.ts b/src/views/Editor/Canvas/hooks/useRotateElement.ts index b28a475c..3d971cfb 100644 --- a/src/views/Editor/Canvas/hooks/useRotateElement.ts +++ b/src/views/Editor/Canvas/hooks/useRotateElement.ts @@ -2,7 +2,15 @@ import { Ref } from 'vue' import { useStore } from 'vuex' import { State, MutationTypes } from '@/store' import { PPTElement, PPTTextElement, PPTImageElement, PPTShapeElement } from '@/types/slides' -import { getAngleFromCoordinate } from '../utils/elementRotate' + +// 给定一个坐标,计算该坐标到(0, 0)点连线的弧度值 +// 注意,Math.atan2的一般用法是Math.atan2(y, x)返回的是原点(0,0)到(x,y)点的线段与X轴正方向之间的弧度值 +// 这里将使用时将x与y的传入顺序交换了,为的是获取原点(0,0)到(x,y)点的线段与Y轴正方向之间的弧度值 +export const getAngleFromCoordinate = (x: number, y: number) => { + const radian = Math.atan2(x, y) + const angle = 180 / Math.PI * radian + return angle +} export default (elementList: Ref, viewportRef: Ref, canvasScale: Ref) => { const store = useStore() diff --git a/src/views/Editor/Canvas/hooks/useScaleElement.ts b/src/views/Editor/Canvas/hooks/useScaleElement.ts index 95f26ea8..7d847dc5 100644 --- a/src/views/Editor/Canvas/hooks/useScaleElement.ts +++ b/src/views/Editor/Canvas/hooks/useScaleElement.ts @@ -4,19 +4,93 @@ import { State, MutationTypes } from '@/store' import { ElementTypes, PPTElement, PPTLineElement } from '@/types/slides' import { OPERATE_KEYS, ElementScaleHandler } from '@/types/edit' import { VIEWPORT_SIZE, VIEWPORT_ASPECT_RATIO } from '@/configs/canvas' -import { getRotateElementPoints, getOppositePoint } from '../utils/elementRotate' import { AlignLine, uniqAlignLines } from '../utils/alignLines' import { AlignmentLineProps, MultiSelectRange } from '../types/index' +// 计算元素被旋转一定角度后,八个操作点的新坐标 +interface RotateElementData { + left: number; + top: number; + width: number; + height: number; +} +export const getRotateElementPoints = (element: RotateElementData, angle: number) => { + const { left, top, width, height } = element + + const radius = Math.sqrt( Math.pow(width, 2) + Math.pow(height, 2) ) / 2 + const auxiliaryAngle = Math.atan(height / width) * 180 / Math.PI + + const tlbraRadian = (180 - angle - auxiliaryAngle) * Math.PI / 180 + const trblaRadian = (auxiliaryAngle - angle) * Math.PI / 180 + const taRadian = (90 - angle) * Math.PI / 180 + const raRadian = angle * Math.PI / 180 + + const halfWidth = width / 2 + const halfHeight = height / 2 + + const middleLeft = left + halfWidth + const middleTop = top + halfHeight + + const leftTopPoint = { + left: middleLeft + radius * Math.cos(tlbraRadian), + top: middleTop - radius * Math.sin(tlbraRadian), + } + const topPoint = { + left: middleLeft + halfHeight * Math.cos(taRadian), + top: middleTop - halfHeight * Math.sin(taRadian), + } + const rightTopPoint = { + left: middleLeft + radius * Math.cos(trblaRadian), + top: middleTop - radius * Math.sin(trblaRadian), + } + const rightPoint = { + left: middleLeft + halfWidth * Math.cos(raRadian), + top: middleTop + halfWidth * Math.sin(raRadian), + } + const rightBottomPoint = { + left: middleLeft - radius * Math.cos(tlbraRadian), + top: middleTop + radius * Math.sin(tlbraRadian), + } + const bottomPoint = { + left: middleLeft - halfHeight * Math.sin(raRadian), + top: middleTop + halfHeight * Math.cos(raRadian), + } + const leftBottomPoint = { + left: middleLeft - radius * Math.cos(trblaRadian), + top: middleTop + radius * Math.sin(trblaRadian), + } + const leftPoint = { + left: middleLeft - halfWidth * Math.cos(raRadian), + top: middleTop - halfWidth * Math.sin(raRadian), + } + + return { leftTopPoint, topPoint, rightTopPoint, rightPoint, rightBottomPoint, bottomPoint, leftBottomPoint, leftPoint } +} + +// 获取元素某个操作点对角线上另一端的操作点坐标(例如:左上 <-> 右下) +export const getOppositePoint = (direction: number, points: ReturnType): { left: number; top: number } => { + const oppositeMap = { + [OPERATE_KEYS.RIGHT_BOTTOM]: points.leftTopPoint, + [OPERATE_KEYS.LEFT_BOTTOM]: points.rightTopPoint, + [OPERATE_KEYS.LEFT_TOP]: points.rightBottomPoint, + [OPERATE_KEYS.RIGHT_TOP]: points.leftBottomPoint, + [OPERATE_KEYS.TOP]: points.bottomPoint, + [OPERATE_KEYS.BOTTOM]: points.topPoint, + [OPERATE_KEYS.LEFT]: points.rightPoint, + [OPERATE_KEYS.RIGHT]: points.leftPoint, + } + return oppositeMap[direction] +} + export default ( elementList: Ref, canvasScale: Ref, activeGroupElementId: Ref, - activeElementIdList: Ref, alignmentLines: Ref, ) => { const store = useStore() - const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive) + const activeElementIdList = computed(() => store.state.activeElementIdList) + const ctrlOrShiftKeyActive: Ref = computed(() => store.getters.ctrlOrShiftKeyActive) const scaleElement = (e: MouseEvent, element: Exclude, command: ElementScaleHandler) => { let isMouseDown = true diff --git a/src/views/Editor/Canvas/hooks/useSelectElement.ts b/src/views/Editor/Canvas/hooks/useSelectElement.ts index 1190206f..90a64615 100644 --- a/src/views/Editor/Canvas/hooks/useSelectElement.ts +++ b/src/views/Editor/Canvas/hooks/useSelectElement.ts @@ -6,14 +6,14 @@ import { PPTElement } from '@/types/slides' export default ( elementList: Ref, - activeElementIdList: Ref, activeGroupElementId: Ref, - editorAreaFocus: Ref, - handleElementId: Ref, moveElement: (e: MouseEvent, element: PPTElement) => void, ) => { const store = useStore() - const ctrlOrShiftKeyActive = computed(() => store.getters.ctrlOrShiftKeyActive) + const activeElementIdList = computed(() => store.state.activeElementIdList) + const handleElementId = computed(() => store.state.handleElementId) + const editorAreaFocus = computed(() => store.state.editorAreaFocus) + const ctrlOrShiftKeyActive: Ref = computed(() => store.getters.ctrlOrShiftKeyActive) const selectElement = (e: MouseEvent, element: PPTElement, canMove = true) => { if(!editorAreaFocus.value) store.commit(MutationTypes.SET_EDITORAREA_FOCUS, true) diff --git a/src/views/Editor/Canvas/hooks/useViewportSize.ts b/src/views/Editor/Canvas/hooks/useViewportSize.ts index 0ac59f3a..e20cef20 100644 --- a/src/views/Editor/Canvas/hooks/useViewportSize.ts +++ b/src/views/Editor/Canvas/hooks/useViewportSize.ts @@ -30,6 +30,13 @@ export default (canvasRef: Ref) => { } } + const viewportStyles = computed(() => ({ + width: VIEWPORT_SIZE, + height: VIEWPORT_SIZE * VIEWPORT_ASPECT_RATIO, + left: viewportLeft.value, + top: viewportTop.value, + })) + const resizeObserver = new ResizeObserver(setViewportSize) onMounted(() => { @@ -41,7 +48,6 @@ export default (canvasRef: Ref) => { return { canvasScale, - viewportLeft, - viewportTop, + viewportStyles, } } \ No newline at end of file diff --git a/src/views/Editor/Canvas/index.vue b/src/views/Editor/Canvas/index.vue index 24f6784b..47ec3023 100644 --- a/src/views/Editor/Canvas/index.vue +++ b/src/views/Editor/Canvas/index.vue @@ -40,11 +40,13 @@ v-if="activeElementIdList.length > 1" :elementList="elementList" :scaleMultiElement="scaleMultiElement" + :canvasScale="canvasScale" />