JavaScript+html5 canvas实现图片破碎重组动画特效


Posted in Javascript onFebruary 22, 2016

也许你见过HTML5图片破碎动画特效,实现的原理也挺简单的。但是你应该没有见过视频也可以破碎重组,这个HTML5动画就是利用Canvas的相关特性,实现了点击鼠标让视频破碎重组的效果。在视频区域点击鼠标,即可让该区域的视频破碎,让后经过一段时间后,破碎的区域又可以重组还原,视觉效果非常棒。

JavaScript+html5 canvas实现图片破碎重组动画特效

HTML代码

<div style="display:none">
 <video id="sourcevid" autoplay="true" loop="true">
  <source src="BigBuckBunny_640x360.mp4" type="video/mp4"/>
  <source src="BigBuckBunny_640x360.ogv" type="video/ogg"/>
 </video>
 <canvas id="sourcecopy" width="640" height="360"></canvas>
</div>
<div>
<center>
 <div style="z-index:1;position:relative;text-align:center;font-size:16px;font-weight:bold;width:1000px;top:60px;">Click video to blow it up!</div>
 <canvas id="output" width="1000" height="600" onmousedown="dropBomb(event, this)" style="border: 0 none">    </canvas>
</center>
</div>

JavaScript代码

var video;
var copy;
var copycanvas;
var draw;

var TILE_WIDTH = 32;
var TILE_HEIGHT = 24;
var TILE_CENTER_WIDTH = 16;
var TILE_CENTER_HEIGHT = 12;
var SOURCERECT = {x:0, y:0, width:0, height:0};
var PAINTRECT = {x:0, y:0, width:1000, height:600};

function init(){
 video = document.getElementById('sourcevid');
 copycanvas = document.getElementById('sourcecopy');
 copy = copycanvas.getContext('2d');
 var outputcanvas = document.getElementById('output');
 draw = outputcanvas.getContext('2d');
 setInterval("processFrame()", 33);
}
function createTiles(){
 var offsetX = TILE_CENTER_WIDTH+(PAINTRECT.width-SOURCERECT.width)/2;
 var offsetY = TILE_CENTER_HEIGHT+(PAINTRECT.height-SOURCERECT.height)/2;
 var y=0;
 while(y < SOURCERECT.height){
 var x=0;
 while(x < SOURCERECT.width){
  var tile = new Tile();
  tile.videoX = x;
  tile.videoY = y;
  tile.originX = offsetX+x;
  tile.originY = offsetY+y;
  tile.currentX = tile.originX;
  tile.currentY = tile.originY;
  tiles.push(tile);
  x+=TILE_WIDTH;
 }
 y+=TILE_HEIGHT;
 }
}

var RAD = Math.PI/180;
var randomJump = false;
var tiles = [];
var debug = false;
function processFrame(){
 if(!isNaN(video.duration)){
 if(SOURCERECT.width == 0){
  SOURCERECT = {x:0,y:0,width:video.videoWidth,height:video.videoHeight};
  createTiles();
 }
 //this is to keep my sanity while developing
 if(randomJump){
  randomJump = false;
  video.currentTime = Math.random()*video.duration;
 }
 //loop
 if(video.currentTime == video.duration){
  video.currentTime = 0;
 }
 }
 var debugStr = "";
 //copy tiles
 copy.drawImage(video, 0, 0);
 draw.clearRect(PAINTRECT.x, PAINTRECT.y,PAINTRECT.width,PAINTRECT.height);

 for(var i=0; i<tiles.length; i++){
 var tile = tiles[i];
 if(tile.force > 0.0001){
  //expand
  tile.moveX *= tile.force;
  tile.moveY *= tile.force;
  tile.moveRotation *= tile.force;
  tile.currentX += tile.moveX;
  tile.currentY += tile.moveY;
  tile.rotation += tile.moveRotation;
  tile.rotation %= 360;
  tile.force *= 0.9;
  if(tile.currentX <= 0 || tile.currentX >= PAINTRECT.width){
  tile.moveX *= -1;
  }
  if(tile.currentY <= 0 || tile.currentY >= PAINTRECT.height){
  tile.moveY *= -1;
  }
 }else if(tile.rotation != 0 || tile.currentX != tile.originX || tile.currentY != tile.originY){
  //contract
  var diffx = (tile.originX-tile.currentX)*0.2;
  var diffy = (tile.originY-tile.currentY)*0.2;
  var diffRot = (0-tile.rotation)*0.2;

  if(Math.abs(diffx) < 0.5){
  tile.currentX = tile.originX;
  }else{
  tile.currentX += diffx;
  }
  if(Math.abs(diffy) < 0.5){
  tile.currentY = tile.originY;
  }else{
  tile.currentY += diffy;
  }
  if(Math.abs(diffRot) < 0.5){
  tile.rotation = 0;
  }else{
  tile.rotation += diffRot;
  }
 }else{
  tile.force = 0;
 }
 draw.save();
 draw.translate(tile.currentX, tile.currentY);
 draw.rotate(tile.rotation*RAD);
 draw.drawImage(copycanvas, tile.videoX, tile.videoY, TILE_WIDTH, TILE_HEIGHT, -TILE_CENTER_WIDTH, -TILE_CENTER_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
 draw.restore();
 }
 if(debug){
 debug = false;
 document.getElementById('trace').innerHTML = debugStr;
 }
}

function explode(x, y){
 for(var i=0; i<tiles.length; i++){
 var tile = tiles[i];

 var xdiff = tile.currentX-x;
 var ydiff = tile.currentY-y;
 var dist = Math.sqrt(xdiff*xdiff + ydiff*ydiff);

 var randRange = 220+(Math.random()*30);
 var range = randRange-dist;
 var force = 3*(range/randRange);
 if(force > tile.force){
  tile.force = force;
  var radians = Math.atan2(ydiff, xdiff);
  tile.moveX = Math.cos(radians);
  tile.moveY = Math.sin(radians);
  tile.moveRotation = 0.5-Math.random();
 }
 }
 tiles.sort(zindexSort);
 processFrame();
}
function zindexSort(a, b){
 return (a.force-b.force);
}

function dropBomb(evt, obj){
 var posx = 0;
 var posy = 0;
 var e = evt || window.event;
 if (e.pageX || e.pageY){
 posx = e.pageX;
 posy = e.pageY;
 }else if (e.clientX || e.clientY) {
 posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
 posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
 }
 var canvasX = posx-obj.offsetLeft;
 var canvasY = posy-obj.offsetTop;
 explode(canvasX, canvasY);
}

function Tile(){
 this.originX = 0;
 this.originY = 0;
 this.currentX = 0;
 this.currentY = 0;
 this.rotation = 0;
 this.force = 0;
 this.z = 0;
 this.moveX= 0;
 this.moveY= 0;
 this.moveRotation = 0;

 this.videoX = 0;
 this.videoY = 0;
}

/*
 getPixel
 return pixel object {r,g,b,a}
*/
function getPixel(imageData, x, y){
 var data = imageData.data;
 var pos = (x + y * imageData.width) * 4;
 return {r:data[pos], g:data[pos+1], b:data[pos+2], a:data[pos+3]}
}
/*
 setPixel
 set pixel object {r,g,b,a}
*/
function setPixel(imageData, x, y, pixel){
 var data = imageData.data;
 var pos = (x + y * imageData.width) * 4;
 data[pos] = pixel.r;
 data[pos+1] = pixel.g;
 data[pos+2] = pixel.b;
 data[pos+3] = pixel.a;
}
/*
 copyPixel
 faster then using getPixel/setPixel combo
*/
function copyPixel(sImageData, sx, sy, dImageData, dx, dy){
 var spos = (sx + sy * sImageData.width) * 4;
 var dpos = (dx + dy * dImageData.width) * 4;
 dImageData.data[dpos] = sImageData.data[spos];   //R
 dImageData.data[dpos+1] = sImageData.data[spos+1]; //G
 dImageData.data[dpos+2] = sImageData.data[spos+2]; //B
 dImageData.data[dpos+3] = sImageData.data[spos+3]; //A
}
</script>

希望本文所述对大家学习javascript程序设计有所帮助。

Javascript 相关文章推荐
img onload事件绑定各浏览器均可执行
Dec 19 Javascript
js页面跳转的问题(跳转到父页面、最外层页面、本页面)
Aug 14 Javascript
父元素与子iframe相互获取变量和元素对象的具体实现
Oct 15 Javascript
查看大图功能代码jquery版
Nov 05 Javascript
最短的IE判断var ie=!-[1,]分析
May 28 Javascript
node.js学习总结之调式代码的方法
Jun 25 Javascript
angularjs指令中的compile与link函数详解
Dec 06 Javascript
js实现键盘控制DIV移动的方法
Jan 10 Javascript
基于jQuery的select下拉框选择触发事件实例分析
Nov 18 Javascript
JavaScript实现时间表动态效果
Jul 15 Javascript
js实现鼠标拖拽多选功能示例
Aug 01 Javascript
Vue3不支持Filters过滤器的问题
Sep 24 Javascript
jQuery获取字符串中出现最多的数
Feb 22 #Javascript
jQuery基于muipicker实现仿ios时间选择
Feb 22 #Javascript
简单谈谈javascript中this的隐式绑定
Feb 22 #Javascript
javascript实现一个简单的弹出窗
Feb 22 #Javascript
Js的Array数组对象详解
Feb 22 #Javascript
AngularJS中使用HTML5手机摄像头拍照
Feb 22 #Javascript
JS字符串的切分用法实例
Feb 22 #Javascript
You might like
一个用于网络的工具函数库
2006/10/09 PHP
PHP 彩色文字实现代码
2009/06/29 PHP
使用php实现快钱支付功能(涉及到接口)
2013/07/01 PHP
php+mysqli使用面向对象方式查询数据库实例
2015/01/29 PHP
如何批量清理系统临时文件(语言:C#、 C/C++、 php 、python 、java )
2016/02/01 PHP
获取URL地址中的文件名和参数的javascript代码
2009/09/02 Javascript
javascript操作cookie的文章(设置,删除cookies)
2010/04/01 Javascript
js的逻辑运算符 ||
2010/05/31 Javascript
键盘KeyCode值列表汇总
2013/11/26 Javascript
变量声明时命名与变量作为对象属性时命名的区别解析
2013/12/06 Javascript
jQuery动画效果animate和scrollTop结合使用实例
2014/04/02 Javascript
js改变embed标签src值的方法
2015/04/10 Javascript
详解JavaScript对W3C DOM模版的支持情况
2015/06/16 Javascript
jQuery EasyUI Layout实现tabs标签的实例
2017/09/26 jQuery
vue-cli+webpack项目 修改项目名称的方法
2018/02/28 Javascript
详解微信小程序canvas圆角矩形的绘制的方法
2018/08/22 Javascript
微信小程序 拍照或从相册选取图片上传代码实例
2019/08/28 Javascript
layui点击数据表格添加或删除一行的例子
2019/09/12 Javascript
小程序自定义圆形进度条
2020/11/17 Javascript
[00:26]TI7不朽珍藏III——冥界亚龙不朽展示
2017/07/15 DOTA
python实现报表自动化详解
2017/11/16 Python
Python continue继续循环用法总结
2018/06/10 Python
python实现画循环圆
2019/11/23 Python
法国珠宝店:CLEOR
2017/01/29 全球购物
梅西百货澳大利亚:Macy’s Australia
2017/07/26 全球购物
Agoda台湾官网:国内外订房2折起
2018/03/20 全球购物
法律专业个人实习自我鉴定
2013/09/23 职场文书
心得体会开头
2014/01/01 职场文书
新领导上任欢迎词
2014/01/13 职场文书
超市端午节活动方案
2014/01/23 职场文书
四年级语文教学反思
2014/02/05 职场文书
语文高效课堂实施方案
2014/05/03 职场文书
空气的环保标语
2014/06/12 职场文书
入党介绍人考察意见
2015/06/01 职场文书
自愿离婚协议书范本2016
2016/03/18 职场文书
如何才能写好调研报告?
2019/07/03 职场文书