Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
pptist
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
viitto
pptist
Commits
683c079d
Commit
683c079d
authored
Jun 19, 2024
by
zhengke
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化字体放大缩小
parent
af5295e4
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
398 additions
and
4 deletions
+398
-4
edit.ts
src/types/edit.ts
+11
-0
TextElementOperate.vue
src/views/Editor/Canvas/Operate/TextElementOperate.vue
+15
-2
index.vue
src/views/Editor/Canvas/Operate/index.vue
+3
-1
useCommonOperate.ts
src/views/Editor/Canvas/hooks/useCommonOperate.ts
+13
-0
useScaleElement.ts
src/views/Editor/Canvas/hooks/useScaleElement.ts
+354
-0
index.vue
src/views/Editor/Canvas/index.vue
+2
-1
No files found.
src/types/edit.ts
View file @
683c079d
...
...
@@ -26,6 +26,17 @@ export const enum OperateBorderLines {
R
=
'right'
,
}
export
const
enum
OperateTesizeHandlers
{
LEFT_TOP
=
'left-top'
,
// TOP = 'top',
RIGHT_TOP
=
'right-top'
,
// LEFT = 'left',
// RIGHT = 'right',
LEFT_BOTTOM
=
'left-bottom'
,
// BOTTOM = 'bottom',
RIGHT_BOTTOM
=
'right-bottom'
,
}
export
const
enum
OperateResizeHandlers
{
LEFT_TOP
=
'left-top'
,
TOP
=
'top'
,
...
...
src/views/Editor/Canvas/Operate/TextElementOperate.vue
View file @
683c079d
...
...
@@ -22,6 +22,15 @@
:style=
"
{ left: scaleWidth / 2 + 'px' }"
@mousedown.stop="$event => rotateElement($event, elementInfo)"
/>
<TextsizeHandler
class=
"operate-resize-handler"
v-for=
"point in tesizeHandlers"
:key=
"point.direction"
:type=
"point.direction"
:rotate=
"elementInfo.rotate"
:style=
"point.style"
@
mousedown
.
stop=
"$event => scaleElement($event, elementInfo, point.direction)"
/>
</
template
>
</div>
</template>
...
...
@@ -37,11 +46,12 @@ import { computed } from 'vue'
import
{
storeToRefs
}
from
'pinia'
import
{
useMainStore
}
from
'@/store'
import
type
{
PPTTextElement
}
from
'@/types/slides'
import
type
{
OperateResizeHandlers
}
from
'@/types/edit'
import
type
{
OperateResizeHandlers
,
OperateTesizeHandlers
}
from
'@/types/edit'
import
useCommonOperate
from
'../hooks/useCommonOperate'
import
RotateHandler
from
'./RotateHandler.vue'
import
ResizeHandler
from
'./ResizeHandler.vue'
import
TextsizeHandler
from
'./TextsizeHandler.vue'
import
BorderLine
from
'./BorderLine.vue'
const
props
=
defineProps
<
{
...
...
@@ -49,6 +59,7 @@ const props = defineProps<{
handlerVisible
:
boolean
rotateElement
:
(
e
:
MouseEvent
,
element
:
PPTTextElement
)
=>
void
scaleElement
:
(
e
:
MouseEvent
,
element
:
PPTTextElement
,
command
:
OperateResizeHandlers
)
=>
void
scaleText
:
(
e
:
MouseEvent
,
element
:
PPTTextElement
,
command
:
OperateTesizeHandlers
)
=>
void
}
>
()
const
{
canvasScale
}
=
storeToRefs
(
useMainStore
())
...
...
@@ -56,6 +67,8 @@ const { canvasScale } = storeToRefs(useMainStore())
const
scaleWidth
=
computed
(()
=>
props
.
elementInfo
.
width
*
canvasScale
.
value
)
const
scaleHeight
=
computed
(()
=>
props
.
elementInfo
.
height
*
canvasScale
.
value
)
const
{
textElementResizeHandlers
,
verticalTextElementResizeHandlers
,
borderLines
}
=
useCommonOperate
(
scaleWidth
,
scaleHeight
)
const
{
textElementResizeHandlers
,
verticalTextElementResizeHandlers
,
borderLines
,
textElementTesizeHandlers
}
=
useCommonOperate
(
scaleWidth
,
scaleHeight
)
const
resizeHandlers
=
computed
(()
=>
props
.
elementInfo
.
vertical
?
verticalTextElementResizeHandlers
.
value
:
textElementResizeHandlers
.
value
)
const
tesizeHandlers
=
computed
(()
=>
props
.
elementInfo
.
vertical
?
textElementTesizeHandlers
.
value
:
textElementTesizeHandlers
.
value
)
console
.
log
(
textElementTesizeHandlers
.
value
,
'---------'
)
</
script
>
\ No newline at end of file
src/views/Editor/Canvas/Operate/index.vue
View file @
683c079d
...
...
@@ -16,6 +16,7 @@
:handlerVisible=
"!elementInfo.lock && (isActiveGroupElement || !isMultiSelect)"
:rotateElement=
"rotateElement"
:scaleElement=
"scaleElement"
:scaleText=
"scaleText"
:dragLineElement=
"dragLineElement"
:moveShapeKeypoint=
"moveShapeKeypoint"
></component>
...
...
@@ -50,7 +51,7 @@ import {
type
PPTShapeElement
,
type
PPTChartElement
,
}
from
'@/types/slides'
import
type
{
OperateLineHandlers
,
OperateResizeHandlers
}
from
'@/types/edit'
import
type
{
OperateLineHandlers
,
OperateResizeHandlers
,
OperateTesizeHandlers
}
from
'@/types/edit'
import
ImageElementOperate
from
'./ImageElementOperate.vue'
import
TextElementOperate
from
'./TextElementOperate.vue'
...
...
@@ -68,6 +69,7 @@ const props = defineProps<{
isMultiSelect
:
boolean
rotateElement
:
(
e
:
MouseEvent
,
element
:
Exclude
<
PPTElement
,
PPTChartElement
|
PPTLineElement
|
PPTVideoElement
|
PPTAudioElement
>
)
=>
void
scaleElement
:
(
e
:
MouseEvent
,
element
:
Exclude
<
PPTElement
,
PPTLineElement
>
,
command
:
OperateResizeHandlers
)
=>
void
scaleText
:
(
e
:
MouseEvent
,
element
:
Exclude
<
PPTElement
,
PPTLineElement
>
,
command
:
OperateTesizeHandlers
)
=>
void
dragLineElement
:
(
e
:
MouseEvent
,
element
:
PPTLineElement
,
command
:
OperateLineHandlers
)
=>
void
moveShapeKeypoint
:
(
e
:
MouseEvent
,
element
:
PPTShapeElement
)
=>
void
openLinkDialog
:
()
=>
void
...
...
src/views/Editor/Canvas/hooks/useCommonOperate.ts
View file @
683c079d
...
...
@@ -23,6 +23,18 @@ export default (width: Ref<number>, height: Ref<number>) => {
{
direction
:
OperateResizeHandlers
.
RIGHT
,
style
:
{
left
:
width
.
value
+
'px'
,
top
:
height
.
value
/
2
+
'px'
}
},
]
})
const
textElementTesizeHandlers
=
computed
(()
=>
{
return
[
{
direction
:
OperateResizeHandlers
.
LEFT_TOP
,
style
:
{}
},
// { direction: OperateResizeHandlers.TOP, style: {left: width.value / 2 + 'px'} },
{
direction
:
OperateResizeHandlers
.
RIGHT_TOP
,
style
:
{
left
:
width
.
value
+
'px'
}
},
// { direction: OperateResizeHandlers.LEFT, style: {top: height.value / 2 + 'px'} },
// { direction: OperateResizeHandlers.RIGHT, style: {left: width.value + 'px', top: height.value / 2 + 'px'} },
{
direction
:
OperateResizeHandlers
.
LEFT_BOTTOM
,
style
:
{
top
:
height
.
value
+
'px'
}
},
// { direction: OperateResizeHandlers.BOTTOM, style: {left: width.value / 2 + 'px', top: height.value + 'px'} },
{
direction
:
OperateResizeHandlers
.
RIGHT_BOTTOM
,
style
:
{
left
:
width
.
value
+
'px'
,
top
:
height
.
value
+
'px'
}
},
]
})
const
verticalTextElementResizeHandlers
=
computed
(()
=>
{
return
[
{
direction
:
OperateResizeHandlers
.
TOP
,
style
:
{
left
:
width
.
value
/
2
+
'px'
}
},
...
...
@@ -45,5 +57,6 @@ export default (width: Ref<number>, height: Ref<number>) => {
textElementResizeHandlers
,
verticalTextElementResizeHandlers
,
borderLines
,
textElementTesizeHandlers
,
}
}
\ No newline at end of file
src/views/Editor/Canvas/hooks/useScaleElement.ts
View file @
683c079d
...
...
@@ -106,6 +106,359 @@ export default (
const
{
addHistorySnapshot
}
=
useHistorySnapshot
()
// 缩放元素
const
scaleText
=
(
e
:
MouseEvent
|
TouchEvent
,
element
:
Exclude
<
PPTElement
,
PPTLineElement
>
,
command
:
OperateResizeHandlers
)
=>
{
const
isTouchEvent
=
!
(
e
instanceof
MouseEvent
)
if
(
isTouchEvent
&&
(
!
e
.
changedTouches
||
!
e
.
changedTouches
[
0
]))
return
let
isMouseDown
=
true
mainStore
.
setScalingState
(
true
)
const
elOriginLeft
=
element
.
left
const
elOriginTop
=
element
.
top
const
elOriginWidth
=
element
.
width
const
elOriginHeight
=
element
.
height
const
originTableCellMinHeight
=
element
.
type
===
'table'
?
element
.
cellMinHeight
:
0
const
elRotate
=
(
'rotate'
in
element
&&
element
.
rotate
)
?
element
.
rotate
:
0
const
rotateRadian
=
Math
.
PI
*
elRotate
/
180
const
fixedRatio
=
ctrlOrShiftKeyActive
.
value
||
(
'fixedRatio'
in
element
&&
element
.
fixedRatio
)
const
aspectRatio
=
elOriginWidth
/
elOriginHeight
const
startPageX
=
isTouchEvent
?
e
.
changedTouches
[
0
].
pageX
:
e
.
pageX
const
startPageY
=
isTouchEvent
?
e
.
changedTouches
[
0
].
pageY
:
e
.
pageY
// 元素最小缩放限制
const
minSize
=
MIN_SIZE
[
element
.
type
]
||
20
const
getSizeWithinRange
=
(
size
:
number
)
=>
size
<
minSize
?
minSize
:
size
let
points
:
ReturnType
<
typeof
getRotateElementPoints
>
let
baseLeft
=
0
let
baseTop
=
0
let
horizontalLines
:
AlignLine
[]
=
[]
let
verticalLines
:
AlignLine
[]
=
[]
// 旋转后的元素进行缩放时,引入基点的概念,以当前操作的缩放点相对的点为基点
// 例如拖动右下角缩放时,左上角为基点,需要保持左上角不变然后修改其他的点的位置来达到所放的效果
if
(
'rotate'
in
element
&&
element
.
rotate
)
{
const
{
left
,
top
,
width
,
height
}
=
element
points
=
getRotateElementPoints
({
left
,
top
,
width
,
height
},
elRotate
)
const
oppositePoint
=
getOppositePoint
(
command
,
points
)
baseLeft
=
oppositePoint
.
left
baseTop
=
oppositePoint
.
top
}
// 未旋转的元素具有缩放时的对齐吸附功能,在此处收集对齐对齐吸附线
// 包括页面内除目标元素外的其他元素在画布中的各个可吸附对齐位置:上下左右四边
// 其中线条和被旋转过的元素不参与吸附对齐
else
{
const
edgeWidth
=
VIEWPORT_SIZE
.
Value
const
edgeHeight
=
VIEWPORT_SIZE
.
Value
*
viewportRatio
.
value
const
isActiveGroupElement
=
element
.
id
===
activeGroupElementId
.
value
for
(
const
el
of
elementList
.
value
)
{
if
(
'rotate'
in
el
&&
el
.
rotate
)
continue
if
(
el
.
type
===
'line'
)
continue
if
(
isActiveGroupElement
&&
el
.
id
===
element
.
id
)
continue
if
(
!
isActiveGroupElement
&&
activeElementIdList
.
value
.
includes
(
el
.
id
))
continue
const
left
=
el
.
left
const
top
=
el
.
top
const
width
=
el
.
width
const
height
=
el
.
height
const
right
=
left
+
width
const
bottom
=
top
+
height
const
topLine
:
AlignLine
=
{
value
:
top
,
range
:
[
left
,
right
]
}
const
bottomLine
:
AlignLine
=
{
value
:
bottom
,
range
:
[
left
,
right
]
}
const
leftLine
:
AlignLine
=
{
value
:
left
,
range
:
[
top
,
bottom
]
}
const
rightLine
:
AlignLine
=
{
value
:
right
,
range
:
[
top
,
bottom
]
}
horizontalLines
.
push
(
topLine
,
bottomLine
)
verticalLines
.
push
(
leftLine
,
rightLine
)
}
// 画布可视区域的四个边界、水平中心、垂直中心
const
edgeTopLine
:
AlignLine
=
{
value
:
0
,
range
:
[
0
,
edgeWidth
]
}
const
edgeBottomLine
:
AlignLine
=
{
value
:
edgeHeight
,
range
:
[
0
,
edgeWidth
]
}
const
edgeHorizontalCenterLine
:
AlignLine
=
{
value
:
edgeHeight
/
2
,
range
:
[
0
,
edgeWidth
]
}
const
edgeLeftLine
:
AlignLine
=
{
value
:
0
,
range
:
[
0
,
edgeHeight
]
}
const
edgeRightLine
:
AlignLine
=
{
value
:
edgeWidth
,
range
:
[
0
,
edgeHeight
]
}
const
edgeVerticalCenterLine
:
AlignLine
=
{
value
:
edgeWidth
/
2
,
range
:
[
0
,
edgeHeight
]
}
horizontalLines
.
push
(
edgeTopLine
,
edgeBottomLine
,
edgeHorizontalCenterLine
)
verticalLines
.
push
(
edgeLeftLine
,
edgeRightLine
,
edgeVerticalCenterLine
)
horizontalLines
=
uniqAlignLines
(
horizontalLines
)
verticalLines
=
uniqAlignLines
(
verticalLines
)
}
// 对齐吸附方法
// 将收集到的对齐吸附线与计算的目标元素当前的位置大小相关数据做对比,差值小于设定的值时执行自动缩放校正
// 水平和垂直两个方向需要分开计算
const
alignedAdsorption
=
(
currentX
:
number
|
null
,
currentY
:
number
|
null
)
=>
{
const
sorptionRange
=
5
const
_alignmentLines
:
AlignmentLineProps
[]
=
[]
let
isVerticalAdsorbed
=
false
let
isHorizontalAdsorbed
=
false
const
correctionVal
=
{
offsetX
:
0
,
offsetY
:
0
}
if
(
currentY
||
currentY
===
0
)
{
for
(
let
i
=
0
;
i
<
horizontalLines
.
length
;
i
++
)
{
const
{
value
,
range
}
=
horizontalLines
[
i
]
const
min
=
Math
.
min
(...
range
,
currentX
||
0
)
const
max
=
Math
.
max
(...
range
,
currentX
||
0
)
if
(
Math
.
abs
(
currentY
-
value
)
<
sorptionRange
&&
!
isHorizontalAdsorbed
)
{
correctionVal
.
offsetY
=
currentY
-
value
isHorizontalAdsorbed
=
true
_alignmentLines
.
push
({
type
:
'horizontal'
,
axis
:
{
x
:
min
-
50
,
y
:
value
},
length
:
max
-
min
+
100
})
}
}
}
if
(
currentX
||
currentX
===
0
)
{
for
(
let
i
=
0
;
i
<
verticalLines
.
length
;
i
++
)
{
const
{
value
,
range
}
=
verticalLines
[
i
]
const
min
=
Math
.
min
(...
range
,
(
currentY
||
0
))
const
max
=
Math
.
max
(...
range
,
(
currentY
||
0
))
if
(
Math
.
abs
(
currentX
-
value
)
<
sorptionRange
&&
!
isVerticalAdsorbed
)
{
correctionVal
.
offsetX
=
currentX
-
value
isVerticalAdsorbed
=
true
_alignmentLines
.
push
({
type
:
'vertical'
,
axis
:
{
x
:
value
,
y
:
min
-
50
},
length
:
max
-
min
+
100
})
}
}
}
alignmentLines
.
value
=
_alignmentLines
return
correctionVal
}
const
handleMousemove
=
(
e
:
MouseEvent
|
TouchEvent
)
=>
{
if
(
!
isMouseDown
)
return
const
currentPageX
=
e
instanceof
MouseEvent
?
e
.
pageX
:
e
.
changedTouches
[
0
].
pageX
const
currentPageY
=
e
instanceof
MouseEvent
?
e
.
pageY
:
e
.
changedTouches
[
0
].
pageY
const
x
=
currentPageX
-
startPageX
const
y
=
currentPageY
-
startPageY
let
width
=
elOriginWidth
let
height
=
elOriginHeight
let
left
=
elOriginLeft
let
top
=
elOriginTop
// 元素被旋转的情况下,需要根据元素旋转的角度,重新计算需要缩放的距离(鼠标按下后移动的距离)
if
(
elRotate
)
{
const
revisedX
=
(
Math
.
cos
(
rotateRadian
)
*
x
+
Math
.
sin
(
rotateRadian
)
*
y
)
/
canvasScale
.
value
let
revisedY
=
(
Math
.
cos
(
rotateRadian
)
*
y
-
Math
.
sin
(
rotateRadian
)
*
x
)
/
canvasScale
.
value
// 锁定宽高比例(仅四个角可能触发,四条边不会触发)
// 以水平方向上缩放的距离为基础,计算垂直方向上的缩放距离,保持二者具有相同的缩放比例
if
(
fixedRatio
)
{
if
(
command
===
OperateResizeHandlers
.
RIGHT_BOTTOM
||
command
===
OperateResizeHandlers
.
LEFT_TOP
)
revisedY
=
revisedX
/
aspectRatio
if
(
command
===
OperateResizeHandlers
.
LEFT_BOTTOM
||
command
===
OperateResizeHandlers
.
RIGHT_TOP
)
revisedY
=
-
revisedX
/
aspectRatio
}
// 根据不同的操作点分别计算元素缩放后的大小和位置
// 需要注意:
// 此处计算的位置需要在后面重新进行校正,因为旋转后再缩放事实上会改变元素基点的位置(虽然视觉上基点保持不动,但这是【旋转】+【移动】共同作用的结果)
// 但此处计算的大小不需要重新校正,因为前面已经重新计算需要缩放的距离,相当于大小已经经过了校正
if
(
command
===
OperateResizeHandlers
.
RIGHT_BOTTOM
)
{
width
=
getSizeWithinRange
(
elOriginWidth
+
revisedX
)
height
=
getSizeWithinRange
(
elOriginHeight
+
revisedY
)
}
else
if
(
command
===
OperateResizeHandlers
.
LEFT_BOTTOM
)
{
width
=
getSizeWithinRange
(
elOriginWidth
-
revisedX
)
height
=
getSizeWithinRange
(
elOriginHeight
+
revisedY
)
left
=
elOriginLeft
-
(
width
-
elOriginWidth
)
}
else
if
(
command
===
OperateResizeHandlers
.
LEFT_TOP
)
{
width
=
getSizeWithinRange
(
elOriginWidth
-
revisedX
)
height
=
getSizeWithinRange
(
elOriginHeight
-
revisedY
)
left
=
elOriginLeft
-
(
width
-
elOriginWidth
)
top
=
elOriginTop
-
(
height
-
elOriginHeight
)
}
else
if
(
command
===
OperateResizeHandlers
.
RIGHT_TOP
)
{
width
=
getSizeWithinRange
(
elOriginWidth
+
revisedX
)
height
=
getSizeWithinRange
(
elOriginHeight
-
revisedY
)
top
=
elOriginTop
-
(
height
-
elOriginHeight
)
}
else
if
(
command
===
OperateResizeHandlers
.
TOP
)
{
height
=
getSizeWithinRange
(
elOriginHeight
-
revisedY
)
top
=
elOriginTop
-
(
height
-
elOriginHeight
)
}
else
if
(
command
===
OperateResizeHandlers
.
BOTTOM
)
{
height
=
getSizeWithinRange
(
elOriginHeight
+
revisedY
)
}
else
if
(
command
===
OperateResizeHandlers
.
LEFT
)
{
width
=
getSizeWithinRange
(
elOriginWidth
-
revisedX
)
left
=
elOriginLeft
-
(
width
-
elOriginWidth
)
}
else
if
(
command
===
OperateResizeHandlers
.
RIGHT
)
{
width
=
getSizeWithinRange
(
elOriginWidth
+
revisedX
)
}
// 获取当前元素的基点坐标,与初始状态时的基点坐标进行对比,并计算差值进行元素位置的校正
const
currentPoints
=
getRotateElementPoints
({
width
,
height
,
left
,
top
},
elRotate
)
const
currentOppositePoint
=
getOppositePoint
(
command
,
currentPoints
)
const
currentBaseLeft
=
currentOppositePoint
.
left
const
currentBaseTop
=
currentOppositePoint
.
top
const
offsetX
=
currentBaseLeft
-
baseLeft
const
offsetY
=
currentBaseTop
-
baseTop
left
=
left
-
offsetX
top
=
top
-
offsetY
}
// 元素未被旋转的情况下,正常计算新的位置大小即可,无需复杂的校正等工作
// 额外需要处理对齐吸附相关的操作
// 锁定宽高比例相关的操作同上,不再赘述
else
{
let
moveX
=
x
/
canvasScale
.
value
let
moveY
=
y
/
canvasScale
.
value
if
(
fixedRatio
)
{
if
(
command
===
OperateResizeHandlers
.
RIGHT_BOTTOM
||
command
===
OperateResizeHandlers
.
LEFT_TOP
)
moveY
=
moveX
/
aspectRatio
if
(
command
===
OperateResizeHandlers
.
LEFT_BOTTOM
||
command
===
OperateResizeHandlers
.
RIGHT_TOP
)
moveY
=
-
moveX
/
aspectRatio
}
if
(
command
===
OperateResizeHandlers
.
RIGHT_BOTTOM
)
{
const
{
offsetX
,
offsetY
}
=
alignedAdsorption
(
elOriginLeft
+
elOriginWidth
+
moveX
,
elOriginTop
+
elOriginHeight
+
moveY
)
moveX
=
moveX
-
offsetX
moveY
=
moveY
-
offsetY
if
(
fixedRatio
)
{
if
(
offsetY
)
moveX
=
moveY
*
aspectRatio
else
moveY
=
moveX
/
aspectRatio
}
width
=
getSizeWithinRange
(
elOriginWidth
+
moveX
)
height
=
getSizeWithinRange
(
elOriginHeight
+
moveY
)
}
else
if
(
command
===
OperateResizeHandlers
.
LEFT_BOTTOM
)
{
const
{
offsetX
,
offsetY
}
=
alignedAdsorption
(
elOriginLeft
+
moveX
,
elOriginTop
+
elOriginHeight
+
moveY
)
moveX
=
moveX
-
offsetX
moveY
=
moveY
-
offsetY
if
(
fixedRatio
)
{
if
(
offsetY
)
moveX
=
-
moveY
*
aspectRatio
else
moveY
=
-
moveX
/
aspectRatio
}
width
=
getSizeWithinRange
(
elOriginWidth
-
moveX
)
height
=
getSizeWithinRange
(
elOriginHeight
+
moveY
)
left
=
elOriginLeft
-
(
width
-
elOriginWidth
)
}
else
if
(
command
===
OperateResizeHandlers
.
LEFT_TOP
)
{
const
{
offsetX
,
offsetY
}
=
alignedAdsorption
(
elOriginLeft
+
moveX
,
elOriginTop
+
moveY
)
moveX
=
moveX
-
offsetX
moveY
=
moveY
-
offsetY
if
(
fixedRatio
)
{
if
(
offsetY
)
moveX
=
moveY
*
aspectRatio
else
moveY
=
moveX
/
aspectRatio
}
width
=
getSizeWithinRange
(
elOriginWidth
-
moveX
)
height
=
getSizeWithinRange
(
elOriginHeight
-
moveY
)
left
=
elOriginLeft
-
(
width
-
elOriginWidth
)
top
=
elOriginTop
-
(
height
-
elOriginHeight
)
}
else
if
(
command
===
OperateResizeHandlers
.
RIGHT_TOP
)
{
const
{
offsetX
,
offsetY
}
=
alignedAdsorption
(
elOriginLeft
+
elOriginWidth
+
moveX
,
elOriginTop
+
moveY
)
moveX
=
moveX
-
offsetX
moveY
=
moveY
-
offsetY
if
(
fixedRatio
)
{
if
(
offsetY
)
moveX
=
-
moveY
*
aspectRatio
else
moveY
=
-
moveX
/
aspectRatio
}
width
=
getSizeWithinRange
(
elOriginWidth
+
moveX
)
height
=
getSizeWithinRange
(
elOriginHeight
-
moveY
)
top
=
elOriginTop
-
(
height
-
elOriginHeight
)
}
else
if
(
command
===
OperateResizeHandlers
.
LEFT
)
{
const
{
offsetX
}
=
alignedAdsorption
(
elOriginLeft
+
moveX
,
null
)
moveX
=
moveX
-
offsetX
width
=
getSizeWithinRange
(
elOriginWidth
-
moveX
)
left
=
elOriginLeft
-
(
width
-
elOriginWidth
)
}
else
if
(
command
===
OperateResizeHandlers
.
RIGHT
)
{
const
{
offsetX
}
=
alignedAdsorption
(
elOriginLeft
+
elOriginWidth
+
moveX
,
null
)
moveX
=
moveX
-
offsetX
width
=
getSizeWithinRange
(
elOriginWidth
+
moveX
)
}
else
if
(
command
===
OperateResizeHandlers
.
TOP
)
{
const
{
offsetY
}
=
alignedAdsorption
(
null
,
elOriginTop
+
moveY
)
moveY
=
moveY
-
offsetY
height
=
getSizeWithinRange
(
elOriginHeight
-
moveY
)
top
=
elOriginTop
-
(
height
-
elOriginHeight
)
}
else
if
(
command
===
OperateResizeHandlers
.
BOTTOM
)
{
const
{
offsetY
}
=
alignedAdsorption
(
null
,
elOriginTop
+
elOriginHeight
+
moveY
)
moveY
=
moveY
-
offsetY
height
=
getSizeWithinRange
(
elOriginHeight
+
moveY
)
}
}
elementList
.
value
=
elementList
.
value
.
map
(
el
=>
{
if
(
element
.
id
!==
el
.
id
)
return
el
if
(
el
.
type
===
'shape'
&&
'pathFormula'
in
el
&&
el
.
pathFormula
)
{
const
pathFormula
=
SHAPE_PATH_FORMULAS
[
el
.
pathFormula
]
let
path
=
''
if
(
'editable'
in
pathFormula
)
path
=
pathFormula
.
formula
(
width
,
height
,
el
.
keypoint
!
)
else
path
=
pathFormula
.
formula
(
width
,
height
)
return
{
...
el
,
left
,
top
,
width
,
height
,
viewBox
:
[
width
,
height
],
path
,
}
}
if
(
el
.
type
===
'table'
)
{
let
cellMinHeight
=
originTableCellMinHeight
+
(
height
-
elOriginHeight
)
/
el
.
data
.
length
cellMinHeight
=
cellMinHeight
<
36
?
36
:
cellMinHeight
if
(
cellMinHeight
===
originTableCellMinHeight
)
return
{
...
el
,
left
,
width
}
return
{
...
el
,
left
,
top
,
width
,
height
,
cellMinHeight
:
cellMinHeight
<
36
?
36
:
cellMinHeight
,
}
}
return
{
...
el
,
left
,
top
,
width
,
height
}
})
}
const
handleMouseup
=
(
e
:
MouseEvent
|
TouchEvent
)
=>
{
isMouseDown
=
false
document
.
ontouchmove
=
null
document
.
ontouchend
=
null
document
.
onmousemove
=
null
document
.
onmouseup
=
null
alignmentLines
.
value
=
[]
const
currentPageX
=
e
instanceof
MouseEvent
?
e
.
pageX
:
e
.
changedTouches
[
0
].
pageX
const
currentPageY
=
e
instanceof
MouseEvent
?
e
.
pageY
:
e
.
changedTouches
[
0
].
pageY
if
(
startPageX
===
currentPageX
&&
startPageY
===
currentPageY
)
return
slidesStore
.
updateSlide
({
elements
:
elementList
.
value
})
mainStore
.
setScalingState
(
false
)
addHistorySnapshot
()
}
if
(
isTouchEvent
)
{
document
.
ontouchmove
=
handleMousemove
document
.
ontouchend
=
handleMouseup
}
else
{
document
.
onmousemove
=
handleMousemove
document
.
onmouseup
=
handleMouseup
}
}
// 缩放元素
const
scaleElement
=
(
e
:
MouseEvent
|
TouchEvent
,
element
:
Exclude
<
PPTElement
,
PPTLineElement
>
,
command
:
OperateResizeHandlers
)
=>
{
const
isTouchEvent
=
!
(
e
instanceof
MouseEvent
)
...
...
@@ -565,5 +918,6 @@ export default (
return
{
scaleElement
,
scaleMultiElement
,
scaleText
,
}
}
\ No newline at end of file
src/views/Editor/Canvas/index.vue
View file @
683c079d
...
...
@@ -51,6 +51,7 @@
:isMultiSelect=
"activeElementIdList.length > 1"
:rotateElement=
"rotateElement"
:scaleElement=
"scaleElement"
:scaleText=
"scaleText"
:openLinkDialog=
"openLinkDialog"
:dragLineElement=
"dragLineElement"
:moveShapeKeypoint=
"moveShapeKeypoint"
...
...
@@ -200,7 +201,7 @@ const { mouseSelection, mouseSelectionVisible, mouseSelectionQuadrant, updateMou
const
{
dragElement
}
=
useDragElement
(
elementList
,
alignmentLines
,
canvasScale
)
const
{
dragLineElement
}
=
useDragLineElement
(
elementList
)
const
{
selectElement
}
=
useSelectElement
(
elementList
,
dragElement
)
const
{
scaleElement
,
scaleMultiElement
}
=
useScaleElement
(
elementList
,
alignmentLines
,
canvasScale
)
const
{
scaleElement
,
scaleMultiElement
,
scaleText
}
=
useScaleElement
(
elementList
,
alignmentLines
,
canvasScale
)
const
{
rotateElement
}
=
useRotateElement
(
elementList
,
viewportRef
,
canvasScale
)
const
{
moveShapeKeypoint
}
=
useMoveShapeKeypoint
(
elementList
,
canvasScale
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment