refactor: 为线条以外的元素都补充旋转角度属性

This commit is contained in:
pipipi-pikachu 2021-11-20 16:05:58 +08:00
parent f7e3c6cef1
commit 8a8a597208
19 changed files with 218 additions and 163 deletions

View File

@ -90,6 +90,7 @@ export default () => {
top: 81.25,
width: 400,
height: 400,
rotate: 0,
themeColor: [themeColor.value],
gridColor: fontColor.value,
data: {
@ -135,6 +136,7 @@ export default () => {
width,
height,
colWidths,
rotate: 0,
data,
left: (VIEWPORT_SIZE - width) / 2,
top: (VIEWPORT_SIZE * viewportRatio.value - height) / 2,
@ -233,6 +235,7 @@ export default () => {
id: createRandomCode(),
width: data.w,
height: data.h,
rotate: 0,
left: (VIEWPORT_SIZE - data.w) / 2,
top: (VIEWPORT_SIZE * viewportRatio.value - data.h) / 2,
path: data.path,
@ -254,6 +257,7 @@ export default () => {
id: createRandomCode(),
width: 500,
height: 300,
rotate: 0,
left: (VIEWPORT_SIZE - 500) / 2,
top: (VIEWPORT_SIZE * viewportRatio.value - 300) / 2,
src,

View File

@ -62,6 +62,8 @@ export interface PPTElementOutline {
*
* height: 元素高度
*
* rotate: 旋转角度
*
* link?: 超链接地址
*/
interface PPTBaseElement {
@ -72,6 +74,7 @@ interface PPTBaseElement {
groupId?: string;
width: number;
height: number;
rotate: number;
link?: string;
}
@ -83,8 +86,6 @@ interface PPTBaseElement {
*
* content: 文本内容HTML字符串
*
* rotate: 旋转角度
*
* defaultFontName: 默认字体HTML内联样式覆盖
*
* defaultColor: 默认颜色HTML内联样式覆盖
@ -104,7 +105,6 @@ interface PPTBaseElement {
export interface PPTTextElement extends PPTBaseElement {
type: 'text';
content: string;
rotate: number;
defaultFontName: string;
defaultColor: string;
outline?: PPTElementOutline;
@ -178,8 +178,6 @@ export interface ImageElementClip {
*
* src: 图片地址
*
* rotate: 旋转角度
*
* outline?: 边框
*
* filters?: 图片滤镜
@ -196,7 +194,6 @@ export interface PPTImageElement extends PPTBaseElement {
type: 'image';
fixedRatio: boolean;
src: string;
rotate: number;
outline?: PPTElementOutline;
filters?: ImageElementFilters;
clip?: ImageElementClip;
@ -254,8 +251,6 @@ export interface ShapeText {
*
* gradient?: 渐变
*
* rotate: 旋转角度
*
* outline?: 边框
*
* opacity?: 不透明度
@ -277,7 +272,6 @@ export interface PPTShapeElement extends PPTBaseElement {
fixedRatio: boolean;
fill: string;
gradient?: ShapeGradient;
rotate: number;
outline?: PPTElementOutline;
opacity?: number;
flipH?: boolean;
@ -311,7 +305,7 @@ export type LinePoint = '' | 'arrow' | 'dot'
*
* curve?: 曲线中点位置[x, y]
*/
export interface PPTLineElement extends Omit<PPTBaseElement, 'height'> {
export interface PPTLineElement extends Omit<PPTBaseElement, 'height' | 'rotate'> {
type: 'line';
start: [number, number];
end: [number, number];

View File

@ -7,15 +7,21 @@
:type="line.type"
:style="line.style"
/>
<template v-if="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)">
<template v-if="handlerVisible">
<ResizeHandler
class="operate-resize-handler"
v-for="point in resizeHandlers"
:key="point.direction"
:type="point.direction"
:rotate="elementInfo.rotate"
:style="point.style"
@mousedown.stop="$event => scaleElement($event, elementInfo, point.direction)"
/>
<RotateHandler
class="operate-rotate-handler"
:style="{ left: scaleWidth / 2 + 'px' }"
@mousedown.stop="rotateElement(elementInfo)"
/>
</template>
</div>
</template>
@ -28,31 +34,35 @@ import { PPTShapeElement, PPTVideoElement, PPTLatexElement } from '@/types/slide
import { OperateResizeHandler } from '@/types/edit'
import useCommonOperate from '../hooks/useCommonOperate'
import RotateHandler from './RotateHandler.vue'
import ResizeHandler from './ResizeHandler.vue'
import BorderLine from './BorderLine.vue'
type PPTElement = PPTShapeElement | PPTVideoElement | PPTLatexElement
export default defineComponent({
name: 'common-element-operate',
inheritAttrs: false,
components: {
RotateHandler,
ResizeHandler,
BorderLine,
},
props: {
elementInfo: {
type: Object as PropType<PPTShapeElement | PPTVideoElement | PPTLatexElement>,
type: Object as PropType<PPTElement>,
required: true,
},
isActiveGroupElement: {
handlerVisible: {
type: Boolean,
required: true,
},
isMultiSelect: {
type: Boolean,
rotateElement: {
type: Function as PropType<(element: PPTElement) => void>,
required: true,
},
scaleElement: {
type: Function as PropType<(e: MouseEvent, element: PPTShapeElement, command: OperateResizeHandler) => void>,
type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateResizeHandler) => void>,
required: true,
},
},

View File

@ -7,7 +7,7 @@
:type="line.type"
:style="line.style"
/>
<template v-if="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)">
<template v-if="handlerVisible">
<ResizeHandler
class="operate-resize-handler"
v-for="point in resizeHandlers"
@ -50,11 +50,7 @@ export default defineComponent({
type: Object as PropType<PPTImageElement>,
required: true,
},
isActiveGroupElement: {
type: Boolean,
required: true,
},
isMultiSelect: {
handlerVisible: {
type: Boolean,
required: true,
},

View File

@ -1,6 +1,6 @@
<template>
<div class="text-element-operate">
<template v-if="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)">
<template v-if="handlerVisible">
<ResizeHandler
class="operate-resize-handler"
v-for="point in resizeHandlers"
@ -33,11 +33,7 @@ export default defineComponent({
type: Object as PropType<PPTLineElement>,
required: true,
},
isActiveGroupElement: {
type: Boolean,
required: true,
},
isMultiSelect: {
handlerVisible: {
type: Boolean,
required: true,
},

View File

@ -7,7 +7,7 @@
:type="line.type"
:style="line.style"
/>
<template v-if="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)">
<template v-if="handlerVisible">
<ResizeHandler
class="operate-resize-handler"
v-for="point in resizeHandlers"
@ -51,11 +51,7 @@ export default defineComponent({
type: Object as PropType<PPTShapeElement>,
required: true,
},
isActiveGroupElement: {
type: Boolean,
required: true,
},
isMultiSelect: {
handlerVisible: {
type: Boolean,
required: true,
},

View File

@ -7,15 +7,21 @@
:type="line.type"
:style="line.style"
/>
<template v-if="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)">
<template v-if="handlerVisible">
<ResizeHandler
class="operate-resize-handler"
v-for="point in textElementResizeHandlers"
:key="point.direction"
:type="point.direction"
:rotate="elementInfo.rotate"
:style="point.style"
@mousedown.stop="$event => scaleElement($event, elementInfo, point.direction)"
/>
<RotateHandler
class="operate-rotate-handler"
:style="{ left: scaleWidth / 2 + 'px' }"
@mousedown.stop="rotateElement(elementInfo)"
/>
</template>
</div>
</template>
@ -28,6 +34,7 @@ import { PPTTableElement } from '@/types/slides'
import { OperateResizeHandler } from '@/types/edit'
import useCommonOperate from '../hooks/useCommonOperate'
import RotateHandler from './RotateHandler.vue'
import ResizeHandler from './ResizeHandler.vue'
import BorderLine from './BorderLine.vue'
@ -35,6 +42,7 @@ export default defineComponent({
name: 'table-element-operate',
inheritAttrs: false,
components: {
RotateHandler,
ResizeHandler,
BorderLine,
},
@ -43,12 +51,12 @@ export default defineComponent({
type: Object as PropType<PPTTableElement>,
required: true,
},
isActiveGroupElement: {
handlerVisible: {
type: Boolean,
required: true,
},
isMultiSelect: {
type: Boolean,
rotateElement: {
type: Function as PropType<(element: PPTTableElement) => void>,
required: true,
},
scaleElement: {

View File

@ -7,7 +7,7 @@
:type="line.type"
:style="line.style"
/>
<template v-if="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)">
<template v-if="handlerVisible">
<ResizeHandler
class="operate-resize-handler"
v-for="point in textElementResizeHandlers"
@ -51,11 +51,7 @@ export default defineComponent({
type: Object as PropType<PPTTextElement>,
required: true,
},
isActiveGroupElement: {
type: Boolean,
required: true,
},
isMultiSelect: {
handlerVisible: {
type: Boolean,
required: true,
},

View File

@ -13,8 +13,7 @@
v-if="isSelected"
:is="currentOperateComponent"
:elementInfo="elementInfo"
:isActiveGroupElement="isActiveGroupElement"
:isMultiSelect="isMultiSelect"
:handlerVisible="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)"
:rotateElement="rotateElement"
:scaleElement="scaleElement"
:dragLineElement="dragLineElement"

View File

@ -29,7 +29,7 @@ export default (elementList: Ref<PPTElement[]>) => {
// 获取所有线条以外的未旋转的元素的8个缩放点作为吸附位置
for (let i = 0; i < elementList.value.length; i++) {
const _element = elementList.value[i]
if (_element.type === 'line' || ('rotate' in _element && _element.rotate)) continue
if (_element.type === 'line' || _element.rotate) continue
const left = _element.left
const top = _element.top

View File

@ -99,7 +99,7 @@
</div>
</template>
<template v-if="['text', 'image', 'shape'].includes(handleElement.type)">
<template v-if="handleElement.type !== 'line'">
<Divider />
<div class="row">

View File

@ -6,6 +6,10 @@
width: elementInfo.width + 'px',
height: elementInfo.height + 'px',
}"
>
<div
class="rotate-wrapper"
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
>
<div
class="element-content"
@ -32,6 +36,7 @@
/>
</div>
</div>
</div>
</template>
<script lang="ts">
@ -70,6 +75,10 @@ export default defineComponent({
.base-element-chart {
position: absolute;
}
.rotate-wrapper {
width: 100%;
height: 100%;
}
.element-content {
width: 100%;
height: 100%;

View File

@ -7,6 +7,10 @@
width: elementInfo.width + 'px',
height: elementInfo.height + 'px',
}"
>
<div
class="rotate-wrapper"
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
>
<div
class="element-content"
@ -35,6 +39,7 @@
/>
</div>
</div>
</div>
</template>
<script lang="ts">
@ -93,7 +98,10 @@ export default defineComponent({
cursor: default;
}
}
.rotate-wrapper {
width: 100%;
height: 100%;
}
.element-content {
width: 100%;
height: 100%;

View File

@ -6,6 +6,10 @@
left: elementInfo.left + 'px',
width: elementInfo.width + 'px',
}"
>
<div
class="rotate-wrapper"
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
>
<div class="element-content">
<StaticTable
@ -17,6 +21,7 @@
/>
</div>
</div>
</div>
</template>
<script lang="ts">
@ -43,7 +48,10 @@ export default defineComponent({
.base-element-table {
position: absolute;
}
.rotate-wrapper {
width: 100%;
height: 100%;
}
.element-content {
width: 100%;
height: 100%;

View File

@ -8,6 +8,10 @@
left: elementInfo.left + 'px',
width: elementInfo.width + 'px',
}"
>
<div
class="rotate-wrapper"
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
>
<div
class="element-content"
@ -36,6 +40,7 @@
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
@ -190,7 +195,10 @@ export default defineComponent({
cursor: default;
}
}
.rotate-wrapper {
width: 100%;
height: 100%;
}
.element-content {
width: 100%;
height: 100%;

View File

@ -6,22 +6,27 @@
width: elementInfo.width + 'px',
height: elementInfo.height + 'px',
}"
>
<div
class="rotate-wrapper"
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
>
<div class="element-content" :style="{ backgroundImage: `url(${elementInfo.poster})` }">
<IconPlayOne class="icon" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
import { PPTTableElement } from '@/types/slides'
import { PPTVideoElement } from '@/types/slides'
export default defineComponent({
name: 'base-element-video',
props: {
elementInfo: {
type: Object as PropType<PPTTableElement>,
type: Object as PropType<PPTVideoElement>,
required: true,
},
},
@ -32,7 +37,10 @@ export default defineComponent({
.base-element-video {
position: absolute;
}
.rotate-wrapper {
width: 100%;
height: 100%;
}
.element-content {
width: 100%;
height: 100%;

View File

@ -6,6 +6,10 @@
width: elementInfo.width + 'px',
height: elementInfo.height + 'px',
}"
>
<div
class="rotate-wrapper"
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
>
<div class="element-content">
<VideoPlayer
@ -17,11 +21,12 @@
/>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, inject, PropType, Ref, ref } from 'vue'
import { PPTTableElement } from '@/types/slides'
import { PPTVideoElement } from '@/types/slides'
import VideoPlayer from './VideoPlayer/index.vue'
@ -32,7 +37,7 @@ export default defineComponent({
},
props: {
elementInfo: {
type: Object as PropType<PPTTableElement>,
type: Object as PropType<PPTVideoElement>,
required: true,
},
},
@ -50,7 +55,10 @@ export default defineComponent({
.screen-element-video {
position: absolute;
}
.rotate-wrapper {
width: 100%;
height: 100%;
}
.element-content {
width: 100%;
height: 100%;

View File

@ -7,6 +7,10 @@
width: elementInfo.width + 'px',
height: elementInfo.height + 'px',
}"
>
<div
class="rotate-wrapper"
:style="{ transform: `rotate(${elementInfo.rotate}deg)` }"
>
<div
class="element-content"
@ -28,12 +32,13 @@
></div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, PropType } from 'vue'
import { useStore } from '@/store'
import { PPTTableElement } from '@/types/slides'
import { PPTVideoElement } from '@/types/slides'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import VideoPlayer from './VideoPlayer/index.vue'
@ -45,11 +50,11 @@ export default defineComponent({
},
props: {
elementInfo: {
type: Object as PropType<PPTTableElement>,
type: Object as PropType<PPTVideoElement>,
required: true,
},
selectElement: {
type: Function as PropType<(e: MouseEvent, element: PPTTableElement, canMove?: boolean) => void>,
type: Function as PropType<(e: MouseEvent, element: PPTVideoElement, canMove?: boolean) => void>,
required: true,
},
contextmenus: {
@ -83,7 +88,10 @@ export default defineComponent({
cursor: default;
}
}
.rotate-wrapper {
width: 100%;
height: 100%;
}
.element-content {
width: 100%;
height: 100%;

View File

@ -14,7 +14,6 @@
"baseUrl": ".",
"types": [
"webpack-env",
"jest",
"resize-observer-browser"
],
"paths": {