视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
基于HTML5Canvas实现视频破碎重组特效
2020-11-27 15:17:10 责编:小采
文档


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

HTML代码

<p style="display:none">
	<video id="sourcevid" autoplay="true" loop="true">
	<source src="BigBuckBunny_0x360.mp4" type="video/mp4"/>
	<source src="BigBuckBunny_0x360.ogv" type="video/ogg"/>
	</video>
	<canvas id="sourcecopy" width="0" height="360"></canvas>
</p>
<p>
<center>
	<p 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!</p>
<canvas id="output" width="1000" height="600" 
onmousedown="dropBomb(event, this)" style="border: 0 none"> </canvas>
</center>
</p>

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>

下载本文
显示全文
专题