1
1
<script setup lang="ts">
2
2
import movie from ' /bird.mp4'
3
3
import { fabric } from ' fabric'
4
- import { onMounted , ref } from ' vue'
4
+ import { storeToRefs } from ' pinia'
5
+ import { onMounted , ref , watch } from ' vue'
5
6
import Logo from ' ~/assets/icons/icon-github.svg'
7
+ import { usePlayerStore } from ' ~/stores/player'
8
+ import emitter from ' ~/utils/bus'
6
9
7
10
defineProps <{
8
11
msg: string
9
12
}>()
13
+ const container = ref <HTMLElement | null >(null )
14
+ let video: HTMLVideoElement
15
+ const playerStore = usePlayerStore ()
16
+ const { playStatus } = storeToRefs (playerStore )
17
+
10
18
let canvas: fabric .Canvas
11
19
let ctx: CanvasRenderingContext2D
12
- const container = ref <HTMLElement | null >(null )
20
+ let clipboard: fabric .Object | null = null
21
+
22
+ emitter .on (' element:copy' , onCopy )
23
+ emitter .on (' element:paste' , onPaste )
24
+ watch (playStatus , () => {
25
+ if (playStatus .value ) {
26
+ video .play ()
27
+ } else {
28
+ video .pause ()
29
+ }
30
+ })
13
31
14
32
function initCanvas() {
15
33
canvas = new fabric .Canvas (' canvas' , {
@@ -58,13 +76,10 @@ function drawStaticElements() {
58
76
// 绘制视频
59
77
// TODO 需要实现通过 webcodecs 进行视频解码后绘制
60
78
function drawVideo() {
61
- const video = document .createElement (' video' )
79
+ video = document .createElement (' video' )
62
80
// video.src = 'https://assets.fedtop.com/picbed/movie.mp4'
63
81
video .src = movie
64
- video .autoplay = true
65
82
video .loop = true
66
- // 不静音就无法在未点击的情况下自动播放
67
- video .muted = true
68
83
const canvasWidth = canvas .width !
69
84
const canvasHeight = canvas .height !
70
85
@@ -89,8 +104,6 @@ function drawVideo() {
89
104
canvas .add (videoElement )
90
105
canvas .setActiveObject (videoElement )
91
106
continuouslyRepaint ()
92
- // TODO 修改成外部控制
93
- video .play ()
94
107
})
95
108
}
96
109
@@ -151,6 +164,7 @@ function initControls() {
151
164
// 添加删除按钮
152
165
addDeleteButton ()
153
166
}
167
+
154
168
// editor 添加删除按钮
155
169
function addDeleteButton() {
156
170
// 有些地方也有用 fabric.Object.prototype.controls.delete
@@ -200,6 +214,45 @@ function resizePlayer() {
200
214
201
215
function canvasOnMouseDown() {}
202
216
217
+ // 复制元素
218
+ function onCopy() {
219
+ const activeObject = canvas .getActiveObject ()
220
+ if (! activeObject ) return
221
+ activeObject .clone ((cloned : fabric .Object ) => {
222
+ clipboard = cloned
223
+ })
224
+ }
225
+
226
+ // TODO 视频元素为什么无法复制
227
+ // 粘贴元素
228
+ function onPaste() {
229
+ if (clipboard === null ) return
230
+ // clone again, so you can do multiple copies.
231
+ clipboard ! .clone ((clonedObj : any ) => {
232
+ canvas .discardActiveObject ()
233
+ clonedObj .set ({
234
+ left: clonedObj .left + 10 ,
235
+ top: clonedObj .top + 10 ,
236
+ evented: true
237
+ })
238
+ if (clonedObj .type === ' activeSelection' ) {
239
+ // active selection needs a reference to the canvas.
240
+ clonedObj .canvas = canvas
241
+ clonedObj .forEachObject ((obj : any ) => {
242
+ canvas .add (obj )
243
+ })
244
+ // this should solve the unselectability
245
+ clonedObj .setCoords ()
246
+ } else {
247
+ canvas .add (clonedObj )
248
+ }
249
+ clipboard ! .top ! += 10
250
+ clipboard ! .left ! += 10
251
+ canvas .setActiveObject (clonedObj )
252
+ canvas .requestRenderAll ()
253
+ })
254
+ }
255
+
203
256
onMounted ((): void => {
204
257
// 初始化画布
205
258
initCanvas ()
0 commit comments