1
+ /* eslint-disable vue/require-default-prop */
1
2
import type { DefineComponent , StyleValue } from "vue" ;
2
3
import {
3
4
h ,
@@ -10,8 +11,12 @@ import {
10
11
ref ,
11
12
watch ,
12
13
} from "vue" ;
13
- import { SceneProps } from "../types" ;
14
- import { InjectionSpotlightOptions } from "../constants" ;
14
+ import { SceneProps , ResolvedSceneProps , GlobalOptions } from "../types" ;
15
+ import {
16
+ InjectionGlobalOptions ,
17
+ InjectionSpotlightOptions ,
18
+ } from "../constants" ;
19
+ import { defaultOptions } from "../options" ;
15
20
import { useAct } from "../composables/act" ;
16
21
import { useBodyScrollFixed } from "../composables/bodyScrollFixed" ;
17
22
import { useWindowSize , useElementBounding } from "@vueuse/core" ;
@@ -31,63 +36,87 @@ export const VueTrailerScene = defineComponent({
31
36
32
37
cameraFollow : {
33
38
type : Boolean ,
34
- default : true ,
39
+ required : false ,
40
+ default : undefined ,
35
41
} ,
36
42
cameraFollowOptions : {
37
43
type : Object as ( ) => ScrollIntoViewOptions ,
38
- default : ( ) => ( {
39
- behavior : "smooth" ,
40
- block : "start" ,
41
- inline : "nearest" ,
42
- } ) ,
44
+ required : false ,
43
45
} ,
44
46
cameraFixAfterFollow : {
45
47
type : Boolean ,
46
- default : true ,
48
+ required : false ,
49
+ default : undefined ,
47
50
} ,
48
51
49
52
voiceOverPlacement : {
50
53
type : String as ( ) => "top" | "bottom" | "left" | "right" ,
51
- default : "left" ,
54
+ required : false ,
52
55
} ,
53
56
voiceOverAutoPlacement : {
54
57
type : Boolean ,
55
- default : true ,
58
+ required : false ,
59
+ default : undefined ,
56
60
} ,
57
61
voiceOverAlign : {
58
62
type : String as ( ) => "start" | "center" | "end" ,
59
- default : "center" ,
63
+ required : false ,
60
64
} ,
61
65
voiceOverWidth : {
62
66
type : Number ,
63
- default : 300 ,
67
+ required : false ,
64
68
} ,
65
69
voiceOverTitle : {
66
70
type : String ,
67
- default : "Voice Over" ,
71
+ required : false ,
68
72
} ,
69
73
voiceOverContent : {
70
74
type : String ,
71
- default :
72
- "It takes a strong man to save himself,\nand a great man to save another." ,
75
+ required : false ,
73
76
} ,
74
77
voiceOverPrevButtonText : {
75
78
type : String ,
76
- default : "Back" ,
79
+ required : false ,
77
80
} ,
78
81
voiceOverNextButtonText : {
79
82
type : String ,
80
- default : "Next" ,
83
+ required : false ,
81
84
} ,
82
85
voiceOverDoneButtonText : {
83
86
type : String ,
84
- default : "Done" ,
87
+ required : false ,
85
88
} ,
86
89
} ,
87
90
setup ( props , { slots } ) {
88
91
const spotlight = ref < HTMLElement | null > ( null ) ;
89
92
const voiceOver = ref < HTMLElement | null > ( null ) ;
90
93
94
+ const globalOptions = inject ( InjectionGlobalOptions , { } ) ;
95
+ const spotlightOptions = inject ( InjectionSpotlightOptions ) ;
96
+ const localOptions = ref < GlobalOptions > ( { } ) ;
97
+ const options = computed < ResolvedSceneProps > ( ( ) => ( {
98
+ ...defaultOptions ,
99
+ ...globalOptions ,
100
+ ...spotlightOptions ,
101
+ ...localOptions . value ,
102
+ actName : props . actName ,
103
+ sceneNumber : props . sceneNumber ,
104
+ } ) ) ;
105
+
106
+ function setLocalOptions ( options : GlobalOptions = { } ) {
107
+ localOptions . value = JSON . parse ( JSON . stringify ( options ) ) ;
108
+ }
109
+
110
+ watch (
111
+ ( ) => props ,
112
+ async ( ) => {
113
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
114
+ const { actName, sceneNumber, ...options } = props ;
115
+ setLocalOptions ( options ) ;
116
+ } ,
117
+ { deep : true , immediate : true } ,
118
+ ) ;
119
+
91
120
const {
92
121
actorWalkIn,
93
122
currentActName,
@@ -102,7 +131,7 @@ export const VueTrailerScene = defineComponent({
102
131
prevScene,
103
132
jumpToScene,
104
133
cut,
105
- } = useAct ( props . actName ) ;
134
+ } = useAct ( options . value . actName ) ;
106
135
107
136
const slotProp = reactive ( {
108
137
hasPrevScene,
@@ -120,22 +149,22 @@ export const VueTrailerScene = defineComponent({
120
149
121
150
const isCurrentScene = computed ( ( ) => {
122
151
return (
123
- currentActName . value === props . actName &&
124
- currentSceneNumber . value === props . sceneNumber
152
+ currentActName . value === options . value . actName &&
153
+ currentSceneNumber . value === options . value . sceneNumber
125
154
) ;
126
155
} ) ;
127
156
128
157
const defaultVoiceOverStyle = computed < StyleValue > ( ( ) => {
129
158
return {
130
- width : `${ props . voiceOverWidth } px` ,
159
+ width : `${ options . value . voiceOverWidth } px` ,
131
160
} ;
132
161
} ) ;
133
162
134
- const spotlightConfig = inject ( InjectionSpotlightOptions ) ;
135
163
const spotlightStyle = computed < StyleValue > ( ( ) => {
136
164
return {
137
- inset : `-${ spotlightConfig ?. padding || 0 } px` ,
138
- borderRadius : `${ spotlightConfig ?. borderRadius || 0 } px` ,
165
+ inset : `-${ options . value . spotlightPadding || 0 } px` ,
166
+ borderRadius : `${ options . value . spotlightBorderRadius || 0 } px` ,
167
+ overflow : "none" ,
139
168
} ;
140
169
} ) ;
141
170
@@ -151,10 +180,11 @@ export const VueTrailerScene = defineComponent({
151
180
const { width : windowWidth , height : windowHeight } = useWindowSize ( ) ;
152
181
153
182
const autoVoiceOverPlacement = computed < string > ( ( ) => {
154
- if ( ! props . voiceOverAutoPlacement ) return props . voiceOverPlacement ;
183
+ if ( ! options . value . voiceOverAutoPlacement )
184
+ return options . value . voiceOverPlacement ;
155
185
156
186
let possiblePositions : string [ ] = [ ] ;
157
- switch ( props . voiceOverPlacement ) {
187
+ switch ( options . value . voiceOverPlacement ) {
158
188
case "top" :
159
189
possiblePositions = [ "top" , "bottom" , "left" , "right" ] ;
160
190
break ;
@@ -208,7 +238,7 @@ export const VueTrailerScene = defineComponent({
208
238
) ;
209
239
}
210
240
211
- return possiblePositions [ 0 ] || props . voiceOverPlacement ;
241
+ return possiblePositions [ 0 ] || options . value . voiceOverPlacement ;
212
242
} ) ;
213
243
214
244
const isScrollFixed = ref ( false ) ;
@@ -219,7 +249,9 @@ export const VueTrailerScene = defineComponent({
219
249
let same = 0 ;
220
250
let lastPos : number ;
221
251
222
- el . scrollIntoView ( props . cameraFollowOptions as ScrollIntoViewOptions ) ;
252
+ el . scrollIntoView (
253
+ options . value . cameraFollowOptions as ScrollIntoViewOptions ,
254
+ ) ;
223
255
requestAnimationFrame ( check ) ;
224
256
225
257
function check ( ) {
@@ -243,22 +275,22 @@ export const VueTrailerScene = defineComponent({
243
275
if ( ! val ) return ;
244
276
245
277
actorWalkIn ( val ) ;
246
- if ( props . cameraFollow ) {
278
+ if ( options . value . cameraFollow ) {
247
279
isScrollFixed . value = true ;
248
280
await smoothScroll ( val ) ;
249
281
isScrollFixed . value = false ;
250
282
}
251
283
252
- if ( props . cameraFixAfterFollow ) fixed ( ) ;
284
+ if ( options . value . cameraFixAfterFollow ) fixed ( ) ;
253
285
} ) ;
254
286
255
287
onMounted ( ( ) => {
256
- addScene ( props . sceneNumber ) ;
288
+ addScene ( options . value . sceneNumber ) ;
257
289
} ) ;
258
290
259
291
onBeforeUnmount ( ( ) => {
260
292
cut ( ) ;
261
- removeScene ( props . sceneNumber ) ;
293
+ removeScene ( options . value . sceneNumber ) ;
262
294
} ) ;
263
295
264
296
return ( ) => {
@@ -274,7 +306,7 @@ export const VueTrailerScene = defineComponent({
274
306
h (
275
307
"div" ,
276
308
{
277
- id : `vue-trailer__spotlight-${ props . actName } -${ props . sceneNumber } ` ,
309
+ id : `vue-trailer__spotlight-${ options . value . actName } -${ options . value . sceneNumber } ` ,
278
310
class : "vue-trailer__spotlight" ,
279
311
ref : spotlight ,
280
312
style : spotlightStyle . value ,
@@ -286,7 +318,7 @@ export const VueTrailerScene = defineComponent({
286
318
class : [
287
319
"vue-trailer__voice-over" ,
288
320
autoVoiceOverPlacement . value ,
289
- props . voiceOverAlign ,
321
+ options . value . voiceOverAlign ,
290
322
] ,
291
323
ref : voiceOver ,
292
324
} ,
@@ -306,7 +338,7 @@ export const VueTrailerScene = defineComponent({
306
338
{
307
339
class : "efault__voice-over__header__content" ,
308
340
} ,
309
- props . voiceOverTitle ,
341
+ options . value . voiceOverTitle ,
310
342
) ,
311
343
slots . voCloseIcon ?.( ) ||
312
344
h (
@@ -329,7 +361,7 @@ export const VueTrailerScene = defineComponent({
329
361
] ) ,
330
362
h ( "div" , { class : "default__voice-over__body" } , [
331
363
slots . voBody ?.( ) ||
332
- h ( "div" , null , props . voiceOverContent ) ,
364
+ h ( "div" , null , options . value . voiceOverContent ) ,
333
365
] ) ,
334
366
h ( "div" , { class : "default__voice-over__footer" } , [
335
367
slots . voFooterScene ?.( ) ||
@@ -356,7 +388,7 @@ export const VueTrailerScene = defineComponent({
356
388
"default__voice-over__footer__btn" ,
357
389
onClick : ( ) => prevScene ( ) ,
358
390
} ,
359
- props . voiceOverPrevButtonText ,
391
+ options . value . voiceOverPrevButtonText ,
360
392
) ,
361
393
hasNextScene . value &&
362
394
h (
@@ -366,7 +398,7 @@ export const VueTrailerScene = defineComponent({
366
398
"default__voice-over__footer__btn" ,
367
399
onClick : ( ) => nextScene ( ) ,
368
400
} ,
369
- props . voiceOverNextButtonText ,
401
+ options . value . voiceOverNextButtonText ,
370
402
) ,
371
403
! hasNextScene . value &&
372
404
h (
@@ -376,7 +408,7 @@ export const VueTrailerScene = defineComponent({
376
408
"default__voice-over__footer__btn" ,
377
409
onClick : ( ) => cut ( ) ,
378
410
} ,
379
- props . voiceOverDoneButtonText ,
411
+ options . value . voiceOverDoneButtonText ,
380
412
) ,
381
413
] ,
382
414
) ,
0 commit comments