@@ -3,6 +3,7 @@ import { motion, AnimatePresence } from 'framer-motion'
33import { clsx } from 'clsx'
44import { ChevronLeft , ChevronRight , RefreshCcw , X , BookOpen } from 'lucide-react'
55import { pdfjs } from 'react-pdf'
6+ import pageTurnAudio from '@/assets/audio/page-turn.mp3'
67import styles from './index.module.less'
78
89// ─── 本地 Worker(兼容 Vite / Webpack 5) ──────────────────────
@@ -289,6 +290,16 @@ export default function InteractiveBook({
289290 const dragStartTimeRef = useRef ( 0 )
290291 const rafIdRef = useRef ( 0 )
291292
293+ // ─── 翻页音效 ────────────────────────────────────
294+ // 使用 DOM <audio> 元素而非 new Audio(),在 Storybook iframe 中更可靠
295+ const audioRef = useRef < HTMLAudioElement | null > ( null )
296+ const playPageTurnSound = ( ) => {
297+ const audio = audioRef . current
298+ if ( ! audio ) return
299+ audio . currentTime = 0
300+ audio . play ( ) . catch ( ( ) => { } )
301+ }
302+
292303 // ─── PDF → 图片 ─────────────────────────────────
293304 const pdfRenderWidth = typeof width === 'number' ? width - 24 : undefined
294305 const { pdfImages, pdfLoading, pdfError } = usePdfToImages ( pdfUrl , pdfRenderWidth )
@@ -308,6 +319,7 @@ export default function InteractiveBook({
308319
309320 const handleOpenBook = ( ) => {
310321 setIsOpen ( true )
322+ playPageTurnSound ( )
311323 }
312324
313325 const handleCloseBook = ( e : React . MouseEvent ) => {
@@ -322,6 +334,7 @@ export default function InteractiveBook({
322334 const newIndex = currentPageIndex + 1
323335 setCurrentPageIndex ( newIndex )
324336 onPageChange ?.( newIndex )
337+ playPageTurnSound ( )
325338 }
326339 }
327340
@@ -331,6 +344,7 @@ export default function InteractiveBook({
331344 const newIndex = currentPageIndex - 1
332345 setCurrentPageIndex ( newIndex )
333346 onPageChange ?.( newIndex )
347+ playPageTurnSound ( )
334348 }
335349 }
336350
@@ -411,6 +425,7 @@ export default function InteractiveBook({
411425 if ( ! isOpen ) {
412426 if ( deltaX < - 25 || ( velocity > 0.3 && deltaX < - 15 ) ) {
413427 setIsOpen ( true )
428+ playPageTurnSound ( )
414429 }
415430 setIsDragging ( false )
416431 setDragOffset ( 0 )
@@ -428,10 +443,12 @@ export default function InteractiveBook({
428443 const newIndex = currentPageIndex + 1
429444 setCurrentPageIndex ( newIndex )
430445 onPageChange ?.( newIndex )
446+ playPageTurnSound ( )
431447 } else if ( deltaX > 0 && currentPageIndex >= 0 ) {
432448 const newIndex = currentPageIndex - 1
433449 setCurrentPageIndex ( newIndex )
434450 onPageChange ?.( newIndex )
451+ playPageTurnSound ( )
435452 }
436453 }
437454
@@ -555,11 +572,13 @@ export default function InteractiveBook({
555572 e . preventDefault ( )
556573 setCurrentPageIndex ( - 1 )
557574 onPageChange ?.( - 1 )
575+ playPageTurnSound ( )
558576 break
559577 case 'End' :
560578 e . preventDefault ( )
561579 setCurrentPageIndex ( totalBookPages - 1 )
562580 onPageChange ?.( totalBookPages - 1 )
581+ playPageTurnSound ( )
563582 break
564583 }
565584 }
@@ -1259,6 +1278,9 @@ export default function InteractiveBook({
12591278 < div className = { styles . dragText } > { Math . abs ( dragOffset ) > 50 ? '松手翻页' : '继续拖拽' } </ div >
12601279 </ motion . div >
12611280 ) }
1281+
1282+ { /* 翻页音效 — 使用 DOM audio 元素,兼容 Storybook iframe */ }
1283+ < audio ref = { audioRef } src = { pageTurnAudio } preload = "auto" />
12621284 </ div >
12631285 )
12641286}
0 commit comments