好久以前的了,那时html5刚出来不久吧,国外有人做了个用canvas来拼视频的游戏,觉得挺好玩的,就模仿了一下(模仿也是好久以前的事了)
---------------------
用到的东西:
1. html5 canvas标签
drawImage (视频源)
2. html5 video标签
source属性(为了浏览器兼容,需要多个视频来源)
3. JQuery
选择器
事件
4. js对象方法
----------------------
效果图:
------------------------
以下为乱七八糟的代码
1. html文件:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 5 <meta charset="utf-8"> 6 <meta http-equiv="charset" content="utf-8"> 7 <meta http-equiv="content-language" content="utf-8"> 8 <title>视频拼图</title> 9 <meta name="keywords" content="视频拼图"> 10 <meta name="description" content="视频拼图"> 11 <!--<link rel="shortcut icon" href="imgs/favicon.ico">--> 12 <!-- 外部css --> 13 <link rel="stylesheet" href="css/guess_style.css"> 14 <!-- 引用JQuery 库 --> 15 <script type="text/javascript" src="js/libs/jquery.js"></script> 16 </head> 17 <body> 18 <!-- html5 video Tag (hidden) --> 19 <div id="video"> 20 </div> 21 <!-- import the js file --> 22 <script type="text/javascript" src="js/me/guessWXS.js"></script> 23 <!-- import the paramater file --> 24 <script type="text/javascript" src="js/me/guessParmsWXS.js"></script> 25 <script type="text/javascript"> 26 //start the game 27 $(function () { 28 new guessWXS(options); 29 }); 30 </script> 31 </body> 32 </html>
2. guessWXS.js :
1 ; 2 var guessWXS = function (options) { 3 //定义变量,我也忘记那些没有用到,那些用到了,只怪那时不好好写注释!!!现在丢人现眼了。。。 4 this.options = options; // 接收参数 5 this.videoCtrlObj; 6 this.canvasLst = new Array(); 7 this.canvasDivLst = new Array(); 8 this.positionTop = new Array(); 9 this.positionLeft = new Array(); 10 this.eachHeight = 0; 11 this.eachWidth = 0; 12 this.wCount = 5; 13 this.hCount = 4; 14 this.canvasCount = this.wCount * this.hCount; 15 this.down = false; 16 this.befPageX; 17 this.befPageY; 18 this.oldLeft; 19 this.oldTop; 20 this.oldZIndex; 21 this.divObj = null; 22 this.start = false; 23 this.win = false; 24 this.wRate = 1; 25 this.hRate = 1; 26 this.doInit(); // 调用初期化方法 27 } 28 29 guessWXS.prototype.doInit = function () { 30 // 初期化方法 31 if ($(this.options.container).length > 0) { 32 var obj = this; 33 //video html 34 $(this.options.container).append(this.options.videoHtml); 35 //video attribute 36 var videoObj = $(this.options.container).find("video").eq(0); 37 $(videoObj).attr("id", this.options.id); 38 var videoObjJs = document.getElementById(this.options.id); 39 $(videoObj).hide(); // 隐藏video Tag (其实可以在js里处理好后,append 到画面的) 40 //calculate video and canvas 41 this.wRate = this.options.width / this.options.videoWidth; 42 this.hRate = this.options.height / this.options.videoHeight; 43 //video source 44 for (var i = 0; i < this.options.videoUrl.length; i++) { 45 videoObj.append("<source src='" + this.options.videoUrl[i] + "' />"); 46 } 47 //video control 48 var videoCtrl = document.getElementById(this.options.id); 49 this.videoCtrlObj = videoCtrl; 50 //canvas list 使用多个canvas来显示一个视频的各个部分(切割视频到canvas list) 51 var top = 0; 52 var left = 0; 53 var topStep = this.options.height / this.hCount; 54 var leftStep = this.options.width / this.wCount; 55 var c = 0; 56 var tempObj; 57 //console.log(topStep, leftStep); 58 for (var h = 0; h < this.hCount; h++) { 59 for (var w = 0; w < this.wCount; w++) { 60 tempObj = $(this.options.canvasHtml).css({ "position": "absolute", "top": (h % this.hCount) * topStep, "left": (w % this.wCount) * leftStep, "border": "0px red solid", "margin": 0, "overflow": "hidden" }); 61 tempObj.width(leftStep).height(topStep); 62 tempObj.find("canvas").attr("id", "canvasWXS_" + c); 63 $(this.options.container).append(tempObj); 64 this.canvasLst.push(document.getElementById("canvasWXS_" + c)); 65 this.canvasDivLst.push(tempObj); 66 this.eachHeight = topStep; 67 this.eachWidth = leftStep; 68 // 保存正确结果,用于判断游戏是否结束 69 this.positionTop.push((h % this.hCount) * topStep); 70 this.positionLeft.push((w % this.wCount) * leftStep); 71 c++; 72 } 73 } 74 // 对canvas 进行事件绑定 75 for (var i = 0; i < this.canvasDivLst.length; i++) { 76 this.canvasDivLst[i].bind("mousedown", function () { obj.doCanvasDivMouseDown(this); }); 77 this.canvasDivLst[i].bind("mouseup", function () { obj.doCanvasDivMouseUp(this); }); 78 this.canvasDivLst[i].bind("mousemove", function () { obj.doCanvasDivMouseMove(this); }); 79 } 80 //videoCtrl.play(); 81 // 绑定视频播放事件,调用doTimeUpdate方法 82 this.Bind(videoCtrl, "timeupdate", this.doTimeUpdate, this); 83 $("body").bind("mouseout", function () { 84 obj.down = false; 85 if (obj.divObj != null) { 86 $(obj.divObj).css({ "z-index": obj.oldZIndex, "box-shadow": "0px 0px 0px 0px #000", "border": "none" }); 87 $(obj.divObj).css({ "left": obj.oldLeft, "top": obj.oldTop }); 88 } 89 }); 90 $(this.options.container).bind("click", function () { obj.doPlay(); }); 91 // 一秒后执行,其实可以在视频加载完后或加载一部分后再执行的 92 setTimeout(function () { $(this.options.container).click();}, 1000); 93 } 94 }; 95 96 guessWXS.prototype.doTimeUpdate = function () { 97 // 将当前的video图片,切割更新至canvas list 98 var context; 99 var h = 0; 100 var w = 0; 101 var topStep = this.options.height / this.hCount; 102 var leftStep = this.options.width / this.wCount; 103 for (var i = 0; i < this.canvasLst.length; i++) { 104 context = this.canvasLst[i].getContext("2d"); 105 context.drawImage(this.videoCtrlObj, (w % this.wCount) * leftStep / this.wRate, (h % this.hCount) * topStep / this.hRate, leftStep / this.wRate, topStep / this.hRate, 0, 0, leftStep, topStep); 106 if ((i + 1) % this.wCount == 0) { 107 w = 0; 108 h++; 109 } else { 110 w++; 111 } 112 } 113 }; 114 115 guessWXS.prototype.doCanvasDivMouseDown = function (thisObj) { 116 // 鼠标按下,醒目标注当前的那块canvas 117 event.preventDefault(); 118 if (this.start && !this.down) { 119 this.befPageX = event.pageX; 120 this.befPageY = event.pageY; 121 this.oldTop = parseInt($(thisObj).css("top").replace(/px/g, "")); 122 this.oldLeft = parseInt($(thisObj).css("left").replace(/px/g, "")); 123 this.oldZIndex = $(thisObj).css("z-index"); 124 this.divObj = thisObj; 125 this.down = true; 126 $(thisObj).css({ "z-index": "999", "box-shadow": "0px 0px 20px 10px #fff" }); 127 } 128 event.stopPropagation(); 129 }; 130 131 guessWXS.prototype.doCanvasDivMouseUp = function (thisObj) { 132 // 替换两块canvas的位置 133 event.preventDefault(); 134 if (this.start && this.down) { 135 this.befPageX = 0; 136 this.befPageY = 0; 137 this.divObj = null; 138 this.down = false; 139 140 var tmpTop; 141 var tmpLeft; 142 var curTop = parseInt($(thisObj).css("top").replace(/px/g, "")) + this.eachHeight / 2; 143 var curLeft = parseInt($(thisObj).css("left").replace(/px/g, "")) + this.eachWidth / 2; 144 var backFlg = true; 145 for (var i = 0; i < this.positionTop.length; i++) { 146 147 if ( 148 (this.positionTop[i] <= curTop && this.positionTop[i] + this.eachHeight >= curTop) 149 && (this.positionLeft[i] <= curLeft && this.positionLeft[i] + this.eachWidth >= curLeft) 150 ) { 151 for (var j = 0; j < this.canvasDivLst.length; j++) { 152 tmpTop = parseInt($(this.canvasDivLst[j]).css("top").replace(/px/g, "")); 153 tmpLeft = parseInt($(this.canvasDivLst[j]).css("left").replace(/px/g, "")); 154 if (tmpTop == this.positionTop[i] && tmpLeft == this.positionLeft[i]) { 155 backFlg = false; 156 $(this.canvasDivLst[j]).css({ "left": this.oldLeft, "top": this.oldTop }); 157 $(thisObj).css({ "left": tmpLeft, "top": tmpTop }); 158 break; 159 } 160 } 161 } 162 if (!backFlg) { break; } 163 } 164 $(thisObj).css({ "z-index": this.oldZIndex, "box-shadow": "0px 0px 0px 0px #fff" }); 165 if (backFlg) { 166 $(thisObj).css({ "left": this.oldLeft, "top": this.oldTop }); 167 } 168 this.doJudge(); 169 } 170 event.stopPropagation(); 171 }; 172 173 guessWXS.prototype.doCanvasDivMouseMove = function (thisObj) { 174 // 移动canvas块 175 event.preventDefault(); 176 if (this.start && this.down) { 177 $(thisObj).css({ "top": event.pageY - this.befPageY + parseInt($(thisObj).css("top").replace(/px/g, "")), "left": event.pageX - this.befPageX + parseInt($(thisObj).css("left").replace(/px/g, "")) }); 178 this.befPageX = event.pageX; 179 this.befPageY = event.pageY; 180 } 181 event.stopPropagation(); 182 }; 183 184 guessWXS.prototype.doPlay = function () { 185 // 播放视频 186 if (!this.start || this.win) { 187 if (this.win) { 188 this.win = !this.win; 189 } else { 190 this.doRandom(); 191 this.videoCtrlObj.play(); 192 } 193 } 194 }; 195 196 guessWXS.prototype.doRandom = function () { 197 // 打乱canvas list 顺序 198 var num1, num2; 199 var tmpPositionT = new Array(); 200 var tmpPositionL = new Array(); 201 //准备初期化数据 202 for (var i = 0; i < this.canvasDivLst.length; i++) { 203 tmpPositionT.push(parseInt($(this.canvasDivLst[i]).css("top").replace(/px/g, ""))); 204 tmpPositionL.push(parseInt($(this.canvasDivLst[i]).css("left").replace(/px/g, ""))); 205 } 206 //进行随机 [对换] 207 console.log(tmpPositionT, tmpPositionL); 208 for (var i = 0; i < this.options.randomCount/*this.canvasDivLst.length*/; i++) { 209 num1 = 0; 210 num2 = 0; 211 while (num1 == num2) { 212 num1 = Math.round(Math.random() * (this.canvasDivLst.length - 1)); 213 num2 = Math.round(Math.random() * (this.canvasDivLst.length - 1)); 214 } 215 tmpPositionT[num1] = tmpPositionT[num1] + tmpPositionT[num2]; 216 tmpPositionT[num2] = tmpPositionT[num1] - tmpPositionT[num2]; 217 tmpPositionT[num1] = tmpPositionT[num1] - tmpPositionT[num2]; 218 tmpPositionL[num1] = tmpPositionL[num1] + tmpPositionL[num2]; 219 tmpPositionL[num2] = tmpPositionL[num1] - tmpPositionL[num2]; 220 tmpPositionL[num1] = tmpPositionL[num1] - tmpPositionL[num2]; 221 } 222 for (var i = 0; i < tmpPositionT.length; i++) { 223 $(this.canvasDivLst[i]).css({ "left": tmpPositionL[i], "top": tmpPositionT[i] }); 224 } 225 this.start = true; 226 }; 227 228 guessWXS.prototype.doJudge = function () { 229 // 判断是否正确 230 var winFlg = true; 231 for (var i = 0; i < this.canvasDivLst.length; i++) { 232 if ( 233 this.positionTop[i] != parseInt($(this.canvasDivLst[i]).css("top").replace(/px/g, "")) 234 || 235 this.positionLeft[i] != parseInt($(this.canvasDivLst[i]).css("left").replace(/px/g, "")) 236 ) { 237 winFlg = false; 238 } 239 } 240 if (winFlg) { 241 this.start = false; 242 this.down = false; 243 this.win = true; 244 alert("YOU WIN!,点击视频再玩一次"); 245 } 246 }; 247 248 guessWXS.prototype.Bind = function (control, eventName, callBack, scope) { 249 if (!scope) { scope = window; } 250 $(control).bind(eventName, function () { 251 callBack.apply(scope, arguments); 252 }); 253 };
3. guessParmsWXS.js (这个随意配置) :
1 var options = { 2 id: 'video1', 3 container: '#video', 4 videoHtml: "<video loop='loop'>Your browser does not support the video tag.</video>", // controls='controls' 5 canvasHtml: "<div><canvas></canvas></div>", 6 '640', 7 height: '360', 8 videoUrl: ['videos/BigBuckBunny_640x360.mp4', 'videos/BigBuckBunny_640x360.ogv'], //['videos/mov_bbb.ogg'], 9 videoWidth: "640", //320 10 videoHeight: "360", //175 11 randomCount: 20 12 };
4. guess_style.css (其实里面没有什么) :
1 body { 2 } 3 #video{width:640px; height:360px; margin:auto; /*background:green;*/ position:relative;}
CSDN下载:(可以单机运行,不需要服务器)