Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
T
text2video-frontend
Project
Project
Details
Activity
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
周成波
text2video-frontend
Commits
bc180f71
Commit
bc180f71
authored
Nov 04, 2024
by
朱国瑞
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
裁剪组件支持裁剪图片
parent
3aa0bb5e
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
157 additions
and
59 deletions
+157
-59
VideoCrop.vue
src/components/VideoCrop.vue
+95
-14
utils.ts
src/utils/utils.ts
+15
-0
gen_digit_human_video.vue
src/views/home/gen_digit_human_video.vue
+1
-1
lib.wm.api.d.ts
typings/types/wm/lib.wm.api.d.ts
+46
-44
No files found.
src/components/VideoCrop.vue
View file @
bc180f71
...
...
@@ -21,22 +21,31 @@ const props = defineProps({
})
watch
(
()
=>
[
props
.
cropArea
,
props
.
visible
],
()
=>
[
props
.
cropArea
,
props
.
visible
,
props
.
url
],
(
newVal
,
oldVal
)
=>
{
console
.
log
(
'cropArea'
,
newVal
[
0
])
if
(
!
props
.
visible
)
{
showCropBox
.
value
=
false
// handleInitCropArea()
}
if
(
props
.
url
)
{
// 判断URL是视频还是图片
const
type
=
utils
.
getFileType
(
props
.
url
)
sourceMaterialType
.
value
=
type
title
.
value
=
type
===
'video'
?
'裁剪视频'
:
'裁剪图片'
}
}
)
const
emit
=
defineEmits
([
'update:visible'
,
'crop'
])
const
isVisible
=
ref
(
props
.
visible
)
const
loginFormRef
=
ref
<
FormInstance
>
()
const
title
=
ref
(
'裁剪视频'
)
const
sourceMaterialType
=
ref
<
Wm
.
SourceMaterialType
>
(
'video'
)
const
isMobile
=
ref
(
utils
.
checkIsMobile
())
const
cropBoxRef
=
ref
<
any
>
()
const
backgroundVideoRef
=
ref
<
HTMLVideoElement
>
()
const
backgroundImageRef
=
ref
<
HTMLImageElement
>
()
const
croppedCanvasRef
=
ref
<
HTMLCanvasElement
>
()
const
rectData
=
ref
({
left
:
0
,
...
...
@@ -63,13 +72,31 @@ const onCancel = () => {
console
.
log
(
'cancel'
)
handleClose
()
}
const
getSourceMaterialInfo
=
()
=>
{
if
(
sourceMaterialType
.
value
===
'video'
)
{
const
video
=
backgroundVideoRef
.
value
return
{
width
:
video
?.
videoWidth
||
0
,
height
:
video
?.
videoHeight
||
0
,
clientWidth
:
video
?.
clientWidth
||
0
,
clientHeight
:
video
?.
clientHeight
||
0
}
}
else
{
const
image
=
backgroundImageRef
.
value
return
{
width
:
image
?.
naturalWidth
||
0
,
height
:
image
?.
naturalHeight
||
0
,
clientWidth
:
image
?.
clientWidth
||
0
,
clientHeight
:
image
?.
clientHeight
||
0
}
}
}
const
onConfirm
=
async
()
=>
{
const
video
=
backgroundVideoRef
.
value
const
sourceMaterialInfo
=
getSourceMaterialInfo
()
// 计算裁剪框在视频中的位置
const
scaleX
=
video
!
.
videoWidth
/
vide
o
!
.
clientWidth
const
scaleY
=
video
!
.
videoHeight
/
vide
o
!
.
clientHeight
const
scaleX
=
sourceMaterialInfo
!
.
width
/
sourceMaterialInf
o
!
.
clientWidth
const
scaleY
=
sourceMaterialInfo
!
.
height
/
sourceMaterialInf
o
!
.
clientHeight
const
cropData
=
{
x
:
Math
.
round
(
rectData
.
value
.
left
*
scaleX
),
y
:
Math
.
round
(
rectData
.
value
.
top
*
scaleY
),
...
...
@@ -86,17 +113,17 @@ const onConfirm = async () => {
if
(
cropData
.
y
<
0
)
{
cropData
.
y
=
0
}
if
(
cropData
.
width
>
video
!
.
videoW
idth
)
{
cropData
.
width
=
video
!
.
videoW
idth
if
(
cropData
.
width
>
sourceMaterialInfo
!
.
w
idth
)
{
cropData
.
width
=
sourceMaterialInfo
!
.
w
idth
}
if
(
cropData
.
x
+
cropData
.
width
>
video
!
.
videoW
idth
)
{
cropData
.
width
=
video
!
.
videoW
idth
-
cropData
.
x
if
(
cropData
.
x
+
cropData
.
width
>
sourceMaterialInfo
!
.
w
idth
)
{
cropData
.
width
=
sourceMaterialInfo
!
.
w
idth
-
cropData
.
x
}
if
(
cropData
.
height
>
video
!
.
videoH
eight
)
{
cropData
.
height
=
video
!
.
videoH
eight
if
(
cropData
.
height
>
sourceMaterialInfo
!
.
h
eight
)
{
cropData
.
height
=
sourceMaterialInfo
!
.
h
eight
}
if
(
cropData
.
y
+
cropData
.
height
>
video
!
.
videoH
eight
)
{
cropData
.
height
=
video
!
.
videoH
eight
-
cropData
.
y
if
(
cropData
.
y
+
cropData
.
height
>
sourceMaterialInfo
!
.
h
eight
)
{
cropData
.
height
=
sourceMaterialInfo
!
.
h
eight
-
cropData
.
y
}
console
.
log
(
rectData
.
value
,
scaleX
,
scaleY
)
...
...
@@ -223,6 +250,46 @@ const handleInitCropArea = () => {
}
}
}
const
onImageLoaded
=
(
val
:
any
)
=>
{
console
.
log
(
'onImageLoaded'
,
val
)
const
img
=
val
.
target
const
imageWidth
=
img
.
naturalWidth
const
imageHeight
=
img
.
naturalHeight
cropPreviewBox
.
value
=
{
width
:
img
.
width
,
height
:
img
.
height
}
showCropBox
.
value
=
true
const
cropArea
:
any
=
toRaw
(
props
.
cropArea
)
if
(
cropArea
.
length
>
0
)
{
const
scaleX
=
cropPreviewBox
.
value
.
width
/
imageWidth
const
scaleY
=
cropPreviewBox
.
value
.
height
/
imageHeight
console
.
log
(
'cropArea'
,
cropArea
,
scaleX
,
scaleY
)
const
left
=
Math
.
round
(
cropArea
[
0
][
0
]
*
scaleX
)
const
top
=
Math
.
round
(
cropArea
[
0
][
1
]
*
scaleY
)
const
width
=
Math
.
round
((
cropArea
[
1
][
0
]
-
cropArea
[
0
][
0
])
*
scaleX
)
const
height
=
Math
.
round
((
cropArea
[
1
][
1
]
-
cropArea
[
0
][
1
])
*
scaleY
)
console
.
log
(
'init cropArea'
,
left
,
top
,
width
,
height
)
rectData
.
value
=
{
left
,
top
,
width
,
height
}
}
else
{
// 全部显示
rectData
.
value
=
{
left
:
0
,
top
:
0
,
width
:
imageWidth
,
height
:
imageHeight
}
}
}
</
script
>
<
template
>
<el-dialog
...
...
@@ -249,8 +316,15 @@ const handleInitCropArea = () => {
playsinline
class=
"background-video"
@
loadeddata=
"onVideoLoaded"
v-if=
"isVisible"
v-if=
"isVisible
&& sourceMaterialType === 'video'
"
></video>
<img
ref=
"backgroundImageRef"
:src=
"url"
class=
"background-image"
@
load=
"onImageLoaded"
v-if=
"isVisible && sourceMaterialType === 'image'"
/>
<VueDragResize
ref=
"cropBoxRef"
:w=
"rectData.width"
...
...
@@ -300,6 +374,13 @@ const handleInitCropArea = () => {
object-fit
:
cover
;
}
.background-image
{
width
:
100%
;
height
:
100%
;
object-fit
:
cover
;
-webkit-user-drag
:
none
;
/* 禁止图片拖动 */
}
.crop-box
{
border-color
:
var
(
--
el-color-primary-dark-2
);
position
:
absolute
;
...
...
src/utils/utils.ts
View file @
bc180f71
...
...
@@ -143,4 +143,19 @@ export default class utils {
return
false
}
}
static
getFileType
=
(
url
:
string
)
=>
{
const
videoExtensions
=
[
'mp4'
,
'avi'
,
'mov'
,
'wmv'
,
'flv'
,
'mkv'
];
const
imageExtensions
=
[
'jpg'
,
'jpeg'
,
'png'
,
'gif'
,
'bmp'
,
'webp'
];
const
extension
=
(
url
.
split
(
'.'
).
pop
()
||
''
).
toLowerCase
();
if
(
videoExtensions
.
includes
(
extension
))
{
return
'video'
;
}
else
if
(
imageExtensions
.
includes
(
extension
))
{
return
'image'
;
}
else
{
return
'unknown'
;
}
}
}
src/views/home/gen_digit_human_video.vue
View file @
bc180f71
...
...
@@ -424,7 +424,7 @@ const onDownloadVideo = async () => {
size=
"small"
@
click
.
stop=
"showCropVideoDialog('show_image_or_video')"
>
裁剪视频画面
裁剪
图片或
视频画面
</el-button>
<
template
#
tip
>
<div
class=
"el-upload__tip"
style=
"color: #0000ff; background-color: #e6f7ff"
>
...
...
typings/types/wm/lib.wm.api.d.ts
View file @
bc180f71
declare
namespace
Wm
{
interface
ImgSize
{
"width"
:
string
,
"height"
:
string
,
width
:
string
height
:
string
}
interface
PromptHistory
{
"role"
:
string
,
"content"
:
string
,
role
:
string
content
:
string
}
interface
PicText
{
"text"
:
string
,
"color"
:
string
,
"bg_color"
:
string
,
"font_size"
:
number
,
"position"
:
number
,
text
:
string
color
:
string
bg_color
:
string
font_size
:
number
position
:
number
}
interface
ScriptsItem
{
"编号"
:
string
,
"场景描述"
:
string
,
"场景关键词"
:
string
,
"场景关键词英文"
:
string
,
"角色"
:
string
,
"角色关键词"
:
string
,
"角色关键词英文"
:
string
,
"画面描述词"
:
string
,
"本镜配图"
:
string
,
"local_image_path"
:
string
,
"info"
:
string
,
"roles"
:
String
[],
"info2"
:
string
,
编号
:
string
场景描述
:
string
场景关键词
:
string
场景关键词英文
:
string
角色
:
string
角色关键词
:
string
角色关键词英文
:
string
画面描述词
:
string
本镜配图
:
string
local_image_path
:
string
info
:
string
roles
:
String
[]
info2
:
string
}
interface
GenVideo
{
"task_id"
:
string
,
"task_info"
:
GenVideoItem
[],
task_id
:
string
task_info
:
GenVideoItem
[]
}
interface
GenVideoItem
{
"idx"
:
string
,
"text"
:
string
,
"img_path"
:
string
,
idx
:
string
text
:
string
img_path
:
string
}
interface
RolesItem
{
"角色"
:
string
,
"角色关键词"
:
string
,
"角色关键词英文"
:
string
,
"属性"
:
string
,
角色
:
string
角色关键词
:
string
角色关键词英文
:
string
属性
:
string
}
interface
UploadResult
{
"code"
:
int
,
"data"
:
[
{
"id"
:
int
,
"key"
:
string
,
"path"
:
string
,
"url"
:
string
}
]
,
"message"
:
string
code
:
int
data
:
[
{
id
:
int
key
:
string
path
:
string
url
:
string
}
]
message
:
string
}
interface
Coordinate
{
"x"
:
int
,
"y"
:
int
,
x
:
int
y
:
int
}
interface
LoginParams
{
...
...
@@ -83,4 +83,6 @@ declare namespace Wm {
password
:
string
username
:
string
}
type
SourceMaterialType
=
'video'
|
'image'
|
'unknown'
}
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