实况照片功能完整实现文档
1. 功能概述
1.1 项目背景
这个是温柔猫进行的原创的二次修改
实况照片功能是基于AnZhiYu主题基础再次开发的一个增强功能,旨在支持苹果设备拍摄的Live Photo在网页端的展示和交互。该功能经历了从基础版本到完整优化版本的迭代开发。
1.2 功能演进历程
版本1.0 - 基础实况照片功能
- 核心功能: 支持实况照片的基本播放
- 交互方式: 鼠标悬停播放
- 显示效果: 进度条显示播放进度
- 智能封面: 自动提取视频首帧作为封面
版本2.0 - 长按播放优化
- 双模式支持: 悬停模式(hover) + 长按模式(press)
- 可配置进度条: 支持显示/隐藏进度条
- 自定义延迟: 可配置长按触发延迟时间
- 移动端适配: 完整的触摸事件支持
- UI/UX优化: 长按提示、视觉反馈等
版本3.0 - 加载优化
- 多重初始化: 解决首次加载适配问题
- 动态内容支持: MutationObserver监听DOM变化
- 性能优化: 防重复初始化、错误处理
- 稳定性提升: 多种加载时机适配
1.3 功能模块详解
1.3.1 核心播放引擎
1 2 3 4 5 6
| class LivePhoto { constructor() { this.containers = []; this.init(); } }
|
作用: 管理所有实况照片实例,提供统一的初始化和控制接口。
1.3.2 智能封面系统 暂时还没有实现!!!,后续会根据需求进行实现。
1 2 3 4
| async handleSmartCover(container, video, stillImage) { }
|
作用: 自动提取视频首帧,确保封面图片的一致性和美观度。
1.3.3 交互控制系统
1 2 3 4 5 6 7
| bindEvents(data) { if (data.playMode === 'hover') { } else if (data.playMode === 'press') { } }
|
作用: 根据配置提供不同的交互方式,适应不同使用场景。
1.3.4 进度显示系统
1 2 3 4
| startProgress(data) { if (!data.showProgress) return; }
|
作用: 可配置的进度条显示,提供视觉反馈。
2. 分步安装指南
2.1 环境准备
2.1.1 基础环境要求
- Node.js: 版本 >= 14.0.0
- Hexo: 版本 >= 5.0.0
- AnZhiYu主题: 最新版本
- 浏览器: 支持ES6+的现代浏览器
2.1.2 检查环境
1 2 3 4 5 6 7 8
| node --version
hexo version
cat themes/anzhiyu/package.json | grep version
|
2.2 依赖项安装
2.2.1 核心依赖
实况照片功能基于原生JavaScript开发,无需额外安装npm包。
2.2.2 主题依赖确认
确保AnZhiYu主题已正确安装:
1 2 3 4 5
| cd your-blog-directory
ls themes/anzhiyu/
|
2.3 配置文件设置
2.3.1 创建相册配置文件
在 source/_data/album.yml 中添加实况照片配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| - class_name: "实况照片展示" path_name: "/livePhotos" type: 1 description: "支持苹果Live Photo的动态展示" album_list: - content: "春日樱花盛开" live_photo: enable: true still_image: "/images/live-photos/sakura-still.jpg" video: "/images/live-photos/sakura-video.mp4" duration: 3 play_mode: "press" show_progress: false press_delay: 300 - content: "夕阳西下美景" live_photo: enable: true still_image: "/images/live-photos/sunset-still.jpg" video: "/images/live-photos/sunset-video.mp4" duration: 2.5 play_mode: "hover" show_progress: true press_delay: 500
|
2.3.2 创建页面文件
在 source/livePhotos/index.md 中创建页面:
1 2 3 4 5 6
| --- title: 实况照片 date: 2024-01-15 type: "album" layout: "album" ---
|
3. 完整部署流程
3.1 文件部署步骤
步骤1: 复制JavaScript文件
1 2
| cp live_photo.js themes/anzhiyu/source/js/
|
步骤2: 复制CSS样式文件
1 2
| cp live_photo.css themes/anzhiyu/source/css/_extra/album/
|
步骤3: 更新模板文件
编辑 themes/anzhiyu/layout/includes/page/album_detail.pug,添加实况照片支持:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| if item.live_photo && item.live_photo.enable .album-container-img - let posterSrc = item.live_photo.poster || item.live_photo.still_image - let playMode = item.live_photo.play_mode || 'hover' - let showProgress = item.live_photo.show_progress !== false - let pressDelay = item.live_photo.press_delay || 300 .live-photo-container(data-duration=item.live_photo.duration data-play-mode=playMode data-show-progress=showProgress data-press-delay=pressDelay) .live-photo-wrapper img.live-photo-still(src=item.live_photo.still_image alt=item.content) video.live-photo-video(preload="none" muted loop playsinline poster=posterSrc) source(src=item.live_photo.video type="video/mp4") .live-photo-controls .live-photo-play-btn i.anzhiyufont.anzhiyu-icon-play .live-photo-indicator LIVE .live-photo-cover-status(style="display: none;") span.cover-status-text 正在提取封面...
|
步骤4: 更新JavaScript引入
编辑 themes/anzhiyu/layout/includes/additional-js.pug,添加:
1 2
| //- 实况照片功能 script(async data-pjax src="/js/live_photo.js")
|
3.2 资源文件准备
3.2.1 创建媒体文件目录
1 2
| mkdir -p source/images/live-photos
|
3.2.2 准备媒体文件
- 静态图片: JPG/PNG格式,建议尺寸1080x1080或16:9
- 视频文件: MP4格式,时长2-5秒,建议码率适中
- 文件命名: 使用有意义的名称,如
sakura-still.jpg 和 sakura-video.mp4
- 建议从icloud进行下载 https://www.icloud.com.cn/
3.3 可能出现的问题及解决方案
问题1: 视频无法播放
现象: 实况照片显示静态图片,但无法播放视频
原因: 视频文件路径错误或格式不支持
解决方案:
1 2 3 4 5
| ls source/images/live-photos/
file source/images/live-photos/your-video.mp4
|
问题2: 首次加载不显示
现象: 需要刷新页面才能正常显示
原因: JavaScript初始化时机问题
解决方案: 已在v3.0版本中修复,确保使用最新版本的live_photo.js
问题3: 移动端触摸无效
现象: 在移动设备上无法触发播放
原因: 触摸事件绑定问题
解决方案: 检查CSS中的touch-action属性设置
问题4: 进度条不显示
现象: 配置了show_progress: true但进度条不显示
原因: CSS样式冲突或配置读取错误
解决方案:
1 2
| console.log(document.querySelector('.live-photo-container').dataset);
|
4. 代码部署说明
4.1 代码结构解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| themes/anzhiyu/ ├── source/ │ ├── js/ │ │ └── live_photo.js # 核心JavaScript文件 │ └── css/ │ └── _extra/ │ └── album/ │ └── live_photo.css # 样式文件 ├── layout/ │ └── includes/ │ ├── page/ │ │ └── album_detail.pug # 页面模板 │ └── additional-js.pug # JavaScript引入 source/ ├── _data/ │ └── album.yml # 配置文件 ├── images/ │ └── live-photos/ # 媒体资源目录 └── livePhotos/ └── index.md # 页面文件
|
4.2 关键配置参数说明
4.2.1 基础配置参数
1 2 3 4 5
| live_photo: enable: true still_image: "path/to/image" video: "path/to/video" duration: 3
|
4.2.2 交互配置参数
1 2 3
| play_mode: "press" show_progress: false press_delay: 300
|
4.2.3 高级配置参数
1 2 3
| poster: "path/to/poster" preload: "none" loop: true
|
4.3 JavaScript API说明
4.3.1 全局对象
1 2 3 4 5 6 7 8
| window.livePhoto
window.livePhoto.refresh();
window.livePhoto.destroy();
|
4.3.2 事件监听
1 2 3 4 5 6 7 8 9
| document.addEventListener('pjax:complete', () => { window.livePhoto.refresh(); });
window.addEventListener('load', () => { window.livePhoto.refresh(); });
|
4.4 CSS类名说明
4.4.1 容器类名
1 2 3 4 5
| .live-photo-container .live-photo-wrapper .live-photo-still .live-photo-video .live-photo-controls
|
4.4.2 控制元素类名
1 2 3 4
| .live-photo-play-btn .live-photo-indicator .live-photo-progress .live-photo-cover-status
|
4.4.3 状态类名
1 2 3
| .playing .loading .error
|
4.5 测试和验证方法
4.5.1 功能测试清单
4.5.2 性能测试
1 2 3 4 5 6 7
| console.log(performance.memory);
console.time('livePhotoInit'); window.livePhoto.refresh(); console.timeEnd('livePhotoInit');
|
4.5.3 兼容性测试
- 桌面端: Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
- 移动端: iOS Safari 13+, Chrome Mobile 80+, Samsung Internet 12+
4.5.4 调试方法
1 2 3 4 5 6 7 8 9 10
| window.livePhoto.debug = true;
console.log(window.livePhoto.containers);
document.querySelectorAll('.live-photo-container').forEach(container => { console.log('配置:', container.dataset); });
|
5. 高级配置和自定义
5.1 自定义样式
5.1.1 修改进度条样式
1 2 3 4 5
| .live-photo-progress { background: linear-gradient(90deg, #ff6b6b, #4ecdc4); height: 4px; border-radius: 2px; }
|
5.1.2 自定义长按提示 现在没有提示了,后续会根据需求进行添加。
1 2 3 4
| .live-photo-container[data-play-mode="press"]::after { content: "长按播放"; }
|
5.2 扩展功能开发
5.2.1 添加音频支持
1 2 3 4 5 6
| const audio = container.querySelector('.live-photo-audio'); if (audio) { data.audio = audio; }
|
5.2.2 添加全屏播放
1 2 3 4 5 6
| fullscreenPlay(data) { if (data.video.requestFullscreen) { data.video.requestFullscreen(); } }
|
6. 维护和更新
6.1 版本更新流程
- 备份现有文件
- 下载新版本文件
- 对比配置差异
- 更新文件并测试
- 部署到生产环境
6.2 常见维护任务
- 定期检查媒体文件完整性
- 监控页面加载性能
- 更新浏览器兼容性
- 优化媒体文件大小
6.3 常见问题修复
6.3.1 LivePhoto重复声明错误修复
问题描述:
在浏览器控制台出现 Uncaught SyntaxError: Identifier 'LivePhoto' has already been declared 错误,这是由于 live_photo.js 文件被多次加载导致的类重复声明。
错误原因:
- PJAX页面切换时重复加载脚本
- 浏览器缓存问题
- 多个页面同时引用相同脚本
修复步骤:
- 添加条件检查:
在 themes/anzhiyu/source/js/live_photo.js 文件中,为 LivePhoto 类声明添加条件检查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| if (typeof window.LivePhoto === 'undefined') { class LivePhoto { constructor() { this.containers = new Map(); this.debug = false; this.init(); } } window.LivePhoto = LivePhoto; if (!window.livePhoto) { window.livePhoto = new LivePhoto(); } if (typeof module !== 'undefined' && module.exports) { module.exports = LivePhoto; } }
|
- 增强事件监听器安全性:
为事件监听器添加安全检查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| if (typeof window.addEventListener !== 'undefined') { window.addEventListener('pjax:complete', () => { if (window.livePhoto && typeof window.livePhoto.refresh === 'function') { window.livePhoto.refresh(); } });
window.addEventListener('load', () => { if (window.livePhoto && typeof window.livePhoto.refresh === 'function') { window.livePhoto.refresh(); } }); }
|
- 清理缓存并重新生成:
1 2
| npx hexo clean npx hexo generate
|
验证修复:
- 打开浏览器开发者工具
- 刷新页面,检查控制台是否还有错误
- 测试实况照片功能是否正常工作
- 测试PJAX页面切换后功能是否正常
预防措施:
- 定期检查脚本重复加载问题
- 使用条件检查防止全局变量重复声明
- 在开发时启用调试模式监控脚本加载
6.4 故障排除工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function diagnoseLivePhoto() { const containers = document.querySelectorAll('.live-photo-container'); containers.forEach((container, index) => { console.log(`容器 ${index}:`, { initialized: container.dataset.livePhotoInitialized, config: container.dataset, video: container.querySelector('.live-photo-video'), image: container.querySelector('.live-photo-still') }); }); }
function checkLivePhotoStatus() { console.log('LivePhoto状态检查:', { classExists: typeof window.LivePhoto !== 'undefined', instanceExists: typeof window.livePhoto !== 'undefined', instanceType: typeof window.livePhoto, methods: window.livePhoto ? Object.getOwnPropertyNames(Object.getPrototypeOf(window.livePhoto)) : 'N/A' }); }
|
7. 总结
实况照片功能为AnZhiYu主题再次基础上提供了丰富的媒体展示能力,通过合理的配置和部署,可以为用户带来优秀的视觉体验。本文档涵盖了从基础安装到高级自定义的完整流程,确保开发者能够顺利部署和维护该功能。
本文档由野似o温柔猫+AI进行实现
如有问题,请参考故障排除章节或查看项目的GitHub仓库获取最新信息。
https://github.com/wenroumao/blog-wenroumao