Canvas+Video打造酷炫播放體驗
2011-11-21 08:32 【當耐特】 閱讀(17322) 評論(19) 收藏 舉報
一.簡介
直到現在,仍然不存在一項旨在網頁上顯示視頻的標準。
今天,大多數視頻是通過插件(比如 Flash)來顯示的。然而,并非所有瀏覽器都擁有同樣的插件。
HTML5 規定了一種通過 video 元素來包含視頻的標準方法。如:
<video src="movie.ogg" controls="controls"> </video>
二.Canvas+Video
HTML5中引入新的元素canvas,其drawImage 方法允許在 canvas 中插入其他圖像( img 和 canvas 元素) 。
drawImage函數有三種函數原型:
drawImage(image, dx, dy)
drawImage(image, dx, dy, dw, dh)
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
第一個參數image可以用HTMLImageElement,HTMLCanvasElement或者HTMLVideoElement作為參數。
dx和dy是image在canvas中定位的坐標值;dw和dh是image在canvas中即將繪制區域(相對dx和dy坐標的偏移量)的寬度和高度值;
sx和sy是image所要繪制的起始位置,sw和sh是image所要繪制區域(相對image的sx和sy坐標的偏移量)的寬度和高度值。
所以這使酷炫播放體驗有了實現的可能。
三.理解canvas.translate和canvas.scale
很多人對于canvas.translate(x,y)的理解有的錯誤,之前一直以原點(0,0)為基準點,作用就是移動原點,默認的原點(0,0)是在屏幕左上角的,你可以通過translate(x,y)把點(x,y)作為原點,就一直以為這個(x,y)就是新的坐標原點。但看一下API就會知道,這種理解是不對的,
不過API確實容易誤導大家:
view plain public void translate (float dx, float dy) Since: API Level 1 Preconcat the current matrix with the specified translation Parameters dx The distance to translate in X dy The distance to translate in Y
其實是原來的原點分別在x軸和y軸偏移多遠的距離,然后以偏移后的位置作為坐標原點。也就是說原來在(100,100),然后translate(1,1)新的坐標原點在(101,101)而不是(1,1)
canvas.scale:
canvas.scale提供了放大縮小倒置等功能。比如Y倒置:canvas.scale(1,-1)
四.核心代碼
canvas.setAttribute('height', Math.floor(video.height));
canvas.setAttribute('width', Math.floor(video.width));
ctx.translate(0, canvas.height );
ctx.scale(1, -1);
ctx.globalAlpha = 0.3;
ctx.drawImage(video, 0, 0, video.width, video.height, 0, -canvas.height/2, canvas.width, canvas.height);
五.在線演示
六.代碼下載
<html >
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div>
<video width="640" height="264">
<source src="http://video-js.zencoder.com/oceans-clip.mp4" >
<source src="http://video-js.zencoder.com/oceans-clip.webm" >
</video> <br/>
<canvas style="position:absolute; top:143px;"></canvas>
</div>
<div style="position:absolute; top:400px;">
<p>
<input type="button" id="play" value="play">
<span id="position">00:00</span> / <span id="duration"></span>
</p>
</div>
<script >
var addEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.addEventListener(type, fn, false);
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
} else {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.attachEvent('on' + type, function () { return fn.call(el, window.event); });
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
}
})();
</script>
<script>
var video = document.querySelector('video');
var togglePlay = document.querySelector('#play');
var position = document.querySelector('#position');
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
addEvent(togglePlay, 'click', function () {
video.playbackRate = 0.5;
if (video.paused) {
if (video.ended) video.currentTime = 0;
video.play();
this.value = "pause";
} else {
video.pause();
this.value = "play";
}
});
setInterval(function () {
position.innerHTML = asTime(video.currentTime);
ctx.drawImage(video, 0, 0, video.width, video.height, 0, -canvas.height / 2, canvas.width, canvas.height);
}, 1000 / 15);
addEvent(video, 'ended', function () {
togglePlay.value = "play";
});
addEvent(video, 'canplay', function () {
video.muted = true;
document.querySelector('#duration').innerHTML = asTime(this.duration);
startCanvas();
});
function startCanvas() {
canvas.setAttribute('height', Math.floor(video.height));
canvas.setAttribute('width', Math.floor(video.width));
ctx.translate(0, canvas.height );
ctx.scale(1, -1);
ctx.globalAlpha = 0.3;
ctx.drawImage(video, 0, 0, video.width, video.height, 0, -canvas.height/2, canvas.width, canvas.height);
}
function asTime(t) {
t = Math.round(t);
var s = t % 60;
var m = Math.round(t / 60);
return two(m) + ':' + two(s);
}
function two(s) {
s += "";
if (s.length < 2) s = "0" + s;
return s;
}
</script>
</body>
</html>
七.同步更新
本文已同步更新至:
浙公網安備 33010602011771號