@@ -127,6 +127,7 @@ function _SkinViewer({
127
127
const [ patch , setPatch ] = useState ( "" ) ;
128
128
const showUIRef = useRef ( ) ;
129
129
const dimensions = useRef ( { width : 1 , height : 1 } ) ;
130
+ const lastTapRef = useRef ( 0 ) ; // 用于移动端双击判断
130
131
131
132
useEffect ( ( ) => {
132
133
setDeltaX ( 0 ) ;
@@ -317,7 +318,6 @@ function _SkinViewer({
317
318
318
319
const handlers = useSwipeable ( {
319
320
onSwipeStart ( e ) {
320
- e . event . preventDefault ( ) ;
321
321
if ( fill ) {
322
322
draggingOrigin = [ e . deltaX , e . deltaY ] ;
323
323
}
@@ -335,7 +335,6 @@ function _SkinViewer({
335
335
}
336
336
} ,
337
337
onSwiped ( e ) {
338
- e . event . preventDefault ( ) ;
339
338
if ( fill ) {
340
339
const { width, height } = dimensions . current ;
341
340
let left = e . vxvy [ 0 ] / ( width - window . innerWidth ) ,
@@ -353,17 +352,13 @@ function _SkinViewer({
353
352
}
354
353
} ,
355
354
onSwipedLeft ( e ) {
356
- e . event . preventDefault ( ) ;
357
355
! fill && e . velocity > 0.6 && goNext ( true ) ;
358
356
} ,
359
357
onSwipedRight ( e ) {
360
- e . event . preventDefault ( ) ;
361
358
! fill && e . velocity > 0.6 && goPrevious ( true ) ;
362
359
} ,
363
360
onSwipedUp ( e ) {
364
- e . event . preventDefault ( ) ;
365
361
const { width, height } = dimensions . current ;
366
-
367
362
if (
368
363
( ! fill || ( height / width ) * window . innerWidth <= window . innerHeight ) &&
369
364
meta . changes
@@ -374,10 +369,31 @@ function _SkinViewer({
374
369
] || ""
375
370
) ;
376
371
} ,
372
+ onSwipedDown ( e ) {
373
+ toggleCentered ( ) ;
374
+ } ,
377
375
preventDefaultTouchmoveEvent : true ,
376
+ preventScrollOnSwipe : true ,
378
377
delta : { left : 3 , right : 3 , up : 50 } ,
379
378
} ) ;
380
379
380
+ // patch、showVideo、centered、imgPath、vidPath、skin 变化时重置 loaded,fill 不再触发
381
+ useEffect ( ( ) => {
382
+ setLoaded ( false ) ;
383
+ } , [ patch , showVideo , centered , imgPath , vidPath , skin ] ) ;
384
+
385
+ function handleTouchEnd ( e ) {
386
+ // 只处理单指触摸
387
+ if ( e . touches && e . touches . length > 0 ) return ;
388
+ const now = Date . now ( ) ;
389
+ if ( now - lastTapRef . current < 300 ) {
390
+ toggleFill ( ) ;
391
+ lastTapRef . current = 0 ;
392
+ } else {
393
+ lastTapRef . current = now ;
394
+ }
395
+ }
396
+
381
397
return (
382
398
< >
383
399
< Head >
@@ -411,6 +427,12 @@ function _SkinViewer({
411
427
[ styles . show ] : showUI ,
412
428
} ) }
413
429
>
430
+ { /* loading 动画 */ }
431
+ { ! loaded && (
432
+ < div className = { styles . loadingWrapper } >
433
+ < Loading />
434
+ </ div >
435
+ ) }
414
436
< div
415
437
className = { styles . hitbox }
416
438
{ ...handlers }
@@ -421,6 +443,7 @@ function _SkinViewer({
421
443
} )
422
444
}
423
445
onDoubleClick = { toggleFill }
446
+ onTouchEnd = { handleTouchEnd }
424
447
onMouseDown = { ( e ) => {
425
448
if ( fill ) {
426
449
draggingOrigin = [ e . screenX , e . screenY ] ;
@@ -534,6 +557,7 @@ function _SkinViewer({
534
557
loop
535
558
key = { `${ vidPath } -${ patch } ` }
536
559
style = { { objectFit : "cover" } }
560
+ onLoadedData = { ( ) => setLoaded ( true ) }
537
561
>
538
562
< source src = { asset ( vidPath , patch || "pbe" ) } />
539
563
</ video >
@@ -544,6 +568,7 @@ function _SkinViewer({
544
568
src = { asset ( imgPath , patch || "pbe" ) }
545
569
alt = { skin . name }
546
570
objectFit = "cover"
571
+ onLoad = { ( ) => setLoaded ( true ) }
547
572
/>
548
573
) }
549
574
</ div >
@@ -577,13 +602,7 @@ function _SkinViewer({
577
602
alt = { skin . name }
578
603
objectFit = { objectFit }
579
604
objectPosition = { objectPosition }
580
- onLoadingComplete = { ( { naturalHeight, naturalWidth } ) => {
581
- dimensions . current = {
582
- width : naturalWidth ,
583
- height : naturalHeight ,
584
- } ;
585
- setLoaded ( true ) ;
586
- } }
605
+ onLoad = { ( ) => setLoaded ( true ) }
587
606
/>
588
607
) }
589
608
</ main >
@@ -612,4 +631,4 @@ export function SkinViewer(props) {
612
631
}
613
632
614
633
return < _SkinViewer { ...props } /> ;
615
- }
634
+ }
0 commit comments