前提:工作涉及到IPTV机顶盒EPG开发业务,正常的IPTV机顶盒视频播放调用的是厂商封装的Mediaplayer组件,异于普通的video播放,渲染的视频窗口属于安卓系统底层渲染,和html页面元素不是一个层面,在文档流的下方,播放时会被dom元素遮挡。想正确的播放视频必须在视频区域处保持dom文档流完全透明才可以,所以用到了canvas解决方案,在此记录。
传统正常操作
传统EPG页面会在生成背景图时,预留好视频播放的窗口,简而言之就是做一个局部透明的PNG图片,当作底图,类似于下面这样:
弊端:固定编排,太过死板,限制视频播放区域。
因为本人开发的EPG页面非固定排版,为后台管理系统智能编排,所以EPG页面完全灵活可配,任何地方都有可能为视频播放区域,传统的解决方案无法满足此需求。
解决方案
设置一个img标签,引入背景图,调用视频播放的时候把图片转为canvas进行局部透明(抠图),在视频播放完毕后还原背景图。
注:css代码忽略
<img id="imgurl" src="xxx.jpg" />
<script>
var bg = document.getElementById("imgurl");
// 当调用视频播放,开始抠图
bg2canvas(bg, 30, 40, 200, 160);
function bg2canvas(bg, left, top, width, height){
var canvas = document.createElement("canvas");
canvas.width = 1280;
canvas.height = 720;
var content = canvas.getContext("2d");
content.drawImage(bg, 0, 0);
var imgData = content.getImageData(left, top, width, height);
for (var i = 0, len = imgData.data.length; i < len; i += 4) {
// 改变每个像素的透明度
imgData.data[i + 3] = 0;
}
content.putImageData(imgData, left, top);
bg.src = canvas.toDataURL();
bg.onload = undefined;
}
// 当视频播放结束
bg.src = "xxx.jpg";
</script>
弊端:有些性能不好的机顶盒在执行的过程中极为缓慢,调查发现在执行透明循环以及canvas.toDataURL()过程中消耗时间过长
优化bg2canvas()方法1
查询canvas文档发现canvas变透明可以调用clearRect() API
function bg2canvas(bg, left, top, width, height){
var canvas = document.createElement("canvas");
canvas.width = 1280;
canvas.height = 720;
var content = canvas.getContext("2d");
content.drawImage(bg, 0, 0);
// 删除
/* var imgData = content.getImageData(left, top, width, height);
for (var i = 0, len = imgData.data.length; i < len; i += 4) {
// 改变每个像素的透明度
imgData.data[i + 3] = 0;
}
content.putImageData(imgData, left, top); */
content.clearRect(left, top, width, height); /* 新增 */
bg.src = canvas.toDataURL();
bg.onload = undefined;
}
弊端:确实节约了一部分性能问题,但是canvas.toDataURL()方法依旧消耗过长时间。
优化bg2canvas()方法2
既然最后一步转为图片消耗性能那就索性不转图片,直接在页面加载时就渲染呈现canvas形式的图形。
<canvas id="canvas"></canvas>
<script>
// 渲染canvas图形
var oimg = new Image();
oimg.src = "../pic/d/7b9ded875fac44208b8f9e5e90c8a21d.JPG";
var cvs = document.querySelector("#canvas");
var context = cvs.getContext("2d");
oimg.onload = function () {
cvs.width = 1280;
cvs.height = 720;
context.drawImage(this, 0, 0, 1280, 720);
};
// 当视频播放时,抠图
context.clearRect(30, 40, 200, 160);
</script>