幾天前同事給我看了一個特效,是一個拼圖遊戲,不同的是,拼圖裡的是動畫。他要我看做個DEMO,於是就自己整了一會,也確實不難。用canvas很容易做。所以這篇博文不適合高手看。 。 。 。就是隨便寫來玩玩的。
效果圖:
至少我剛看到這個的時候覺得挺新穎的,所以才會想到做出來玩玩,覺得樓主out的哥們請輕噴
不多說,先上DEMO:影片拼圖 (或許要等一會才能看到效果,我是直接在w3school那裡搞了個影片連結過來的,拖曳什麼的都做的很簡單,或許還有些bug,畢竟就只是做一個DEMO玩玩而已,說說原理就行了),還有一點,直接把視頻的當前幀畫到canvas中在移動設備上好像還不支持。 。 。至少我用ipad看了一下,發現畫不上去,如果有知道腫麼解決這問題的大牛請為小弟解答一下,不甚感激
原理:每一塊拼圖就是一個canvas,同時還需要一個離屏canvas。先整一個video標籤
並且把video隱藏掉,然後播放影片的時候把每一幀都畫到離屏canvas中(離屏canvas就是隱藏了的canvas,用於保存資料),寫法很簡單:
ctx.drawImage(video 程式碼如下:
ctx.drawImage(video 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()> newTime = new Date();
if(newTime - lastTime > 30){
lastTime = newTime;
ctx.drawImage(video , 0 , 0 , vw , vh); canvas. (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("webkitRequestAnimation." {
webkitRequestAnimationFrame(animate);
}
else if("msRequestAnimationFrame" in window){
msRequestAnimationFrame(animate);
}
msRequestAnimationFrame(animate);
}
elsequestAnimation {
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. ".allCanvas"),<br /> vw = 600,<br /> vh = 400,<br /> canvass = [];
<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,列,行){<br /> this.x = x;<br /> this.y = y;<br /> this.w = w;<br /> 這個。 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 /> 行為: 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 /> window.onmousemove = function(e> }<br /> window.onmousemove = function(e> }<br /> window.onmousemove = function(e> }<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 newTime;<br /> ctx.drawImage(video , 0 00 , 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" 在視窗中){<br /> webkitRequestAnimationFrame(animate);<br /> }<br /> else if("msRequestAnimationFrame" 在視窗中){<br /> else if("msRequestAnimationFrame" 在視窗中){<br /> FrameReido); > }<br /> else if("mozRequestAnimationFrame" in window){<br /> mozRequestAnimationFrame(animate);<br /> }<br /> }
<p> video.play();</script>
initAnimate();