代码改变世界

Canvas+Video打造酷炫播放体验

2011-11-21 08:32 【当耐特】 阅读(...) 评论(...) 编辑 收藏

image

一.简介

直到现在,仍然不存在一项旨在网页上显示视频的标准。

今天,大多数视频是通过插件(比如 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);

 

 

五.在线演示

00:00 /

 

 

 

 

 

 

 

 

六.代码下载

<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>

 

 

七.同步更新

本文已同步更新至:

HTML5实验室【目录】:   http://www.cnblogs.com/iamzhanglei/archive/2011/11/06/2237870.html