HTML5 Canvas 破碎重组的视频特效的示例代码


Posted in HTML / CSS onSeptember 24, 2019

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

HTML5 Canvas 破碎重组的视频特效的示例代码

HTML代码
 

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
css3实现一款模仿iphone样式的注册表单
Mar 20 HTML / CSS
利用CSS3的transition属性实现滑动效果
Aug 05 HTML / CSS
使用CSS3实现多列布局与多背景的技巧
Feb 29 HTML / CSS
CSS3弹性盒模型开发笔记(二)
Apr 26 HTML / CSS
利用CSS3实现开门效果实例源码
Aug 22 HTML / CSS
Css3新特性应用之视觉效果实例
Dec 12 HTML / CSS
HTML5 Canvas 起步(1) - 基本概念
May 12 HTML / CSS
利用html5的websocket实现websocket聊天室
Dec 12 HTML / CSS
HTML5标签嵌套规则详解【必看】
Apr 26 HTML / CSS
Canvas制作旋转的太极的示例
Mar 09 HTML / CSS
总结html5自定义属性有哪些
Apr 01 HTML / CSS
CSS3常见动画的实现方式
Apr 14 HTML / CSS
HTML5实现的震撼3D焦点图动画的示例代码
Sep 26 #HTML / CSS
基于 HTML5 WebGL 实现的垃圾分类系统
Oct 08 #HTML / CSS
HTML5移动端开发遇见的东西
Oct 11 #HTML / CSS
分享一个页面平滑滚动小技巧(推荐)
Oct 23 #HTML / CSS
分享一个H5原生form表单的checkbox特效代码
Feb 26 #HTML / CSS
利用HTML5+css3+jquery+weui实现仿微信聊天界面功能
Jan 08 #HTML / CSS
canvas基础之图形验证码的示例
Jan 02 #HTML / CSS
You might like
php自动获取字符串编码函数mb_detect_encoding
2011/05/31 PHP
PHP中使用break跳出多重循环代码实例
2015/01/21 PHP
php批量删除cookie的简单实现方法
2015/01/26 PHP
PHP通过API获取手机号码归属地
2015/05/28 PHP
PHP共享内存用法实例分析
2016/02/12 PHP
PHP使用curl函数发送Post请求的注意事项
2016/11/26 PHP
Extjs学习笔记之一 初识Extjs之MessageBox
2010/01/07 Javascript
window.event.keyCode兼容IE和Firefox实现js代码
2013/05/30 Javascript
jquery实现向下滑出的二级导航下滑菜单效果
2015/08/25 Javascript
利用prop-types第三方库对组件的props中的变量进行类型检测
2017/05/02 Javascript
解决Vue-cli npm run build生产环境打包,本地不能打开的问题
2018/09/20 Javascript
使用vue 国际化i18n 实现多实现语言切换功能
2018/10/11 Javascript
微信小程序实现折线图的示例代码
2019/06/07 Javascript
优雅的使用javascript递归画一棵结构树示例代码
2019/09/22 Javascript
浅谈JavaScript中this的指向更改
2020/07/28 Javascript
[54:47]Liquid vs VP Supermajor决赛 BO 第五场 6.10
2018/07/05 DOTA
[42:24]完美世界DOTA2联赛循环赛 LBZS vs DM BO2第一场 11.01
2020/11/02 DOTA
Python使用pygame模块编写俄罗斯方块游戏的代码实例
2015/12/08 Python
动态规划之矩阵连乘问题Python实现方法
2017/11/27 Python
python打包exe开机自动启动的实例(windows)
2019/06/28 Python
深入了解Python枚举类型的相关知识
2019/07/09 Python
Python Selenium库的基本使用教程
2021/01/04 Python
three.js模拟实现太阳系行星体系功能
2019/09/03 HTML / CSS
移动端html5判断是否滚动到底部并且下拉加载
2019/11/19 HTML / CSS
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
伦敦一家领先的精品零售商:IRIS Fashion
2019/05/24 全球购物
联强国际笔试题面试题
2013/07/10 面试题
西安交大自主招生自荐信
2014/01/27 职场文书
家长评语和期望
2014/02/10 职场文书
仓库管理员岗位职责
2014/03/19 职场文书
中学生寄语大全
2014/04/03 职场文书
绿色小区申报材料
2014/08/22 职场文书
重阳节演讲稿:尊敬帮助老人 弘扬传统美德
2014/09/25 职场文书
美术教师求职信范文
2015/03/20 职场文书
nginx基于域名,端口,不同IP的虚拟主机设置的实现
2021/03/31 Servers
python中的random模块和相关函数详解
2022/04/22 Python