• 用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             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>
  • 相关阅读:
    javascript计算两个时间差
    angular 倒计时15 minute的方法封装
    一个页面多个倒计时的封装
    网站倒计时
    angularjs定时任务的设置与清除
    浏览器Event Loop 是个什么鬼
    一个图片测试的小网站:dummyimage.com
    在vscode 一行的末尾按下tab键 快速生成代码 很爽
    VSCODE 快捷键
    weex 在iOS 平台上的整合
  • 原文地址:https://www.cnblogs.com/axes/p/3509290.html
Copyright © 2020-2023  润新知