几天前同事给我看了一个特效,是一个拼图游戏,不同的是,拼图里的是动画。他让我看下做个DEMO,于是就自己整了一会,也确实不难。用canvas很容易做。所以这篇博文不适合高手看。。。。就是随便写来玩玩的。
效果图:
至少我刚看到这个的时候觉得挺新颖的,所以才会想到做出来玩玩,觉得楼主out的哥们请轻喷
不多说,先上DEMO:视频拼图 (或许要等一会才能看到效果,我是直接在w3school那里搞了个视频链接过来的,拖动什么的都做的很简单,或许还有些bug,毕竟就只是做一个DEMO玩玩而已,说说原理就行了),还有一点,直接把视频的当前帧画到canvas中在移动设备上好像还不支持。。。至少我用ipad看了一下,发现画不上去,如果有知道肿么解决这问题的大牛请为小弟解答一下,不甚感激
原理:每一块拼图就是一个canvas,同时还需要一个离屏canvas。先整一个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毫秒,太低浏览器容易崩溃,太高的话视频出现卡帧现象了:
function animate(){
var newTime = new Date();
if(newTime - lastTime > 30){
lastTime = newTime;
ctx.drawImage(video , 0 , 0 , vw , vh);
canvases.forEach(function(){
var ctx2 = this.cas.getContext('2d');
ctx2.drawImage(cs , -this.cols*this.w , -this.rows*this.h , vw , vh);
});
}
if("requestAnimationFrame" in window){
requestAnimationFrame(animate);
}
else if("webkitRequestAnimationFrame" in window){
webkitRequestAnimationFrame(animate);
}
else if("msRequestAnimationFrame" in window){
msRequestAnimationFrame(animate);
}
else if("mozRequestAnimationFrame" in window){
mozRequestAnimationFrame(animate);
}
}
最后贴出所有代码:
视频拼图
<script><br /> var video = document.getElementById("video");<br /> var cs = document.getElementById("liping");<br /> var ctx = cs.getContext('2d')<br /> var rows = 3,<br /> cols = 3,<br /> cb = document.querySelector(".allCanvas"),<br /> vw = 600,<br /> vh = 400,<br /> canvases = [];
<p> function createCanvas(){<br /> var num = rows*cols;<br /> for(var i=0;i<cols;i++){<br /> for(var j=0;j<rows;j++){<br /> var canvas = new vCanvas(Math.random()*600, Math.random()*600 , vw/rows , vh/cols , j , i);<br /> canvases.push(canvas);<br /> }<br /> }<br /> }
<p> var vCanvas = function(x,y,w,h,cols,rows){<br /> this.x = x;<br /> this.y = y;<br /> this.w = w;<br /> this.h = h;<br /> this.cols = cols;<br /> this.rows = rows;<br /> this.creat();<br /> this.behavior();<br /> }<br /> vCanvas.prototype = {<br /> creat:function(){<br /> this.cas = document.createElement("canvas");<br /> cb.appendChild(this.cas);<br /> this.cas.className = "vcanvas";<br /> this.cas.id = "vc_"+(this.cols+1)*(this.rows+1);<br /> this.cas.style.left = this.x+"px";<br /> this.cas.style.top = this.y+"px";<br /> this.cas.width = this.w;<br /> this.cas.height = this.h;<br /> },<br /> behavior:function(){<br /> this.cas.onmousedown = function(e){<br /> e = e || window.event;<br /> var that = this;<br /> var om = {<br /> x:e.clientX,<br /> y:e.clientY<br /> }<br /> window.onmousemove = function(e){<br /> e = e || window.event;<br /> var nm = {<br /> x:e.clientX,<br /> y:e.clientY<br /> }<br /> that.style.left = parseInt(that.style.left.replace("px","")) + (nm.x-om.x) + "px";<br /> that.style.top = parseInt(that.style.top.replace("px","")) + (nm.y-om.y) + "px";<br /> om = nm;<br /> }<br /> window.onmouseup = function(){<br /> this.onmousemove = null;<br /> }<br /> }<br /> }<br /> }
<p> Array.prototype.forEach = function(callback){<br /> for(var i=0;i<this.length;i++){<br /> callback.call(this[i]);<br /> }<br /> }
<p> var lastTime = 0;<br /> function initAnimate(){<br /> lastTime = new Date();<br /> createCanvas();<br /> animate();<br /> }
<p> function animate(){<br /> var newTime = new Date();<br /> if(newTime - lastTime > 30){<br /> lastTime = newTime;<br /> ctx.drawImage(video , 0 , 0 , vw , vh);<br /> canvases.forEach(function(){<br /> var ctx2 = this.cas.getContext('2d');<br /> ctx2.drawImage(cs , -this.cols*this.w , -this.rows*this.h , vw , vh);<br /> });<br /> }<br /> if("requestAnimationFrame" in window){<br /> requestAnimationFrame(animate);<br /> }<br /> else if("webkitRequestAnimationFrame" in window){<br /> webkitRequestAnimationFrame(animate);<br /> }<br /> else if("msRequestAnimationFrame" in window){<br /> msRequestAnimationFrame(animate);<br /> }<br /> else if("mozRequestAnimationFrame" in window){<br /> mozRequestAnimationFrame(animate);<br /> }<br /> }
<p> video.play();<br /> initAnimate();<br /> </script>