用Canvas做視頻拼圖


  聲明:本文為原創文章,如需轉載,請注明來源WAxes,謝謝!

  幾天前同事給我看了一個特效,是一個拼圖游戲,不同的是,拼圖里的是動畫。他讓我看下做個DEMO,於是就自己整了一會,也確實不難。用canvas很容易做。所以這篇博文不適合高手看。。。。就是隨便寫來玩玩的。

  效果圖:。。。至少我剛看到這個的時候覺得挺新穎的,所以才會想到做出來玩玩,覺得樓主out的哥們請輕噴

  不多說,先上DEMO:視頻拼圖  (或許要等一會才能看到效果,我是直接在w3school那里搞了個視頻鏈接過來的,拖動什么的都做的很簡單,或許還有些bug,畢竟就只是做一個DEMO玩玩而已,說說原理就行了),還有一點,直接把視頻的當前幀畫到canvas中在移動設備上好像還不支持。。。至少我用ipad看了一下,發現畫不上去,如果有知道腫么解決這問題的大牛請為小弟解答一下,不甚感激

  原理:每一塊拼圖就是一個canvas,同時還需要一個離屏canvas。先整一個video標簽

<video id="video" src="http://www.w3school.com.cn/example/html5/mov_bbb.mp4" width="600px" height="400px" controls="control" loop="loop" style="display:block;position:absolute;top:-6000px;"></video>

並且把video隱藏掉,然后播放視頻的時候把每一幀都畫到離屏canvas中(離屏canvas就是隱藏了的canvas,用於保存數據),寫法很簡單:

ctx.drawImage(video , 0 , 0 , vw , vh);

,直接用drawImage方法畫上去就行了。為何要先用離屏canvas呢,因為如果直接把每一幀數據同時畫到所有拼圖塊的canvas中,瀏覽器會瞬間崩掉。所以用一個離屏canvas作為緩沖。先把當前幀的數據保存到canvas,然后再將canvas畫到作為拼圖塊的canvas中。將canvas畫到canvas中也很簡單,也是用drawImage就可以搞定:

ctx2.drawImage(cs , -this.cols*this.w , -this.rows*this.h , vw , vh);

然后。。。。原理就這么簡單,之后提醒一點,用requestAnimationFrame循環取幀時,要限一下速,例如下面所寫的,我是每30毫秒取一次,推薦30~50毫秒,太低瀏覽器容易崩潰,太高的話視頻出現卡幀現象了:

 1 function animate(){
 2             var newTime = new Date();
 3             if(newTime - lastTime > 30){
 4                 lastTime = newTime;
 5                 ctx.drawImage(video , 0 , 0 , vw , vh);
 6                 canvases.forEach(function(){
 7                     var ctx2 = this.cas.getContext('2d');
 8                     ctx2.drawImage(cs , -this.cols*this.w , -this.rows*this.h , vw , vh);
 9                 });
10             }
11             if("requestAnimationFrame" in window){
12                 requestAnimationFrame(animate);
13             }
14             else if("webkitRequestAnimationFrame" in window){
15                 webkitRequestAnimationFrame(animate);
16             }
17             else if("msRequestAnimationFrame" in window){
18                 msRequestAnimationFrame(animate);
19             }
20             else if("mozRequestAnimationFrame" in window){
21                 mozRequestAnimationFrame(animate);
22             }
23         }

最后貼出所有代碼:

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  3 <head>
  4     <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  5     <style>
  6         body{margin:0;padding:0;}
  7         .allCanvas{
  8             position: relative;
  9             margin:50px auto;
 10             width:600px;
 11         }
 12         .vcanvas{
 13             position: absolute;
 14             display: block;
 15             border: 1px solid;
 16         }
 17     </style>
 18     <title>視頻拼圖</title>
 19 </head>
 20 <body>
 21     <div class="allCanvas">
 22         <canvas id="liping" width="600" height="400" style="display:none"></canvas>
 23     </div>
 24     <video id="video" src="http://www.w3school.com.cn/example/html5/mov_bbb.mp4" width="600px" height="400px" controls="control" loop="loop" style="display:block;position:absolute;top:-6000px;"></video>
 25     <script>
 26         var video = document.getElementById("video");
 27         var cs = document.getElementById("liping");
 28         var ctx = cs.getContext('2d')
 29         var rows = 3,
 30             cols = 3,
 31             cb = document.querySelector(".allCanvas"),
 32             vw = 600,
 33             vh = 400,
 34             canvases = [];
 35 
 36         function createCanvas(){
 37             var num = rows*cols;
 38             for(var i=0;i<cols;i++){
 39                 for(var j=0;j<rows;j++){
 40                     var canvas = new vCanvas(Math.random()*600, Math.random()*600 , vw/rows , vh/cols , j , i);
 41                     canvases.push(canvas);
 42                 }
 43             }
 44         }
 45 
 46         var vCanvas = function(x,y,w,h,cols,rows){
 47             this.x = x;
 48             this.y = y;
 49             this.w = w;
 50             this.h = h;
 51             this.cols = cols;
 52             this.rows = rows;
 53             this.creat();
 54             this.behavior();
 55         }
 56         vCanvas.prototype = {
 57             creat:function(){
 58                 this.cas = document.createElement("canvas");
 59                 cb.appendChild(this.cas);
 60                 this.cas.className = "vcanvas";
 61                 this.cas.id = "vc_"+(this.cols+1)*(this.rows+1);
 62                 this.cas.style.left = this.x+"px";
 63                 this.cas.style.top = this.y+"px";
 64                 this.cas.width = this.w;
 65                 this.cas.height = this.h;
 66             },
 67             behavior:function(){
 68                 this.cas.onmousedown = function(e){
 69                     e = e || window.event;
 70                     var that = this;
 71                     var om = {
 72                         x:e.clientX,
 73                         y:e.clientY
 74                     }
 75                     window.onmousemove = function(e){
 76                         e = e || window.event;
 77                         var nm = {
 78                             x:e.clientX,
 79                             y:e.clientY
 80                         }
 81                         that.style.left = parseInt(that.style.left.replace("px","")) + (nm.x-om.x) + "px";
 82                         that.style.top = parseInt(that.style.top.replace("px","")) + (nm.y-om.y) + "px";
 83                         om = nm;
 84                     }
 85                     window.onmouseup = function(){
 86                         this.onmousemove = null;
 87                     }
 88                 }
 89             }
 90         }
 91 
 92         Array.prototype.forEach = function(callback){
 93             for(var i=0;i<this.length;i++){
 94                 callback.call(this[i]);
 95             }
 96         }
 97 
 98         var lastTime = 0;
 99         function initAnimate(){
100             lastTime = new Date();
101             createCanvas();
102             animate();
103         }
104 
105         function animate(){
106             var newTime = new Date();
107             if(newTime - lastTime > 30){
108                 lastTime = newTime;
109                 ctx.drawImage(video , 0 , 0 , vw , vh);
110                 canvases.forEach(function(){
111                     var ctx2 = this.cas.getContext('2d');
112                     ctx2.drawImage(cs , -this.cols*this.w , -this.rows*this.h , vw , vh);
113                 });
114             }
115             if("requestAnimationFrame" in window){
116                 requestAnimationFrame(animate);
117             }
118             else if("webkitRequestAnimationFrame" in window){
119                 webkitRequestAnimationFrame(animate);
120             }
121             else if("msRequestAnimationFrame" in window){
122                 msRequestAnimationFrame(animate);
123             }
124             else if("mozRequestAnimationFrame" in window){
125                 mozRequestAnimationFrame(animate);
126             }
127         }
128 
129         video.play();
130         initAnimate();
131     </script>
132 </body>
133 </html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM