Uniapp微信小程序视频全屏播放功能极简实现法

本文详细介绍了如何通过CSS的旋转和定位实现视频全屏播放功能,包括解决横屏和竖屏播放的问题,以及处理全屏模式下slider组件的交互难题。在横屏播放时,通过将视频旋转90度并调整定位,实现了屏幕填充。同时,对于无法正常拖动的slider,使用触摸事件模拟拖动和点击操作。文章还提供了一段关于处理滑动和点击事件的代码示例,帮助读者理解实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

*高端的食材,往往只需要最朴素的烹饪方式,本文用css旋转定位实现视频全屏播放,朴实无华,简单实用,本文为原创,分享请标明出处*

实习入职第三周,在经过两周的改bug和切图之后,组里说给我一个有挑战性的需求,做一个视频全屏播放的功能
在这里插入图片描述
在这里插入图片描述
简单来说,就是点击按钮,将视频全屏播放,宽高比例过1.8的横屏播放,小于1.8的仍然竖屏播放,就像下面这样
在这里插入图片描述
看完需求我的思考如下:
1.在原页面操作属实麻烦,需要点击全屏按钮跳转到新页面播放
2.由于需要保留侧边栏的点赞关注等功能,所以需要组件分离复用
3.由于存在横竖屏之分,所以跳转页面时需要传递视频宽高比,新页 面需要分别写出横屏和竖屏的css样式
开工:
项目中视频用的是uniapp的video组件,底部的滑动条用的是uniapp的slider组件,我于是乎我在uniapp的文档中查到一个属性
在这里插入图片描述
由于我们的项目将全屏按钮隐藏掉了,而且这个属性不能手动设置判断的宽高比,所以我选择弃用现有的轮子,另辟蹊径
有可能是前两周切图css写多了,一下就想到既然是横屏直接将视图旋转90度不久好了吗,于是我开始着手尝试
1.直接将视频顺时针旋转90度,并且将视频宽度改为100vh,高度改为100vw,使其充满整个屏幕

 	.full-page-video-horizontal {
 		width: 100vh;
 		height: 100vw;
 		transform: rotate(90deg);
 	}

效果如下
在这里插入图片描述
很明显,这里出现了中心点偏移的情况,css3旋转的中心点默认是元素的中心点,所以我们将宽高改变后元素的中心点由原来的(50vw,50vh)变成了(50vh,50vw),所以接下来要用相对定位将屏幕中心点(即整个元素)移回原来的坐标
在这里插入图片描述
复位

 	.full-page-video-horizontal {
 		width: 100vh;
 		height: 100vw;
 		transform: rotate(90deg);
      +  position: relative;
 	  +  right: calc(50vh - 50vw);
 	  +  top: calc(50vh - 50vw)
 	}

视频旋转完成了,接下来是对slider的处理,这里有一个大坑,因为我们直接将slider也旋转90度再复位到屏幕底部,但是因为uniapp的slider组件并没有给出相应的方向属性,所以在我们把视图旋转过来之后,虽然滑动条竖向显示了,但是它仍然只能横向拖动,简单来说就是:视图旋转了,逻辑没有跟着旋转
在这里插入图片描述
所以当横屏播放时,我们也弃用slider自带的拖动功能,使用touchstart和touchend替代拖动和点击事件
拖动开始,将当前的y坐标保存到状态:

touchStart(e) {
 				this.currentVideoContext.pause()
 				this.nowY = e.changedTouches[0].pageY
 			},

拖动结束,计算当前y和状态中y的差值,得出偏移量,计算偏移量和屏幕总高度的比,并等比移动进度条

		touchEnd(e) {
 				const {
 					windowWidth,
 					windowHeight
 				} = uni.getSystemInfoSync();
 				let sliderWidth = windowHeight * 0.85
 				let y = e.changedTouches[0].pageY
 				let dy = y - this.nowY
 				let value = dy / sliderWidth
 				const {
 					duration,
 					currentTime
 				} = this.progressTime;
 				const time = duration * (value + (currentTime / duration));
 				this.currentVideoContext.seek(time)
 				this.currentVideoContext.play()
 			},

模拟点击事件,即当拖动的距离足够小时,直接记录当前y坐标,获取视口高度,得出当前y坐标在整个视口的相对位置,并且把进度条调到整个进度条的同比相对位置

		tapSlider(e) {
 				const {
 					windowWidth,
 					windowHeight
 				} = uni.getSystemInfoSync();
 				let begin = windowHeight * 0.07
 				let y = e.changedTouches[0].pageY
 				let dy = y - begin
 				let rate = dy / (windowHeight * 0.85)
 				const {
 					duration,
 					currentTime
 				} = this.progressTime;
 				let time = duration * rate
 				this.currentVideoContext.seek(time)
 			},

PS:由于拖动进度条的时候视频仍处于播放中,进度状态不停的在更新,会导致拖动时有闪动的情况,所以需要在拖动开始时暂停视频,在拖动结束后再播放,但是uniapp的slider组件没有拖动开始的属性,只有sliderChanging,它会在拖动中高频率触发,所以我们写一个节流函数让它3秒只触发一次暂停视频,减少不必要的内存消耗

		//进度条拖拽节流
 			sliderChanging() {
 				if (this.t) return
 				this.t = setTimeout(() => {
 					this.t = null
 				}, 3000)
 				this.currentVideoContext.pause()
 			},

具体实现的一些细节需要各位自行写出代码编译尝试,祝大家学有所得

### 可能的原因分析 在 UniApp 小程序中遇到 `video` 标签无播放视频并呈现黑屏的情况,可能由以下几个因素引起: - **视频格式不兼容**:不同平台对于视频格式的支持存在差异。例如,在 Android 和 iOS 上并非所有常见格式都得到支持[^2]。 - **网络延迟或资源加载失败**:当视频文件过大或者服务器响应时间过长时,可能导致客户端长时间缓冲而最终未能成功渲染画面。 - **缺少必要的元数据信息**:某些情况下,特别是涉及到直播流媒体场景下(如RTMP协议),若初始化阶段缺乏关键帧(IDR Frame),则会造成短暂甚至持续性的黑屏现象[^4]。 ### 解决方案建议 针对上述提到的各种可能性,可以采取如下措施来尝试解决问题: #### 优化视频编码参数 确保所使用的视频素材已经按照目标平台上推荐的标准进行了转码处理。比如优先选用 MP4 容器封装 H.264 编解码方式制作的内容,因为这种组合几乎被所有的现代移动操作系统广泛接受和支持。 ```bash ffmpeg -i input.mp4 -c:v libx264 -preset veryfast output_optimized.mp4 ``` 此命令利用 FFmpeg 工具对原始视频进行重新压缩,并设置较快的速度预设以便快速完成转换过程而不牺牲太多质量。 #### 设置合理的缓存策略 为了改善用户体验以及减少因网速波动带来的影响,可以在 `<video>` 组件属性里指定合适的 preload 值,让浏览器提前下载部分数据以加快首桢显示速度;同时也要注意控制好最大带宽消耗以免给用户造成额外负担。 ```html <template> <view class="container"> <!-- 使用uni-app内置组件 --> <video id="myVideo" :src="videoSrc" controls webkit-playsinline playsinline preload="auto"></video> </view> </template> <script setup lang="ts"> import { ref } from 'vue'; const videoSrc = ref('https://example.com/path/to/video.mp4'); </script> ``` 这里设置了 `preload="auto"` 参数指示页面尽可能早地获取多媒体内容,从而有助于缓解初次打开时可能出现的卡顿状况。 #### 处理特殊场景下的黑屏情况 如果是基于 RTMP 协议构建的应用,则需特别关注如何高效捕获首个 I-frame 来启动后续的画面更新流程。可以通过调整服务端推流配置或是前端 SDK 初始化选项等方式加以改进。 另外值得注意的是,尽管本案例主要围绕着小程序环境展开讨论,但对于其他类型的 Web 应用同样具有一定的借鉴意义。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Feng Wuqian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值