HTML5之创新的视频拼图剖析式学习之二
昨天我们剖析了一下翻阅体验的实现。今天要剖析另外一个很有意思的效果——视频拼图。
网站中第一部分第二页《月熊的标志》是月熊志中互动性较强的一页,页面上会随机分布9块视频碎片,用户可以通过鼠标或者触控移动碎片完成拼图。
在这个Demo中,我们需要引用2个JavaScript库,jQuery和Hammer.js。
Hammer.js 是一个手势触控JS库,能够为网页加入Tap、Swipe、Drag等事件,并且同时支持鼠标和触控输入,免去自己监听事件和判断浏览器兼容等问题。
建立九宫格
首先,我们在页面中建立一个九宫格:
HTML:
<div id="puzzle">
<div class="container"><i></i></div>
…
<div class="container"><i></i></div>
</div> CSS:
#puzzle {
position: absolute;
top: 50%;
left: 38%;
margin-top: -190px;
width: 678px;
height: 381px;
} #puzzle .container {
float: left;
width: 226px;
height: 127px;
} #puzzle .container i {
display: block;
margin: 4px;
width: 218px;
height: 119px;
background: #fff;
}
每个宫格(.container)的大小是226*127,其中白色部分(.container i)是218*119。
插入视频
接着我们在页面中插入视频,我们使用HTML5 中新增的Video标签,并且为了兼容多数浏览器,使用了2种格式的视频源,然后设置视频为自动播放(Autoplay)和循环播放(Loop),视频源的大小建议和九宫格保持一致:
HTML:
<video width="678" height="381" id="video" autoplay loop>
<source src="../video/findjasper.mp4" type="video/mp4">
<source src="../video/findjasper.ogv" type="video/ogg; codecs='theora, vorbis'">
</video>
最后把视频隐藏起来,在幕后默默的运行即可:
CSS:
#video {
display: none;
}
创建视频碎片
视频碎片本身是一个个canvas元素,通过JS将Video的帧画面分块循环绘制到canvas上。
JS:
//为数组添加随机打乱方法
Array.prototype.shuffle = function () {
var l = this.length,
i = l;
while (i--) {
var p = parseInt(Math.random() * l),
t = this[i];
this[i] = this[p];
this[p] = t;
};
return this;
};
//随机函数,随机返回min~max中的任一数值
function random(min, max) {
return parseInt(Math.random() * (max - min + 1) + min);
};
上面的JS方法/函数接下来会用到。
S:
var PIECE_WIDTH = 226,
PIECE_HEIGHT = 127,
$body = $("body"),
video = $("#video")[0],
$puzzle = $("#puzzle"),
$puzzleItems = $puzzle.find(".container"),
zIndex = 2,
ctxs = [],
rndArray = [0, 1, 2, 3, 4, 5, 6, 7, 8].shuffle();
以上是会用到的变量,其中需要特别说明的是zIndex用来保存碎片的z-index值,ctxs用来保存碎片的canvas上下文,rndArray是一个0~8的随机数组。
JS:
//循环创建碎片
for (var i = 0; i <; i++) {
var index = rndArray[i], //分配随机位置
piece = document.createElement("canvas"); //创建canvas元素 piece.className = "piece";
piece.width = PIECE_WIDTH;
piece.height = PIECE_HEIGHT;
ctxs.push(piece.getContext("2d")); //把上下文push到ctxs数组,方便绘制时调用 //使用random函数给碎片设置一个随机的位置
//使用css3 transform旋转碎片角度,使拼图更加真实
//最后把碎片所对应的宫格(.container)保存到data("container")中
$(piece).css({
left: random(50, window.innerWidth - PIECE_WIDTH),
top: random(50, window.innerHeight - PIECE_HEIGHT),
transform: "rotate(" + random(-25, 25) + "deg)"
}).data("container", $puzzleItems.eq(index)).appendTo($body);
};
目前并没有限制碎片出现的位置,所以碎片可能会遮盖页面上的文字,你可以自己加以完善。
如果现在运行页面,你就能看到页面上出现的随机碎片了,但是由于还没有把视频绘制到页面上,所以只能看到黑色。
绘制视频碎片
绘制视频到canvas其实十分简单,主要用到的是canvas的drawImage方法。
drawImage方法接收9个参数。
context.drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight)
image指向要使用的来源,可以是图片、视频或者Canvas元素,
sourceX和sourceY指image上绘制的左上角坐标,
sourceWidth 和 sourceHeight指从image上要绘制的宽和高,
destX和destY表示将image绘制到画布上的左上角坐标,
destWidth 和destHeight表示绘制到画布上的宽和高。
看文字的话可能比较难懂,看下面这张图应该能帮助你理解:
我们创建一个drawVideo函数绘制视频
JS:
function drawVideo() {
for (var i = 0; i <; i++) {
var index = rndArray[i], //当前碎片位置
row = Math.floor(index / 3), //因为宫格是3x3的,所以用取余数获取行数
col = Math.floor(index % 3); //与3取模获得列数
ctxs[i].drawImage(video, (col * PIECE_WIDTH), (row * PIECE_HEIGHT), PIECE_WIDTH, PIECE_HEIGHT, 0, 0, PIECE_WIDTH, PIECE_HEIGHT); //row和col分别乘以宫格的宽高就是要从视频上绘制的左上角坐标
};
};
setInterval(drawVideo, 50);
然后调用setInterval每隔50毫秒循环绘制。
处理拖拽操作
hammer.js的事件对象添加一个gesture对象,里面保存了关于此次操作的相关信息,比如移动距离、移动速率、移动角度、持续时间等。
我们先创建3个函数,对应拖拽过程中的3个事件。
开始拖拽碎片时,加上.dragging(添加box-shadow),并设置更高一层的z-index保证在所有碎片之上,最后保存当前的位置到data("offset")中。
function dragStart(){
var $piece = $(this);
$piece.addClass("dragging").css("z-index", zIndex++).data("offset", $piece.offset());
};
在拖拽碎片时,只需要给之前保存的offset加上移动距离(deltaX/ deltaY),就是现在的正确位置。
function drag(event){
var $piece = $(this),
pieceOffset = $piece.data("offset");
$piece.css({
left: pieceOffset.left + event.gesture.deltaX,
top: pieceOffset.top + event.gesture.deltaY
});
};
最后拖拽结束,移除dragging类。
如果碎片的中心点在对应的宫格内部,就移动的宫格内,并关闭hammer。
如果九宫格内有9块碎片,就完成拼图了!
function dragEnd(event){
var $piece = $(this),
pieceOffset = $piece.data("offset"); $piece.removeClass("dragging"); var centerX = pieceOffset.left + event.gesture.deltaX + PIECE_WIDTH / 2,
centerY = pieceOffset.top + event.gesture.deltaY + PIECE_HEIGHT / 2,
$container = $piece.data("container"),
containerOffset = $container.offset(); if (centerX > containerOffset.left && (centerX < containerOffset.left + PIECE_WIDTH) && centerY > containerOffset.top && centerY < (containerOffset.top + PIECE_HEIGHT)) {
$container.prepend($piece.removeAttr("style").data("hammer").off());
if ($puzzle.find(".piece").length == 9) {
// bingo.
};
};
}; $(".piece").hammer({
prevent_default: true
}).on("dragstart", dragStart).on("drag", drag).on("dragend", dragEnd);
最后初始化碎片并绑定函数到对应的事件上,这个互动小游戏就完成了。
其实,网站上还有很多特效的制作,大家可以自己前去体验:http://moonbear.animalsasia.org/ie/。希望本文能给大家带来一些灵感,运用到自己的网站开发上面去。
HTML5之创新的视频拼图剖析式学习之二的更多相关文章
- HTML5之CSS3 3D transform 剖析式学习之一
最近坐地铁发现“亚洲动物基金”在地铁上做了很多公益广告,比较吸引人的是一个月熊的广告.做的很可爱.回去就搜了一下,发现这个网站是HTML5做的,非常炫. 所以想学习一下,方法就是传统的学习办法,模仿. ...
- 用Canvas做视频拼图
声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 几天前同事给我看了一个特效,是一个拼图游戏,不同的是,拼图里的是动画.他让我看下做个DEMO,于是就自己整了一会,也确实不难.用canva ...
- LiveVideoStackCon2021 北京站专访:从上云到创新,视频云的新技术、新场景
伴随着视频技术的进步和标准的迭代,视频产业从模拟进入到数字时代,完成了从电影电视到互联网的媒介转换,并且衍生出了超高清.3D.AR/VR 等多种创新形态.特别是在后疫情的当下,我们可以看到音视频技术领 ...
- 关于有偿提供拼图响应式后台的通知---------pintuer ui的官方通知(www.pintuer.com)
拼图响应式前端框架版响应式后台正式发布. 考虑到目前拼图的状况,我们不打算免费开放下载,但也不会收各位朋友1分钱,该版后台将有偿提供给各位给予拼图贡献的朋友. 废话不多说,一切皆以有图有真相,下面上图 ...
- 浅谈html5网页内嵌视频
更好的阅读体验:浅谈html5网页内嵌视频 如今在这个特殊的时代下:flash将死未死,微软和IE的历史问题,html5标准未定,苹果和谷歌的闭源和开源之争,移动互联网的大势所趋,浏览器各自为战... ...
- html5 video微信浏览器视频不能自动播放
html5 video微信浏览器视频不能自动播放 一.微信浏览器(x5内核): 1.不能自动播放 2.全屏 3.最顶层(z层的最顶层) 二.ios系统解决方案:(无phone手机未测试) <au ...
- html5-7 html5语义标签和视频
html5-7 html5语义标签和视频 一.总结 一句话总结:设计网站的时候要兼顾早期浏览器的话,最新技术要缓着用,自己可以先尝试. 1.html5所有标签共有属性有哪四种? 1.id2.clas ...
- HTML5全屏背景视频与 CSS 和 JS(插件或库)
译文原链接:http://codetheory.in/html5-fullscreen-background-video/ 前言: 当网页载入时,自动播放的全屏背景视频已经成为当前颇受欢迎的趋势. 就 ...
- HTML5与CSS3基础教程第八版学习笔记16-21章
第十六章,表单 HTML5引入了新的表单元素.输入类型和属性,以及内置的对必填字段.电子邮件地址.URL以及定制模式验证. 元素: <input type="email"&g ...
随机推荐
- my_strcmp()
void my_strcmp(const char* s1,const char* s2){ int i=0; while(*(s1+i)!='\0'||*(s2+i)!='\0'){ if(*(s1 ...
- ubuntu下eclipse scala开发插件(Scala IDE for Eclipse)安装
1. 环境介绍 系统:ubuntu16.04(不过和系统版本关系不大) elipse:Neon.1aRelease (4.6.1) 2. 插件介绍 Scala IDE for eclipse是elip ...
- 3.10.17 procfs示例
/* * wesley * the linux module sample of procfs * * wesley for testing * 2013-12-23 ...
- js实现打开网页自动弹出添加QQ好友邀请窗口
我们有时进一些网面或专题页面会自动弹出一个加为好友的对话框了,在研究了很久之后发现可以直接使用js来实现,下面我们一起来看js实现打开网页自动弹出添加QQ好友邀请窗口的方法. 第一步.JS脚本 这个是 ...
- 谁在死锁Mutex——用Windbg查找Mutex死锁所有者线程
Who is blocking that Mutex? - Fun with WinDbg, CDB and KD 05 Aug 2006 By Ingo Rammer I'm currently t ...
- UART Explained(转载)
做嵌入式开发,UART几乎是必不可少的,调试串口.GPS.GPRS.Bluetooth等模块很多都是用的UART接口.时下火热的IoT也不乏UART的身影,串口的BLE.WIFI.Zigbee.Lor ...
- NOIP2010乌龟棋[DP 多维状态]
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...
- NOIP2004合并果子
题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...
- 手机开启HDR后拍照有什么不同?
转自http://www.leiphone.com/news/201406/hdr-pic.html HDR这词大家可能并不陌生,但大部分人只是听过而已,在脑子并没有太多的概念,可能只是简单的认为HD ...
- Nginx反向代理、负载均衡、页面缓存、URL重写及读写分离详解
大纲 一.前言 二.环境准备 三.安装与配置Nginx 四.Nginx之反向代理 五.Nginx之负载均衡 六.Nginx之页面缓存 七.Nginx之URL重写 八.Nginx之读写分离 注,操作系统 ...