终于把你给定住了
作者: 蜗牛不是牛 日期: 6天前
整体功能总结
这段代码实现了一个完整的视频播放页面,核心功能包括:
- 动态调用后台配置的视频 API,支持灵活更换视频源;
- 视频播放、切换、连续播放等基础控制;
- 加载状态提示与错误自动重试,提升用户体验;
- 自适应不同设备(桌面 / 移动端)的响应式布局;
- 视频资源保护(禁用下载、右键菜单、添加水印);
- 与 Typecho 博客系统无缝集成,支持动态加载评论模块和模板组件。
- 通过 CSS+HTML+PHP+JS 的配合,实现了 “美观、易用、适配、安全” 的视频播放体验。
使用场景与扩展
若需要更换水印内容,只需修改div标签内的文字(如改为网站域名、品牌名等);
- 如需更换位置,可调整top/right属性(例如left:10px改为左上角);
- 若想使用图片水印,可将div标签替换为img标签,并调整样式(如background-image),保持pointer-events: none和层级设置即可。
总体而言,该水印设计在版权保护和用户体验之间做了平衡,既起到了标识作用,又不会过度干扰视频观看。
<style>
/* 添加媒体查询适配移动端 */
@media (max-width: 768px) {
.sm-mainContent {
flex-direction: column;
}
#player-container {
transition: none; /* 移动端禁用过渡动画避免错位 */
}
.video-wrapper {
width: 100%; /* 移动端全宽度 */
max-width: none;
margin-bottom: 20px;
}
#buttons {
flex-direction: column;
align-items: center;
}
#switch, #next1 {
width: 90%;
max-width: 300px;
margin: 6px 0;
}
/* 移动端横屏模式 */
.video-wrapper.landscape-mode {
width: 100%;
max-width: none;
}
}
/* 原有样式优化 */
#switch,#next1{
background: linear-gradient(135deg, #7b68ee 0%, #4895ef 100%);
color:#fff;
line-height:40px;
text-align:center;
width:100px;
border:none;
margin:0 6px;
border-radius:6px;
font-weight:bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
#switch:hover,#next1:hover{
background: linear-gradient(135deg, #6a5acd 0%, #3d85c6 100%);
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
#switch:active,#next1:active{
transform: scale(0.98);
}
.widget{
margin: 20px 0;
}
.video-wrapper {
width: 70%;
margin: 0 auto;
position: relative;
max-width: 600px;
min-height: 300px;
transition: all 0.3s ease;
}
/* 横屏模式下的容器样式 */
.video-wrapper.landscape-mode {
width: 100%;
max-width: none;
}
#player-container {
width: 100%;
position: relative;
background-color: #000;
overflow: hidden;
aspect-ratio: 9/16; /* 默认竖屏比例 */
transition: all 0.3s ease;
}
/* 横屏比例类 */
#player-container.landscape {
aspect-ratio: 16/9;
}
#player {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
}
/* 优化后的加载提示 */
.video-loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start; /* 顶部对齐 */
padding-top: 40%; /* 避免遮挡播放按钮 */
}
.video-loading-text {
color: white;
font-size: 16px;
margin-top: 15px;
text-align: center;
max-width: 80%;
}
.loader {
width: 40px;
height: 40px;
border: 4px solid rgba(255,255,255,0.2);
border-top: 4px solid #7b68ee;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.video-watermark {
position: absolute;
top: 10px;
right: 10px;
color: rgba(255, 255, 255, 0.3);
font-size: 18px;
font-weight: bold;
pointer-events: none;
z-index: 5;
text-shadow: 0 0 2px rgba(0,0,0,0.3);
}
.video-controls {
text-align: center;
margin-top: 10px;
padding: 10px 0;
}
/* 确保播放按钮可点击 */
#player::-webkit-media-controls-play-button {
z-index: 15;
}
</style>
<div class="sm-mainContent">
<div class="sm-innermainContent">
<section>
<article>
<section class="widget xm-margin-top20 xm-list-wai">
<ul class="widget-list">
<div class="video-wrapper" id="videoWrapper">
<div id="player-container">
<div class="video-loading" id="videoLoading">
<div class="loader"></div>
<div class="video-loading-text">视频加载中,请稍候...</div>
</div>
<!-- 替换为动态视频路径 -->
<div id="player-wrapper">
<div class="video-watermark">蜗牛视频</div>
<video id="player" src="<?php $this->options->video(); ?>" controls="controls"
controlsList="nodownload" oncontextmenu="return false"></video>
</div>
</div>
<div class="video-controls">
<section id="buttons">
<button id="switch">连续: 开</button>
<button id="next1">换一个</button>
</section>
</div>
</div>
</ul>
</section>
</article>
</section>
<?php
// 保留原有的评论模块调用
if($this->options->xmmokuai == 'mkb'){
$this->need('commentsa.php');
}elseif($this->options->xmmokuai == 'mkc'){
$this->need('commentsb.php');
}else{
$this->need('comments.php');
}
?>
</div>
</div>
<?php $this->need('sidebar.php'); ?>
<?php $this->need('footer.php'); ?>
<script>
(function (window, document) {
if (top != self) {
window.top.location.replace(self.location.href);
}
var get = function (id) {
return document.getElementById(id);
}
var bind = function (element, event, callback) {
return element.addEventListener(event, callback);
}
var auto = true;
var player = get('player');
var loadingIndicator = get('videoLoading');
var playerContainer = get('player-container');
var videoWrapper = get('videoWrapper');
var showLoading = function() {
loadingIndicator.style.display = 'flex';
// 根据播放器大小调整提示位置
var playerHeight = playerContainer.offsetHeight;
var topPosition = Math.min(playerHeight * 0.4, 200); // 最高不超过200px
// 设置加载提示位置
loadingIndicator.style.paddingTop = topPosition + 'px';
};
var hideLoading = function() {
loadingIndicator.style.display = 'none';
loadingIndicator.style.paddingTop = '40%'; // 恢复默认值
};
// 优化后的比例调整函数
var adjustPlayerRatio = function() {
var videoWidth = player.videoWidth;
var videoHeight = player.videoHeight;
if (videoWidth && videoHeight) {
var aspectRatio = videoWidth / videoHeight;
// 移除所有比例类
playerContainer.classList.remove('landscape');
videoWrapper.classList.remove('landscape-mode');
// 判断横屏视频
if (aspectRatio > 1) {
playerContainer.classList.add('landscape');
videoWrapper.classList.add('landscape-mode');
}
}
};
var randomm = function () {
showLoading();
player.pause();
// 动态获取视频API路径并添加随机参数防止缓存
var baseUrl = '<?php $this->options->video(); ?>';
var newSrc = baseUrl + (baseUrl.indexOf('?') > -1 ? '&' : '?') + '_t=' + Math.random();
player.src = newSrc;
// 重置容器比例
playerContainer.classList.remove('landscape');
videoWrapper.classList.remove('landscape-mode');
player.play().then(function() {
// 延迟调整比例确保元数据加载
setTimeout(adjustPlayerRatio, 500);
hideLoading();
}).catch(function() {
setTimeout(hideLoading, 500);
});
};
bind(get('next1'), 'click', randomm);
bind(player, 'error', function () {
hideLoading();
setTimeout(randomm, 500);
});
bind(player, 'loadedmetadata', function() {
adjustPlayerRatio();
});
bind(player, 'canplay', function() {
hideLoading();
});
bind(get('switch'), 'click', function () {
auto = !auto;
this.innerText = '连续: ' + (auto ? '开' : '关');
});
bind(player, 'ended', function () {
if (auto) {
randomm();
}
});
// 初始加载
window.addEventListener('load', function() {
// 初始化比例
setTimeout(adjustPlayerRatio, 1000);
// 初始显示加载提示
showLoading();
// 如果视频已经可以播放,则隐藏加载提示
if (player.readyState >= 3) {
setTimeout(hideLoading, 500);
}
});
// 监听窗口大小变化调整加载提示位置
window.addEventListener('resize', function() {
if (loadingIndicator.style.display === 'flex') {
showLoading();
}
});
})(window, document);
</script>
一直琢磨着给 “小姐姐视频” 页面弄个固定效果,这样每次刷视频时页面就不会来回晃动,可惜这事儿搁了好久都没搞定。今天有空问了下 AI,跟豆包大模型聊了几次,它还真做出了我想要的效果,太厉害了,必须感谢!有了 AI,像我这样的新手也能玩得很顺手,真不错!最让我开心的是,播放器能根据视频的实际比例,自动在 9:16 和 16:9 之间切换,这操作简直帅呆了!!!
前去观看:https://www.wnblog.com/niumei.html
评论: 17 | 查看: 520
美女图是要上线了吗、期待。
没呢没呢,期待大佬你能整一个哈。
看了一个视频又一个视频,差点陷入进去了(好东西值得折腾)哈哈哈
这上千小视频中我放了一个彩蛋,不知道何位大佬能刷到。有点后怕了。
还有彩蛋啊?有意思咯哈哈
精神食粮嘛!据说80%男人的博客都有小姐姐视频
看来我和旺东大佬是在同一正营,有空还得在多挖掘点新资源!
之前还有18+的api 现在基本全封完了!
怪只可惜的,我都没看过。早点认识旺东大佬就好了。
福利时代一去不回了!
为了一个美女,也是拼了个命
太有精力折腾了皮哥
哈哈,就这点爱好了打发时间,没条件和你一样可以外出旅游!尴尬了~
皮哥又低调了
过个把月要广东中山三日游,要不要约下江边钓鱼。去年我可钓到不少大货。
我要看到时候有没时间过去呢