前言
最近用uniapp在做一个播放视频截图的功能,第一个当然想到了video组件。可是翻遍这货竟然没有支持截图的API。一番操作下来,用uniapp肯定是无法实现这个功能了,那我们能不能曲线救国方案实现了?当然是可以的,不然就不会有本篇文章出现了,这里以播放uniapp官方的视频为例,先上图镇楼:
思路
先讲下思路,uniapp没有给我们提供视频截图的api,但是使用浏览器提供的drawImage方法能实现video截图,但是前提是必须使用html中的VIDEO标签。然后再使用uniapp提供的renderjs配合dom操作来完成视频截图功能。
实现
首先是页面元素,很简单这里不做过多解释
<template>
<view>
<!--VIDEO标签父元素-->
<view id="videop"></view>
<image id="myImg" :src="shot" style="width: 100%;height: 200px;"></image>
<!--这里的test对应renderjs中的module取值-->
<button @click="test.onClick">截图</button>
</view>
</template>
然后我们看下renderjs实现部分,逻辑参考注释
<script module="test" lang="renderjs">
let width,height
export default {
mounted() {
width = uni.getSystemInfoSync().screenWidth
height = 200
console.log('mounted')
var src = "https://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/%E7%AC%AC1%E8%AE%B2%EF%BC%88uni-app%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D%EF%BC%89-%20DCloud%E5%AE%98%E6%96%B9%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B@20200317.mp4"
//通过dom操作创建一个html VIDEO标签并设置好相关参数
var x = document.createElement("VIDEO");
x.setAttribute("id", "videoplayer");
x.setAttribute("width", width);
x.setAttribute("height", height);
x.setAttribute("controls", "controls");
x.setAttribute("autoplay", "true");
x.setAttribute("src", src);
//加入到页面id为videop的元素中
document.getElementById('videop').appendChild(x)
},
methods: {
//页面元素截图按钮点击事件
onClick(event, ownerInstance) {
//通过dom创建一个canvas
var canvas = document.createElement("canvas");
canvas.setAttribute("width", width);
canvas.setAttribute("height", height);
var canvasCtx = canvas.getContext("2d");
//获取页面中的VIDEO标签
var video = document.querySelector("#videoplayer")
//坐原图像的x,y轴坐标,大小,目标图像的x,y轴标,大小。
canvasCtx.drawImage(video, 0, 0, video.width, video.height);
//把图标base64编码后变成一段url字符串
var dataUrl = canvas.toDataURL("image/png");
//调用页面methods中的updateimg方法,将图片base64地址传递
ownerInstance.callMethod('updateimg', {
dataUrl: dataUrl
})
}
}
}
</script>
接下来看下页面methods中的updateimg方法
...
methods: {
updateimg(obj){
//获取图片地址,并显示到页面的img标签上,然后将base64图片保存到相册
this.shot = obj.dataUrl
const bitmap = new plus.nativeObj.Bitmap("test");
bitmap.loadBase64Data(obj.dataUrl, function() {
const url = "_doc/" + new Date().getTime() + ".png"; // url为时间戳命名方式
bitmap.save(url, {
overwrite: true, // 是否覆盖
quality: 100 // 图片清晰度
}, (i) => {
uni.saveImageToPhotosAlbum({
filePath: url,
success: function() {
uni.showToast({
title: '图片保存成功',
icon: 'none'
})
bitmap.clear()
}
});
}, (e) => {
uni.showToast({
title: '图片保存失败',
icon: 'none'
})
bitmap.clear()
});
}, (e) => {
uni.showToast({
title: '图片保存失败',
icon: 'none'
})
bitmap.clear()
});
}
}
...
实现代码到这里基本就完成了,代码算是比较简单,但是思路确实另辟蹊径,有兴趣的可以跑跑看,唯一的缺点是截图的大小不跟随视频的分辨率而是跟你VIDEO的大小一样,VIDEO设置的太小可能导致图片不清晰。
尾巴
今天的内容相对来说比较简单,但是特别要注意这种方式只适用于APP。
老规矩,喜欢我的文章,欢迎给我点赞,评论,关注,谢谢大家!