|
|
@@ -11,22 +11,8 @@
|
|
|
}"
|
|
|
@mousedown="$event => handleSelectElement($event)"
|
|
|
>
|
|
|
- <ImageClip
|
|
|
- v-if="isCliping"
|
|
|
- :src="elementInfo.src"
|
|
|
- :clipData="elementInfo.clip"
|
|
|
- :canvasScale="canvasScale"
|
|
|
- :width="elementInfo.width"
|
|
|
- :height="elementInfo.height"
|
|
|
- :top="elementInfo.top"
|
|
|
- :left="elementInfo.left"
|
|
|
- :clipPath="clipShape.style"
|
|
|
- @clip="range => clip(range)"
|
|
|
- />
|
|
|
-
|
|
|
<div
|
|
|
class="element-content"
|
|
|
- v-if="!isCliping"
|
|
|
v-contextmenu="contextmenus"
|
|
|
:style="{
|
|
|
filter: shadowStyle ? `drop-shadow(${shadowStyle})` : '',
|
|
|
@@ -69,74 +55,25 @@
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
- <div
|
|
|
- class="operate"
|
|
|
- :class="{
|
|
|
- 'selected': isSelected,
|
|
|
- 'multi-select': isMultiSelect && isSelected,
|
|
|
- 'active': isActive,
|
|
|
- }"
|
|
|
- :style="{ transform: `scale(${1 / canvasScale})` }"
|
|
|
- v-if="!isCliping"
|
|
|
- >
|
|
|
- <BorderLine
|
|
|
- class="operate-border-line"
|
|
|
- v-for="line in borderLines"
|
|
|
- :key="line.type"
|
|
|
- :type="line.type"
|
|
|
- :style="line.style"
|
|
|
- />
|
|
|
- <template v-if="!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)">
|
|
|
- <ResizeHandler
|
|
|
- class="operate-resize-handler"
|
|
|
- v-for="point in resizeHandlers"
|
|
|
- :key="point.direction"
|
|
|
- :type="point.direction"
|
|
|
- :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>
|
|
|
-
|
|
|
- <AnimationIndex v-if="animationIndex !== -1" :animationIndex="animationIndex" />
|
|
|
- </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
|
-import { computed, defineComponent, ref, PropType } from 'vue'
|
|
|
+import { computed, defineComponent, PropType } from 'vue'
|
|
|
|
|
|
import { PPTImageElement } from '@/types/slides'
|
|
|
-import { OperateResizeHandler } from '@/types/edit'
|
|
|
-import useCommonOperate from '@/views/_common/_element/hooks/useCommonOperate'
|
|
|
-
|
|
|
+import { ContextmenuItem } from '@/components/Contextmenu/types'
|
|
|
import { CLIPPATHS, ClipPathTypes } from '@/configs/imageClip'
|
|
|
+import useElementShadow from '@/views/_element/hooks/useElementShadow'
|
|
|
|
|
|
-import RotateHandler from '@/views/_common/_operate/RotateHandler.vue'
|
|
|
-import ResizeHandler from '@/views/_common/_operate/ResizeHandler.vue'
|
|
|
-import BorderLine from '@/views/_common/_operate/BorderLine.vue'
|
|
|
-import AnimationIndex from '@/views/_common/_operate/AnimationIndex.vue'
|
|
|
-
|
|
|
-import ImageClip, { ClipedEmitData } from './ImageClipHandler.vue'
|
|
|
import ImageRectOutline from './ImageRectOutline.vue'
|
|
|
import ImageEllipseOutline from './ImageEllipseOutline.vue'
|
|
|
import ImagePolygonOutline from './ImagePolygonOutline.vue'
|
|
|
|
|
|
-import useElementShadow from '@/views/_common/_element/hooks/useElementShadow'
|
|
|
|
|
|
export default defineComponent({
|
|
|
name: 'editable-element-image',
|
|
|
components: {
|
|
|
- RotateHandler,
|
|
|
- ResizeHandler,
|
|
|
- BorderLine,
|
|
|
- AnimationIndex,
|
|
|
- ImageClip,
|
|
|
ImageRectOutline,
|
|
|
ImageEllipseOutline,
|
|
|
ImagePolygonOutline,
|
|
|
@@ -146,55 +83,29 @@ export default defineComponent({
|
|
|
type: Object as PropType<PPTImageElement>,
|
|
|
required: true,
|
|
|
},
|
|
|
- canvasScale: {
|
|
|
- type: Number,
|
|
|
- required: true,
|
|
|
- },
|
|
|
- isSelected: {
|
|
|
- type: Boolean,
|
|
|
- required: true,
|
|
|
- },
|
|
|
- isActive: {
|
|
|
- type: Boolean,
|
|
|
- required: true,
|
|
|
- },
|
|
|
- isActiveGroupElement: {
|
|
|
- type: Boolean,
|
|
|
- required: true,
|
|
|
- },
|
|
|
- isMultiSelect: {
|
|
|
- type: Boolean,
|
|
|
- required: true,
|
|
|
- },
|
|
|
- animationIndex: {
|
|
|
- type: Number,
|
|
|
- required: true,
|
|
|
- },
|
|
|
selectElement: {
|
|
|
type: Function as PropType<(e: MouseEvent, element: PPTImageElement, canMove?: boolean) => void>,
|
|
|
required: true,
|
|
|
},
|
|
|
- rotateElement: {
|
|
|
- type: Function as PropType<(element: PPTImageElement) => void>,
|
|
|
- required: true,
|
|
|
- },
|
|
|
- scaleElement: {
|
|
|
- type: Function as PropType<(e: MouseEvent, element: PPTImageElement, command: OperateResizeHandler) => void>,
|
|
|
- required: true,
|
|
|
- },
|
|
|
contextmenus: {
|
|
|
- type: Function,
|
|
|
+ type: Function as PropType<() => ContextmenuItem[]>,
|
|
|
},
|
|
|
},
|
|
|
setup(props) {
|
|
|
- const clipingImageElId = ref('')
|
|
|
-
|
|
|
- const scaleWidth = computed(() => props.elementInfo.width * props.canvasScale)
|
|
|
- const scaleHeight = computed(() => props.elementInfo.height * props.canvasScale)
|
|
|
+ const shadow = computed(() => props.elementInfo.shadow)
|
|
|
+ const { shadowStyle } = useElementShadow(shadow)
|
|
|
|
|
|
- const { resizeHandlers, borderLines } = useCommonOperate(scaleWidth, scaleHeight)
|
|
|
+ const handleSelectElement = (e: MouseEvent) => {
|
|
|
+ if(props.elementInfo.lock) return
|
|
|
+ e.stopPropagation()
|
|
|
+ props.selectElement(e, props.elementInfo)
|
|
|
+ }
|
|
|
+ const clipShape = computed(() => {
|
|
|
+ if(!props.elementInfo || !props.elementInfo.clip) return CLIPPATHS.rect
|
|
|
+ const shape = props.elementInfo.clip.shape || ClipPathTypes.RECT
|
|
|
|
|
|
- const isCliping = computed(() => clipingImageElId.value === props.elementInfo.id)
|
|
|
+ return CLIPPATHS[shape]
|
|
|
+ })
|
|
|
|
|
|
const imgPosition = computed(() => {
|
|
|
if(!props.elementInfo || !props.elementInfo.clip) {
|
|
|
@@ -221,13 +132,6 @@ export default defineComponent({
|
|
|
}
|
|
|
})
|
|
|
|
|
|
- const clipShape = computed(() => {
|
|
|
- if(!props.elementInfo || !props.elementInfo.clip) return CLIPPATHS.rect
|
|
|
- const shape = props.elementInfo.clip.shape || ClipPathTypes.RECT
|
|
|
-
|
|
|
- return CLIPPATHS[shape]
|
|
|
- })
|
|
|
-
|
|
|
const filter = computed(() => {
|
|
|
if(!props.elementInfo.filters) return ''
|
|
|
let filter = ''
|
|
|
@@ -246,45 +150,13 @@ export default defineComponent({
|
|
|
return ''
|
|
|
})
|
|
|
|
|
|
- const shadow = computed(() => props.elementInfo.shadow)
|
|
|
- const { shadowStyle } = useElementShadow(shadow)
|
|
|
-
|
|
|
- const handleSelectElement = (e: MouseEvent) => {
|
|
|
- if(isCliping.value || props.elementInfo.lock) return
|
|
|
- e.stopPropagation()
|
|
|
- props.selectElement(e, props.elementInfo)
|
|
|
- }
|
|
|
-
|
|
|
- const clip = (data: ClipedEmitData) => {
|
|
|
- clipingImageElId.value = ''
|
|
|
-
|
|
|
- if(!data) return
|
|
|
-
|
|
|
- const { range, position } = data
|
|
|
- const originClip = props.elementInfo.clip || {}
|
|
|
-
|
|
|
- const _props = {
|
|
|
- clip: { ...originClip, range },
|
|
|
- left: props.elementInfo.left + position.left,
|
|
|
- top: props.elementInfo.top + position.top,
|
|
|
- width: props.elementInfo.width + position.width,
|
|
|
- height: props.elementInfo.height + position.height,
|
|
|
- }
|
|
|
- console.log(_props)
|
|
|
- }
|
|
|
-
|
|
|
return {
|
|
|
- scaleWidth,
|
|
|
- isCliping,
|
|
|
- imgPosition,
|
|
|
+ shadowStyle,
|
|
|
+ handleSelectElement,
|
|
|
clipShape,
|
|
|
- resizeHandlers,
|
|
|
- borderLines,
|
|
|
+ imgPosition,
|
|
|
filter,
|
|
|
flip,
|
|
|
- shadowStyle,
|
|
|
- handleSelectElement,
|
|
|
- clip,
|
|
|
}
|
|
|
},
|
|
|
})
|
|
|
@@ -311,35 +183,8 @@ export default defineComponent({
|
|
|
overflow: hidden;
|
|
|
position: relative;
|
|
|
}
|
|
|
-
|
|
|
img {
|
|
|
position: absolute;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-.operate {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- z-index: 100;
|
|
|
- user-select: none;
|
|
|
-
|
|
|
- &.selected {
|
|
|
- .operate-border-line,
|
|
|
- .operate-resize-handler,
|
|
|
- .operate-rotate-handler {
|
|
|
- display: block;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &.multi-select:not(.selected) .operate-border-line {
|
|
|
- border-color: rgba($color: $themeColor, $alpha: .3);
|
|
|
- }
|
|
|
-
|
|
|
- .operate-border-line,
|
|
|
- .operate-resize-handler,
|
|
|
- .operate-rotate-handler {
|
|
|
- display: none;
|
|
|
- }
|
|
|
-}
|
|
|
</style>
|