App前端视频播放JS添加全屏不遮挡且兼容iOS和Android的水印方案
一、核心需求分析
在移动端App的视频播放场景中,添加水印需满足以下关键要求:
全屏显示:水印需覆盖整个视频区域,包括iOS的全屏模式
不遮挡内容:水印位置应避免覆盖视频主要内容区域
跨平台兼容:同时支持iOS和Android系统及主流浏览器内核
性能优化:不影响视频播放流畅度和页面渲染性能
二、技术方案设计
1. 实现思路
采用双水印层叠加策略:
普通模式水印:覆盖在视频容器上层,随视频一起缩放
全屏模式水印:监听全屏事件,在全屏容器上动态创建水印层
2. 关键技术点
使用CSS定位和变换实现水印自适应布局
通过Fullscreen API监听全屏状态变化
利用CSS动画实现水印透明度渐变效果
针对不同平台进行兼容性处理
三、完整代码实现
1. HTML结构
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>视频水印示例</title> <link rel="stylesheet" href="watermark.css"> </head> <body> <div class="video-container"> <video id="myVideo" controls width="100%" height="auto"> <source src="your-video.mp4" type="video/mp4"> 您的浏览器不支持HTML5视频播放 </video> <!-- 普通模式水印 --> <div id="normalWatermark" class="watermark">机密内容</div> </div> <script src="watermark.js"></script> </body> </html>
2. CSS样式
/* 基础样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
}
.video-container {
position: relative;
max-width: 800px;
margin: 20px auto;
background: #000;
}
video {
display: block;
width: 100%;
height: auto;
}
/* 水印基础样式 */
.watermark {
position: absolute;
color: rgba(255, 255, 255, 0.5);
font-size: 16px;
font-weight: bold;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
pointer-events: none; /* 防止水印阻挡视频操作 */
user-select: none; /* 禁止选中文字 */
z-index: 10;
}
/* 普通模式水印定位 */
#normalWatermark {
top: 20px;
right: 20px;
transform-origin: top right;
}
/* 全屏模式水印样式 */
.fullscreen-watermark {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100vw !important;
height: 100vh !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 24px !important;
transform: none !important;
animation: watermarkFade 3s ease-in-out infinite alternate;
}
/* 水印淡入淡出动画 */
@keyframes watermarkFade {
0% { opacity: 0.3; }
100% { opacity: 0.7; }
}3. JavaScript逻辑
class VideoWatermark {
constructor(videoId, options = {}) {
this.video = document.getElementById(videoId);
this.normalWatermark = document.getElementById('normalWatermark');
this.fullscreenWatermark = null;
this.options = {
text: '机密内容',
fontSize: 16,
opacity: 0.5,
...options
};
this.init();
}
init() {
if (!this.video) {
console.error('视频元素未找到');
return;
}
// 设置普通模式水印
this.setupNormalWatermark();
// 监听全屏事件
this.addFullscreenListeners();
// 监听窗口大小变化,更新水印位置
window.addEventListener('resize', () => this.updateWatermarkPosition());
}
setupNormalWatermark() {
if (this.normalWatermark) {
this.normalWatermark.textContent = this.options.text;
this.normalWatermark.style.fontSize = `${this.options.fontSize}px`;
this.normalWatermark.style.opacity = this.options.opacity;
}
}
addFullscreenListeners() {
const fullscreenEvents = [
'fullscreenchange',
'webkitfullscreenchange',
'mozfullscreenchange',
'MSFullscreenChange'
];
fullscreenEvents.forEach(event => {
document.addEventListener(event, () => this.handleFullscreenChange());
});
// 针对iOS的特殊处理
this.video.addEventListener('webkitbeginfullscreen', () => this.handleIOSFullscreen(true));
this.video.addEventListener('webkitendfullscreen', () => this.handleIOSFullscreen(false));
}
handleFullscreenChange() {
const isFullscreen = !!(
document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement
);
if (isFullscreen) {
this.createFullscreenWatermark();
} else {
this.removeFullscreenWatermark();
}
}
handleIOSFullscreen(isEntering) {
if (isEntering) {
this.createFullscreenWatermark();
} else {
this.removeFullscreenWatermark();
}
}
createFullscreenWatermark() {
// 移除已存在的水印
this.removeFullscreenWatermark();
// 创建新的全屏水印
this.fullscreenWatermark = document.createElement('div');
this.fullscreenWatermark.className = 'watermark fullscreen-watermark';
this.fullscreenWatermark.textContent = this.options.text;
this.fullscreenWatermark.style.fontSize = `${this.options.fontSize * 1.5}px`;
this.fullscreenWatermark.style.opacity = this.options.opacity;
// 添加到全屏容器或body
const fullscreenElement = document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement ||
document.body;
fullscreenElement.appendChild(this.fullscreenWatermark);
}
removeFullscreenWatermark() {
if (this.fullscreenWatermark && this.fullscreenWatermark.parentNode) {
this.fullscreenWatermark.parentNode.removeChild(this.fullscreenWatermark);
this.fullscreenWatermark = null;
}
}
updateWatermarkPosition() {
// 可以在这里添加更复杂的逻辑来动态调整水印位置
// 例如根据视频宽高比调整水印位置避免遮挡重要内容
}
destroy() {
this.removeFullscreenWatermark();
window.removeEventListener('resize', this.updateWatermarkPosition);
const fullscreenEvents = [
'fullscreenchange',
'webkitfullscreenchange',
'mozfullscreenchange',
'MSFullscreenChange'
];
fullscreenEvents.forEach(event => {
document.removeEventListener(event, this.handleFullscreenChange);
});
}
}
// 初始化水印
document.addEventListener('DOMContentLoaded', () => {
const watermark = new VideoWatermark('myVideo', {
text: '机密内容',
fontSize: 16,
opacity: 0.5
});
});四、关键技术解析
1. 全屏API兼容性处理
不同浏览器对全屏API的实现存在差异,代码中通过监听多种事件确保兼容性:
fullscreenchange:标准事件webkitfullscreenchange:Chrome/Safari/Operamozfullscreenchange:FirefoxMSFullscreenChange:IE/Edge
2. iOS特殊处理
iOS的Safari浏览器对全屏API的支持与其他平台不同,需要使用WebKit特有的事件:
webkitbeginfullscreen:进入全屏时触发webkitendfullscreen:退出全屏时触发
3. 水印层级管理
通过z-index确保水印始终位于视频上方,同时使用pointer-events: none确保水印不会阻挡用户对视频的操作。
4. 性能优化措施
使用CSS硬件加速(transform属性)
避免在滚动或 resize 事件中执行复杂计算
合理使用CSS动画而非JavaScript动画
五、扩展功能建议
1. 动态水印内容
// 从服务器获取动态水印内容
async function loadDynamicWatermark() {
try {
const response = await fetch('/api/watermark');
const data = await response.json();
watermark.updateText(data.text);
} catch (error) {
console.error('加载水印失败:', error);
}
}2. 多行水印布局
.watermark.multiline {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}3. 基于视频内容的智能避让
可通过Canvas分析视频帧,检测主要内容区域并动态调整水印位置。
六、注意事项
水印内容应符合相关法律法规要求
在高分辨率屏幕上适当增大水印尺寸以保证可读性
测试不同设备和浏览器组合以确保兼容性
考虑添加水印开关控制,满足不同场景需求
通过以上方案,可实现在App前端视频播放中添加全屏不遮挡且兼容iOS和Android的水印功能,同时保证了良好的用户体验和性能表现。