@cc-component/cc-video 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,338 @@
1
+ import { _decorator, assetManager, Component, Node, VideoClip, VideoPlayer, view } from 'cc';
2
+ import { BaseVideo, IVideoParam } from './IVideo';
3
+ import { ImageAsset } from 'cc';
4
+ import { Texture2D, SpriteFrame, Sprite, UITransform } from 'cc';
5
+ import { Size } from 'cc';
6
+ import { Vec3 } from 'cc';
7
+ const { ccclass, property } = _decorator;
8
+ declare var tt: any;
9
+ @ccclass('VideoPlayTT')
10
+ export class VideoPlayTT extends BaseVideo {
11
+
12
+ onTimeUpdate: (data: { position: number, duration: number }) => void = null
13
+ pauseFinish: Function
14
+ onError: Function = null
15
+ onVideoEnd: Function = null
16
+ onRead: Function = null
17
+ data: { position: number, duration: number } = {
18
+ position: 0,
19
+ duration: 0
20
+ }
21
+ videoName: string = ""
22
+ videoPlayer: any
23
+ isPlaying: boolean = false
24
+ isReady: boolean = false;
25
+
26
+ getisPause() {
27
+ return !this.isPlaying
28
+ }
29
+ // node: Node;
30
+ taskId: string;
31
+ param: IVideoParam = {
32
+ isLoop: true,
33
+ isLocal: true,
34
+ isPlayTime: false,
35
+ isTargetSize: false
36
+ }
37
+ initParam: { bundle: string, dir: string }
38
+ remoteURL: string;
39
+
40
+ videoTexture: Texture2D;
41
+ imgAsset: ImageAsset;
42
+ video_sp: Sprite
43
+ video_sp_ut: UITransform;
44
+ video_sprite: SpriteFrame;
45
+ canPlay: boolean = false;
46
+ is_stop: boolean = false;
47
+
48
+ initVideo(initParam: { bundle: string, dir: string }) {
49
+ this.initParam = initParam
50
+ this.video_sp = this.node.getComponent(Sprite);
51
+ this.video_sp_ut = this.video_sp.getComponent(UITransform);
52
+ this.imgAsset = new ImageAsset();
53
+ this.videoTexture = new Texture2D();
54
+ this.video_sprite = new SpriteFrame();
55
+
56
+ // const sp = new SpriteFrame()
57
+ // this.videoTexture = new Texture2D();
58
+ // sp.texture = this.videoTexture
59
+ // this.imgAsset = new ImageAsset();
60
+ // this.videoTexture.image = this.imgAsset;
61
+ // this.video_sp.spriteFrame = sp;
62
+ //this.videoPlayer = this.createVideoWX('', true)
63
+ this.actioveSelf(false)
64
+
65
+ // this.video_sp.spriteFrame = new SpriteFrame();
66
+ // this.videoPlayer = this.createVideoWX("", true)
67
+ // this.imgAsset = new ImageAsset();
68
+ // this.imgAsset.reset(this.videoPlayer);
69
+ // this.videoTexture = new Texture2D();
70
+ // this.videoTexture.image = this.imgAsset;
71
+ // this.video_sp.spriteFrame.texture = this.videoTexture;
72
+ // const size = view.getVisibleSize();
73
+ // this.videoPlayer.width = size.width;
74
+ // this.videoPlayer.height = size.height
75
+ //this.video.videoHeight / this.video.videoWidth * width;
76
+ // const uiTransform = this.videoSpriteNode.getComponent(UITransform);
77
+ // uiTransform.width = this.video.width;
78
+ // uiTransform.height = this.video.height;
79
+ //this.video.play();
80
+
81
+
82
+
83
+ }
84
+ //创建视频地址(可能要做缓存处理)
85
+ public createVideoWX(remoteUrl: string, isloop: boolean = false) {
86
+ const self = this;
87
+ const windowInfo = tt.getSystemInfoSync();
88
+ const { windowWidth, windowHeight } = windowInfo;
89
+ let video = tt.createOffscreenVideo();
90
+ video.onError(self.videoError.bind(self))
91
+ video.onEnded(self.videoEnd.bind(self));
92
+ video.onTimeUpdate(self.onUpdate.bind(self))
93
+ video.onPlay(self.onPlay.bind(self))
94
+ video.onPause(self.onPause.bind(self))
95
+ return video;
96
+ }
97
+
98
+ onCanplay() {
99
+ // if (this.is_stop) {
100
+ // console.warn('停止')
101
+ // return
102
+ // } else {
103
+ // }
104
+ console.warn('准备好了')
105
+ this.videoTexture = new Texture2D();
106
+ this.imgAsset.reset(this.videoPlayer);
107
+ this.videoTexture.image = this.imgAsset;
108
+ this.video_sprite.texture = this.videoTexture;
109
+ this.video_sp.spriteFrame = this.video_sprite
110
+
111
+ this.videoPlayer.width = this.videoPlayer.videoWidth;
112
+ this.videoPlayer.height = this.videoPlayer.videoHeight;
113
+ this.canPlay = true;
114
+ this.videoPlayer.play()
115
+ // this.isReady = true;
116
+ // this.readyPlay()
117
+
118
+ }
119
+ public async loadVideo(name: string, param: IVideoParam) {
120
+ this.videoName = name
121
+ this.param = param;
122
+ // 首次调用tt.creatCanvas方法时创建的canvas为上屏canvas,之后创建的均为离屏canvas
123
+
124
+ this.destroyVideo()
125
+ this.isReady = false;
126
+ this.is_stop = false;
127
+ this.videoPlayer = this.createVideoWX(name, true)
128
+ this.actioveSelf(true)
129
+
130
+
131
+ this.videoPlayer.src = name;
132
+ this.videoPlayer.onCanplay(this.onCanplay.bind(this))
133
+
134
+ this.videoPlayer.loop = param.isLoop
135
+ const is_skip = name === this.remoteURL;
136
+ this.remoteURL = name;
137
+ if (!param.isTargetSize)
138
+ this.autoSize()
139
+
140
+ }
141
+
142
+ update(dt: number): void {
143
+ //if (this.videoPlayer && this.video_sp && this.video_sp.spriteFrame && this.isPlaying) {
144
+ if (this.videoPlayer && this.video_sp && this.video_sp.spriteFrame && this.canPlay) {
145
+ this.imgAsset.reset(this.videoPlayer);
146
+ this.videoTexture.updateImage();
147
+ this.video_sp.spriteFrame.texture = this.videoTexture;
148
+ }
149
+ }
150
+
151
+
152
+ // this.video = globalThis.tt.createOffscreenVideo();
153
+ // // 传入视频src
154
+ // this.video.src = "your video url";
155
+ // this.video.onCanplay(() => {
156
+ // const imgAsset = new ImageAsset();
157
+ // imgAsset.reset(this.video);
158
+ // this.videoTexture = new Texture2D();
159
+ // this.videoTexture.image = imgAsset;
160
+ // const spFrame = new SpriteFrame();
161
+ // spFrame.texture = this.videoTexture;
162
+ // this.videoSpriteNode.getComponent(Sprite).spriteFrame = spFrame;
163
+ // const width = view.getVisibleSize().width;
164
+ // this.video.width = width;
165
+ // this.video.height = this.video.videoHeight / this.video.videoWidth * width;
166
+ // const uiTransform = this.videoSpriteNode.getComponent(UITransform);
167
+ // uiTransform.width = this.video.width;
168
+ // uiTransform.height = this.video.height;
169
+ // this.video.play();
170
+ // });
171
+
172
+ play(isloop?: boolean) {
173
+ if (isloop != undefined || isloop != null) {
174
+ this.videoPlayer.loop = isloop
175
+ }
176
+ this.is_stop = false;
177
+
178
+ this.videoPlayer.play();
179
+ this.isPlaying = true
180
+ }
181
+ async pause() {
182
+ super.pause();
183
+ return new Promise<void>((resolve, reject) => {
184
+ this.pauseFinish = resolve;
185
+ this.videoPlayer.pause();
186
+ this.isPlaying = false
187
+
188
+ console.log("暂停")
189
+ })
190
+
191
+ }
192
+ stop() {
193
+ this.videoPlayer.stop();
194
+ this.isPlaying = false
195
+ console.log("停止")
196
+ this.canPlay = false;
197
+
198
+ }
199
+
200
+ resume() {
201
+ this.videoPlayer.resume();
202
+ this.isPlaying = true
203
+ }
204
+
205
+ seek(time: number) {
206
+ //console.error('seek', time)
207
+ this.videoPlayer.seek(time)
208
+ }
209
+
210
+ private videoEnd() {
211
+ // if (!this.isloop) this.node.off(VideoPlayer.EventType.COMPLETED, this.videoEnd, this);
212
+ this.onVideoEnd?.();
213
+ }
214
+ private playIng() {
215
+ // if (!this.isloop) this.node.off(VideoPlayer.EventType.PLAYING, this.playIng, this);
216
+ //this.isPlaying = true
217
+ //this.callReadBack && this.callReadBack()
218
+ }
219
+
220
+ private async readyPlay() {
221
+ this.videoPlayer.pause()
222
+ this.onRead?.(this)
223
+
224
+ this.scheduleOnce(() => {
225
+ this.isPlaying = false
226
+ })
227
+ // if (!this.isloop) this.node.off(VideoPlayer.EventType.READY_TO_PLAY, this.readyPlay, this);
228
+ }
229
+ private videoError(err: any) {
230
+
231
+ this.onError?.(err);
232
+ }
233
+ private onPlay() {
234
+ this.isPlaying = true
235
+ if (!this.isReady) {
236
+ this.isReady = true;
237
+ this.is_stop = false
238
+ this.readyPlay()
239
+ }
240
+ this.isReady = true;
241
+ }
242
+ onPause() {
243
+ if (this.pauseFinish) {
244
+ this.pauseFinish()
245
+ this.pauseFinish = null
246
+ }
247
+ }
248
+
249
+ protected onDestroy(): void {
250
+ this.destroyVideo()
251
+ }
252
+
253
+ protected onUpdate(data: any): void {
254
+ if (this.isPlaying && this.param.isPlayTime) {
255
+ this.onTimeUpdate?.(data)
256
+
257
+ }
258
+ }
259
+
260
+ async destroyVideo() {
261
+ if (this.videoPlayer) {
262
+
263
+
264
+ this.is_stop = true
265
+ this.actioveSelf(false)
266
+ this.video_sp.spriteFrame = null
267
+ //this.videoPlayer.x = 2000;
268
+ this.pause()
269
+ console.warn('销毁了视频')
270
+ this.isReady = false;
271
+
272
+ this.videoPlayer.destroy()
273
+ this.videoPlayer.offCanplay(this.onCanplay)
274
+ this.videoPlayer.offError(this.videoError)
275
+ this.videoPlayer.offError(this.videoError)
276
+ this.videoPlayer.offEnded(this.videoEnd);
277
+ this.videoPlayer.offTimeUpdate(this.onUpdate)
278
+ this.videoPlayer.offPlay(this.onPlay)
279
+ this.videoPlayer.offPause(this.onPause)
280
+ this.videoPlayer = null
281
+
282
+ }
283
+ }
284
+
285
+ actioveSelf(show: boolean) {
286
+ this.video_sp.node.active = show
287
+ }
288
+
289
+ setSize(param: { x: number, y: number, width: number, height: number }) {
290
+ if (this.videoPlayer) {
291
+ var size = view.getVisibleSize();
292
+ var designResolutionSize = view.getDesignResolutionSize();
293
+ var ratio = size.width / designResolutionSize.width;
294
+ var width = param.width * ratio;
295
+ var height = param.height * ratio;
296
+ var x = param.x * ratio - width / 2;;
297
+ var y = param.y - size.height + param.height / 2 * ratio //* ratio// + param.height / 2 * ratio
298
+ this.video_sp_ut.node.position = new Vec3(x, y, 0);
299
+ this.video_sp_ut.contentSize = new Size(width, height);
300
+ console.error(param.y, size)
301
+ }
302
+ }
303
+
304
+ videoFit(param: { x: number, y: number, width: number, height: number }) {
305
+ if (this.videoPlayer) {
306
+ const size = view.getVisibleSize();
307
+ const designResolutionSize = view.getDesignResolutionSize();
308
+ const ratio = size.width / designResolutionSize.width;
309
+ const width = param.width * ratio;
310
+ const height = param.height * ratio;
311
+ const x = param.x * ratio - width / 2;
312
+ const y = param.y * ratio + param.height / 2 * ratio;
313
+ this.video_sp_ut.node.position = new Vec3(x, y, 0);
314
+ this.video_sp_ut.contentSize = new Size(width, height);
315
+ }
316
+ }
317
+
318
+ // 节点位置适配
319
+ autoSize() {
320
+ if (this.videoPlayer) {
321
+ let size = view.getVisibleSize();
322
+ if (this.param.isVideoFit) {
323
+ this.videoFit({ x: size.width / 2, y: -size.height / 2, width: 1080, height: 1920 });
324
+ return;
325
+ }
326
+ const designResolutionSize = view.getDesignResolutionSize()
327
+ const ratio = size.height / designResolutionSize.height
328
+
329
+ const width = size.width * ratio
330
+ const x = Math.abs(size.width - width) / 2
331
+ this.video_sp_ut.node.position = new Vec3(-x, 0, 0)
332
+ this.video_sp_ut.contentSize = new Size(width, size.height)
333
+ }
334
+ }
335
+
336
+ }
337
+
338
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "ver": "4.0.24",
3
+ "importer": "typescript",
4
+ "imported": true,
5
+ "uuid": "624a16da-86f2-40dd-b167-a08a6dae88ef",
6
+ "files": [],
7
+ "subMetas": {},
8
+ "userData": {}
9
+ }
@@ -0,0 +1,274 @@
1
+ import { _decorator, assetManager, Component, Node, VideoClip, VideoPlayer, view } from 'cc';
2
+ import { BaseVideo, IVideoParam } from './IVideo';
3
+ const { ccclass, property } = _decorator;
4
+ declare var wx: any;
5
+ @ccclass('VideoPlayWX')
6
+ export class VideoPlayWX extends BaseVideo {
7
+
8
+ onTimeUpdate: (data: { position: number, duration: number }) => void = null
9
+ pauseFinish: Function
10
+ onError: Function = null
11
+ onVideoEnd: Function = null
12
+ onRead: Function = null
13
+ data: { position: number, duration: number } = {
14
+ position: 0,
15
+ duration: 0
16
+ }
17
+ videoName: string = ""
18
+ videoPlayer: any
19
+ isPlaying: boolean = false
20
+ isReady: boolean = false;
21
+
22
+ getisPause() {
23
+ return !this.isPlaying
24
+ }
25
+ // node: Node;
26
+ taskId: string;
27
+ param: IVideoParam = {
28
+ isLoop: true,
29
+ isLocal: true,
30
+ isPlayTime: false,
31
+ isTargetSize: false
32
+ }
33
+ initParam: { bundle: string, dir: string }
34
+ remoteURL: string;
35
+ initVideo(initParam: { bundle: string, dir: string }) {
36
+ this.initParam = initParam
37
+ this.videoPlayer = this.createVideoWX("", true)
38
+
39
+ }
40
+ //创建视频地址(可能要做缓存处理)
41
+ public createVideoWX(remoteUrl: string, isloop: boolean = false) {
42
+ const self = this;
43
+ const windowInfo = wx.getWindowInfo();
44
+ const { windowWidth, windowHeight } = windowInfo;
45
+ let video = wx.createVideo({
46
+ // x: 0,
47
+ // y: 0,
48
+ // width: windowWidth,
49
+ // height: windowHeight,
50
+ //src: remoteUrl,
51
+ // objectFit: "cover",
52
+ // autoplay: true,
53
+ // loop: isLoop,
54
+ // controls: false,
55
+ // underGameView: true,
56
+ // //zIndex: -9999,//好大的坑 官方API根本没写这个
57
+ // showCenterPlayBtn: false,
58
+ // showProgress: false,
59
+ // showProgressInControlMode: false,
60
+ // enableProgressGesture: false,
61
+ x: 0,
62
+ y: 0,
63
+ src: remoteUrl,
64
+ loop: isloop,
65
+ width: windowWidth,
66
+ height: windowHeight,
67
+ controls: false,
68
+ showProgress: false,
69
+ showProgressInControlMode: false,
70
+ autoplay: true,
71
+ showCenterPlayBtn: false,
72
+ underGameView: true,
73
+ enableProgressGesture: false,
74
+ objectFit: "cover",
75
+ //zIndex: -9999,//好大的坑 官方API根本没写这个
76
+ });
77
+ video.onError(self.videoError.bind(self))
78
+ video.onEnded(self.videoEnd.bind(self));
79
+ video.onTimeUpdate(self.onUpdate.bind(self))
80
+ video.onPlay(self.onPlay.bind(self))
81
+ video.onPause(self.onPause.bind(self))
82
+ return video;
83
+ }
84
+
85
+ public async loadVideo(name: string, param: IVideoParam) {
86
+ this.videoName = name
87
+ this.param = param;
88
+ // const is_skip = name === (this.videoPlayer?.src ?? "");
89
+ // if (is_skip) {
90
+ // return;
91
+ // }
92
+ // this.destroyVideo();
93
+ this.isReady = false;
94
+ // this.videoPlayer = this.createVideoWX(name, param.isLoop)
95
+ this.videoPlayer.hide = false;
96
+ this.videoPlayer.x = 0;
97
+ this.videoPlayer.src = name;
98
+ this.videoPlayer.loop = param.isLoop
99
+ const is_skip = name === this.remoteURL;
100
+
101
+ if (is_skip) {
102
+ this.isReady = true;
103
+ this.readyPlay()
104
+ } else {
105
+ this.play()
106
+ }
107
+ this.remoteURL = name;
108
+ if (!param.isTargetSize)
109
+ this.autoSize()
110
+ }
111
+
112
+ play(isloop?: boolean) {
113
+ if (isloop != undefined || isloop != null) {
114
+ this.videoPlayer.loop = isloop
115
+ }
116
+ this.videoPlayer.play();
117
+ this.isPlaying = true
118
+ }
119
+ async pause() {
120
+ super.pause();
121
+ this.isPlaying = false
122
+ return new Promise<void>((resolve, reject) => {
123
+ this.pauseFinish = resolve;
124
+ this.videoPlayer.pause();
125
+ console.log("暂停")
126
+ })
127
+ }
128
+ stop() {
129
+ this.videoPlayer.stop();
130
+ this.isPlaying = false
131
+ console.log("停止")
132
+
133
+ }
134
+ resume() {
135
+ this.videoPlayer.resume();
136
+ this.isPlaying = true
137
+ }
138
+
139
+ seek(time: number) {
140
+ this.videoPlayer.seek(time)
141
+ }
142
+
143
+ private videoEnd() {
144
+ // if (!this.isloop) this.node.off(VideoPlayer.EventType.COMPLETED, this.videoEnd, this);
145
+ this.onVideoEnd?.();
146
+ }
147
+ private playIng() {
148
+ // if (!this.isloop) this.node.off(VideoPlayer.EventType.PLAYING, this.playIng, this);
149
+ //this.isPlaying = true
150
+ //this.callReadBack && this.callReadBack()
151
+ }
152
+ private async readyPlay() {
153
+ this.videoPlayer.pause();
154
+ // if (!this.isloop) this.node.off(VideoPlayer.EventType.READY_TO_PLAY, this.readyPlay, this);
155
+ this.onRead?.(this)
156
+ }
157
+ private videoError() {
158
+ this.onError?.();
159
+ }
160
+ private onPlay() {
161
+ if (!this.isReady) {
162
+ this.readyPlay()
163
+ }
164
+ this.isReady = true;
165
+ }
166
+ onPause() {
167
+ if (this.pauseFinish) {
168
+ this.pauseFinish()
169
+ this.pauseFinish = null
170
+ }
171
+ }
172
+
173
+ protected onDestroy(): void {
174
+ this.destroyVideo()
175
+ }
176
+
177
+ protected onUpdate(data: any): void {
178
+ if (this.isPlaying && this.param.isPlayTime) {
179
+ this.onTimeUpdate?.(data)
180
+
181
+ }
182
+ }
183
+
184
+ async destroyVideo() {
185
+ if (this.videoPlayer) {
186
+ // this.videoPlayer.offEnded(this.videoEnd)
187
+ // this.videoPlayer.onTimeUpdate(this.onUpdate)
188
+ // this.videoPlayer.offError(this.videoError)
189
+ // this.videoPlayer.offPause(this.onPause)
190
+ // this.videoPlayer.offPlay(this.onPlay)
191
+ //this.videoPlayer.objectFit = "cover"
192
+ this.videoPlayer.hide = true
193
+ this.videoPlayer.x = 2000;
194
+ this.stop()
195
+ this.isReady = false;
196
+ console.error(this.videoPlayer)
197
+ //this.seek(0)
198
+ // this.videoPlayer.src = '';
199
+ //this.videoPlayer.destroy()
200
+ //this.videoPlayer = null
201
+ }
202
+ }
203
+
204
+ setSize(param: { x: number, y: number, width: number, height: number }) {
205
+ if (this.videoPlayer) {
206
+ // fill 填充,视频拉伸填满整个容器,不保证保持原有长宽比例
207
+ // contain 包含,保持原有长宽比例。保证视频尺寸一定可以在容器里面放得下。因此,可能会有部分空白
208
+ // cover 覆盖,保持原有长宽比例。保证视频尺寸一定大于容器尺寸,宽度和高度至少有一个和容器一致。因此,视频有部分会看不见
209
+ const windowInfo = wx.getWindowInfo();
210
+ const { windowWidth, windowHeight } = windowInfo;
211
+ const designResolutionSize = view.getDesignResolutionSize()
212
+
213
+ const ratio = windowWidth / designResolutionSize.width
214
+ const width = param.width * ratio
215
+ const height = param.height * ratio
216
+ const x = param.x * ratio - width / 2
217
+ const y = param.y * ratio + param.height / 2 * ratio;
218
+ this.videoPlayer.objectFit = "fill"
219
+ this.videoPlayer.x = x;
220
+ this.videoPlayer.y = windowHeight - y;
221
+ this.videoPlayer.width = width
222
+ this.videoPlayer.height = height
223
+ this.videoPlayer.underGameView = true;
224
+
225
+ }
226
+ }
227
+
228
+ videoFit(param: { x: number, y: number, width: number, height: number }) {
229
+ if (this.videoPlayer) {
230
+ const windowInfo = wx.getWindowInfo();
231
+ const { windowWidth, windowHeight } = windowInfo;
232
+ const designResolutionSize = view.getDesignResolutionSize()
233
+
234
+ const ratio = windowWidth / designResolutionSize.width
235
+ const width = param.width * ratio
236
+ const height = param.height * ratio
237
+ const x = param.x * ratio - width / 2
238
+ const y = param.y * ratio + param.height / 2 * ratio;
239
+ this.videoPlayer.objectFit = "contain"
240
+ this.videoPlayer.x = x;
241
+ this.videoPlayer.y = y;
242
+ this.videoPlayer.width = width
243
+ this.videoPlayer.height = height
244
+ this.videoPlayer.underGameView = true;
245
+ }
246
+ }
247
+
248
+ // 节点位置适配
249
+ autoSize() {
250
+ if (this.videoPlayer) {
251
+ const designResolutionSize = view.getDesignResolutionSize()
252
+ let windowInfo = wx.getWindowInfo();
253
+ if (this.param.isVideoFit) {
254
+ this.videoPlayer.objectFit = "contain";
255
+ this.videoPlayer.x = 0;
256
+ this.videoPlayer.y = 0;
257
+ this.videoPlayer.width = windowInfo.windowWidth;
258
+ this.videoPlayer.height = windowInfo.windowHeight;
259
+ return;
260
+ }
261
+
262
+ const { windowWidth, windowHeight } = windowInfo;
263
+ this.videoPlayer.objectFit = "cover"
264
+ this.videoPlayer.x = 0;
265
+ this.videoPlayer.y = 0;
266
+ this.videoPlayer.width = windowWidth
267
+ this.videoPlayer.height = windowHeight
268
+ this.videoPlayer.underGameView = true;
269
+ }
270
+ }
271
+
272
+ }
273
+
274
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "ver": "4.0.24",
3
+ "importer": "typescript",
4
+ "imported": true,
5
+ "uuid": "807ce772-7243-4acf-8c65-f94b5a8ee868",
6
+ "files": [],
7
+ "subMetas": {},
8
+ "userData": {}
9
+ }