Skip to content

Commit eff4db6

Browse files
committed
feat: Interactive Book 翻页音效
1 parent 896b1d7 commit eff4db6

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

src/assets/audio/page-turn.mp3

24 KB
Binary file not shown.

src/components/stateless/InteractiveBook/index.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { motion, AnimatePresence } from 'framer-motion'
33
import { clsx } from 'clsx'
44
import { ChevronLeft, ChevronRight, RefreshCcw, X, BookOpen } from 'lucide-react'
55
import { pdfjs } from 'react-pdf'
6+
import pageTurnAudio from '@/assets/audio/page-turn.mp3'
67
import 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

Comments
 (0)