Commit f1c15699 authored by liujiangnan's avatar liujiangnan

feat: 点读功能

parent b5a849da
# 绘本阅读器 # 绘本阅读器
基于JSON数据实现的绘本阅读器系统,支持音频同步播放、页面切换、文本高亮等功能。 一个交互式的绘本阅读器,支持音频同步播放和点读功能。
## 功能特性 ## 功能特性
1. **分页展示图片** - 每一页显示一张图片,图片按照页面尺寸适配 ### 基本功能
2. **页面控制** - 左下角浮动上一页/下一页按钮 - 绘本页面展示
3. **音频播放控制** - 播放/暂停按钮,浮动在左下角 - 音频同步播放
4. **音频页面同步** - 音频播放到哪一页就显示对应页面 - 自动页面切换
5. **智能跳转** - 手动切换页面时,如果音频正在播放则跳转到对应页面的开始时间 - 实时高亮显示当前朗读内容
6. **蓝色矩形框** - 当音频读到某个矩形框时显示,过了就消失
7. **单词高亮** - 当音频读到某个单词时显示黄色背景高亮,切换页时高亮消失 ### 点读功能
8. **循环播放** - 音频播放结束后自动回到第一页重新开始 - 点击右上角的"点读"按钮进入点读模式
- 在点读模式下,当前页面的所有句子都会以蓝色矩形框显示
## 技术栈 - **只显示有完整时间信息的句子**(开始时间和结束时间都不为空)
- **点击任意矩形框播放整个句子**:一个句子可能由多个矩形框组成,点击任意矩形框都会播放整个句子的音频
- Vue 2 - **鼠标悬停高亮整个句子**:鼠标悬停在任意矩形框上时,同一句子的所有矩形框都会高亮显示
- Element UI 2.12 - **连续点击同一个句子时会被忽略**,确保当前句子播放完整
- jQuery 1.12.3 - **播放整个句子的时间范围**:使用句子的原始开始时间和结束时间,不进行额外的时间调整
- 原生HTML5 Audio API - **点读模式下不会因为音频播放时间而自动跳页**,用户可以自由浏览不同页面
- 再次点击"退出点读"按钮可以退出点读模式
## 数据结构
### 控制按钮
JSON数据包含以下字段: - 上一页/下一页:手动切换页面
- `audio_url`: 音频文件地址 - 播放/暂停:控制音频播放
- `pages`: 页面数组,每个页面包含:
- `image_url`: 图片地址
- `page`: 页面编号
- `start`: 页面开始时间(秒)
- `end`: 页面结束时间(秒)
- `groups`: 句子组数组,包含文本位置和时间信息
## 使用方法 ## 使用方法
1. 启动本地服务器: 1. 打开 `index.html` 文件
```bash 2. 等待页面加载完成
cd play 3. 点击播放按钮开始自动播放
python3 -m http.server 8000 4. 点击右上角的"点读"按钮进入点读模式
``` 5. 在点读模式下点击任意蓝色矩形框播放对应句子
2. 打开浏览器访问:`http://localhost:8000` ## 技术实现
3. 使用控制按钮: - 使用 Vue.js 进行状态管理
- 点击播放按钮开始播放音频 - 使用 HTML5 Audio API 进行音频控制
- 点击暂停按钮暂停播放 - 响应式设计,支持不同屏幕尺寸
- 点击上一页/下一页按钮切换页面 - 健壮的时间计算算法,确保音频播放的准确性
- 观察文本高亮和矩形框显示效果
## 文件结构
- `index.html` - 主页面模板
- `index.css` - 样式文件
- `index.js` - Vue应用逻辑
- `defaultData_1.json` - 示例数据文件
- `schema.json` - 数据格式定义
## 注意事项
- 确保音频文件和图片文件可以正常访问
- 数据文件需要符合schema.json定义的格式
- 浏览器需要支持HTML5 Audio API
...@@ -160,3 +160,73 @@ body { ...@@ -160,3 +160,73 @@ body {
text-align: center; text-align: center;
z-index: 200; z-index: 200;
} }
/* 点读按钮样式 */
.point-read-btn {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
padding: 10px 20px;
border: none;
border-radius: 25px;
background-color: rgba(255, 255, 255, 0.9);
color: #333;
font-size: 16px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.point-read-btn:hover {
background-color: rgba(255, 255, 255, 1);
transform: scale(1.05);
}
.point-read-btn.active {
background-color: rgba(76, 175, 80, 0.9);
color: white;
}
.point-read-btn.active:hover {
background-color: rgba(76, 175, 80, 1);
}
/* 点读模式下的可点击矩形框 */
.highlight-rect.clickable {
pointer-events: auto;
cursor: pointer;
border: 3px solid #007bff;
background-color: rgba(0, 123, 255, 0.1);
transition: all 0.2s ease;
}
.highlight-rect.clickable:hover {
background-color: rgba(0, 123, 255, 0.3);
border-color: #0056b3;
transform: scale(1.02);
}
/* 句子高亮状态 */
.highlight-rect.clickable.highlighted {
background-color: rgba(255, 193, 7, 0.4);
border-color: #ffc107;
border-width: 4px;
transform: scale(1.05);
box-shadow: 0 0 10px rgba(255, 193, 7, 0.6);
}
/* 调试信息样式 */
.debug-info {
position: absolute;
top: 80px;
right: 20px;
z-index: 100;
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 10px;
border-radius: 5px;
font-size: 12px;
font-family: monospace;
}
...@@ -26,6 +26,15 @@ ...@@ -26,6 +26,15 @@
<div v-else class="book-container"> <div v-else class="book-container">
<!-- 点读按钮 -->
<button
class="point-read-btn"
:class="{ active: isPointReadMode }"
@click="togglePointReadMode"
title="点读模式"
>
{{ isPointReadMode ? '退出点读' : '点读' }}
</button>
<!-- 图片容器 --> <!-- 图片容器 -->
<div class="image-container"> <div class="image-container">
...@@ -43,7 +52,14 @@ ...@@ -43,7 +52,14 @@
v-for="(rect, index) in activeRects" v-for="(rect, index) in activeRects"
:key="'rect-' + index" :key="'rect-' + index"
class="highlight-rect" class="highlight-rect"
:class="{
'clickable': isPointReadMode,
'highlighted': rect._highlighted
}"
:style="getRectStyle(rect)" :style="getRectStyle(rect)"
@click="isPointReadMode ? playRectAudio(rect, index) : null"
@mouseenter="isPointReadMode ? highlightSentence(rect) : null"
@mouseleave="isPointReadMode ? clearSentenceHighlight() : null"
></div> ></div>
<!-- 单词高亮 --> <!-- 单词高亮 -->
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment