用HTML5做拼图效果,【开发教程】HTML5网页内的视频拼图特效

【开发教程】HTML5网页内的视频拼图特效-源码吐血分享

前几天那谁发布的《月熊志》那个网站,我对里面的视频拼图这个效果很感兴趣。琢磨好几天,终于搞定了,并且知道是怎么做出来的了,在这里分享给大家。

大家先去这个网站看效果(网址:http://moonbear.animalsasia.org/ie/),然后往下看具体怎么实现,我会在这里很详细的给大家讲解。

网站中第一部分第二页《月熊的标志》是月熊志中互动性较强的一页,页面上会随机分布9块视频碎片,用户可以通过鼠标或者触控移动碎片完成拼图。

35cd3747bf95e94b21f82024d7a8f21f.png

在这个Demo中,我们需要引用2个JavaScript库,jQuery和Hammer.js。

Hammer.js 是一个手势触控JS库,能够为网页加入Tap、Swipe、Drag等事件,并且同时支持鼠标和触控输入,免去自己监听事件和判断浏览器兼容等问题。

建立九宫格

首先,我们在页面中建立一个九宫格:

HTML:

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;

56557505_1.png

每个宫格(.container)的大小是226*127,其中白色部分(.container i)是218*119。

插入视频

接着我们在页面中插入视频,我们使用HTML5 中新增的Video标签,并且为了兼容多数浏览器,使用了2种格式的视频源,然后设置视频为自动播放(Autoplay)和循环播放(Loop),视频源的大小建议和九宫格保持一致:

HTML:

最后把视频隐藏起来,在幕后默默的运行即可:

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方法/函数接下来会用到。

JS:

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 < 9; 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);

;

目前并没有限制碎片出现的位置,所以碎片可能会遮盖页面上的文字,你可以自己加以完善。

如果现在运行页面,你就能看到页面上出现的随机碎片了,但是由于还没有把视频绘制到页面上,所以只能看到黑色。

a14407d793b54ad9c21475f322633871.png

绘制视频碎片

绘制视频到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表示绘制到画布上的宽和高。

看文字的话可能比较难懂,看下面这张图应该能帮助你理解:

d6b01868973c1293d6d22dc591b39847.png

我们创建一个drawVideo函数绘制视频

JS:

function drawVideo()

for (var i = 0; i < 9; 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毫秒循环绘制。

e53dddfdafc217e35eb9fb255c06e210.png

处理拖拽操作

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);

最后初始化碎片并绑定函数到对应的事件上,这个互动小游戏就完成了。

bfd46e5c9174be93f1e413dce074ca8a.png

在众多HTML5网站里,这个网站运用的特效算是比较多了,尤其是交互体验,非常值得我们搞开发的研究学习。

其实,网站上还有很多其他互动方面的体验效果,做的都挺不错。大家可以自己前去体验:http://moonbear.animalsasia.org/ie/。希望本文能给大家带来一些灵感,运用到自己的网站开发上面去。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值