jQuery+HTML5实现WebGL高性能烟花绽放动画效果【附demo源码下载】


Posted in jQuery onAugust 18, 2017

本文实例讲述了jQuery+HTML5实现WebGL高性能烟花绽放动画效果。分享给大家供大家参考,具体如下:

运行效果:

jQuery+HTML5实现WebGL高性能烟花绽放动画效果【附demo源码下载】

完整代码如下:

<!DOCTYPE html>
<html class=" -webkit- js flexbox canvas canvastext webgl no-touch geolocation postmessage websqldatabase indexeddb hashchange history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients cssreflections csstransforms csstransforms3d csstransitions fontface generatedcontent video audio localstorage sessionstorage webworkers applicationcache svg inlinesvg smil svgclippaths">
<head>
<meta charset="UTF-8">
<meta name="viewport" content=" initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="format-detection" content="telephone=no">
<title>HTML5/WebGL高性能烟花绽放动画</title>
<meta name="description" content="HTML5/WebGL高性能烟花绽放动画">
<meta name="keywords" content="HTML5/WebGL高性能烟花绽放动画">
<style>
canvas {
  position: absolute;
  top: 0;
  left: 0;
  background-color: #111;
}
</style>
</head>
<body>
<script src="jquery-1.11.1.min.js"></script>
<canvas id="c" width="1440" height="304"></canvas><script src="prefixfree.min.js"></script><script src="modernizr.js"></script><script>var gl = c.getContext('webgl', {
    preserveDrawingBuffer: true
  }),
  w = c.width = window.innerWidth,
  h = c.height = window.innerHeight
, webgl = {}, opts = {
  projectileAlpha: .8,
  projectileLineWidth: 1.3,
  fireworkAngleSpan: .5,
  baseFireworkVel: 3,
  addedFireworkVel: 3,
  gravity: .03,
  lowVelBoundary: -.2,
  xFriction: .995,
  baseShardVel: 1,
  addedShardVel: .2,
  fireworks: 1000,
  baseShardsParFirework: 10,
  addedShardsParFirework: 10,
  shardFireworkVelMultiplier: .3,
  initHueMultiplier: 1 / 360,
  runHueAdder: .1 / 360
}
webgl.vertexShaderSource = `
uniform int u_mode;
uniform vec2 u_res;
attribute vec4 a_data;
varying vec4 v_color;
vec3 h2rgb( float h ){
 return clamp( abs( mod( h * 6. + vec3( 0, 4, 2 ), 6. ) - 3. ) -1., 0., 1. );
}
void clear(){
 gl_Position = vec4( a_data.xy, 0, 1 );
 v_color = vec4( 0, 0, 0, a_data.w );
}
void draw(){
 gl_Position = vec4( vec2( 1, -1 ) * ( ( a_data.xy / u_res ) * 2. - 1. ), 0, 1 );
 v_color = vec4( h2rgb( a_data.z ), a_data.w );
}
void main(){
 if( u_mode == 0 )
 draw();
 else
 clear();
}
`;
webgl.fragmentShaderSource = `
precision mediump float;
varying vec4 v_color;
void main(){
 gl_FragColor = v_color;
}
`;
webgl.vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(webgl.vertexShader, webgl.vertexShaderSource);
gl.compileShader(webgl.vertexShader);
webgl.fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(webgl.fragmentShader, webgl.fragmentShaderSource);
gl.compileShader(webgl.fragmentShader);
webgl.shaderProgram = gl.createProgram();
gl.attachShader(webgl.shaderProgram, webgl.vertexShader);
gl.attachShader(webgl.shaderProgram, webgl.fragmentShader);
gl.linkProgram(webgl.shaderProgram);
gl.useProgram(webgl.shaderProgram);
webgl.dataAttribLoc = gl.getAttribLocation(webgl.shaderProgram, 'a_data');
webgl.dataBuffer = gl.createBuffer();
gl.enableVertexAttribArray(webgl.dataAttribLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, webgl.dataBuffer);
gl.vertexAttribPointer(webgl.dataAttribLoc, 4, gl.FLOAT, false, 0, 0);
webgl.resUniformLoc = gl.getUniformLocation(webgl.shaderProgram, 'u_res');
webgl.modeUniformLoc = gl.getUniformLocation(webgl.shaderProgram, 'u_mode');
gl.viewport(0, 0, w, h);
gl.uniform2f(webgl.resUniformLoc, w, h);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
gl.lineWidth(opts.projectileLineWidth);
webgl.data = [];
webgl.clear = function() {
  gl.uniform1i(webgl.modeUniformLoc, 1);
  var a = .1;
  webgl.data = [-1, -1, 0, a,
    1, -1, 0, a, -1, 1, 0, a, -1, 1, 0, a,
    1, -1, 0, a,
    1, 1, 0, a
  ];
  webgl.draw(gl.TRIANGLES);
  gl.uniform1i(webgl.modeUniformLoc, 0);
  webgl.data.length = 0;
}
webgl.draw = function(glType) {
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(webgl.data), gl.STATIC_DRAW);
  gl.drawArrays(glType, 0, webgl.data.length / 4);
}
var fireworks = [],
  tick = 0,
  sins = [],
  coss = [],
  maxShardsParFirework = opts.baseShardsParFirework + opts.addedShardsParFirework,
  tau = 6.283185307179586476925286766559;
for (var i = 0; i < maxShardsParFirework; ++i) {
  sins[i] = Math.sin(tau * i / maxShardsParFirework);
  coss[i] = Math.cos(tau * i / maxShardsParFirework);
}
function Firework() {
  this.reset();
  this.shards = [];
  for (var i = 0; i < maxShardsParFirework; ++i)
    this.shards.push(new Shard(this));
}
Firework.prototype.reset = function() {
  var angle = -Math.PI / 2 + (Math.random() - .5) * opts.fireworkAngleSpan,
    vel = opts.baseFireworkVel + opts.addedFireworkVel * Math.random();
  this.mode = 0;
  this.vx = vel * Math.cos(angle);
  this.vy = vel * Math.sin(angle);
  this.x = Math.random() * w;
  this.y = h;
  this.hue = tick * opts.initHueMultiplier;
}
Firework.prototype.step = function() {
  if (this.mode === 0) {
    var ph = this.hue,
      px = this.x,
      py = this.y;
    this.hue += opts.runHueAdder;
    this.x += this.vx *= opts.xFriction;
    this.y += this.vy += opts.gravity;
    webgl.data.push(
      px, py, ph, opts.projectileAlpha * .2,
      this.x, this.y, this.hue, opts.projectileAlpha * .2);
    if (this.vy >= opts.lowVelBoundary) {
      this.mode = 1;
      this.shardAmount = opts.baseShardsParFirework + opts.addedShardsParFirework * Math.random() | 0;
      var baseAngle = Math.random() * tau,
        x = Math.cos(baseAngle),
        y = Math.sin(baseAngle),
        sin = sins[this.shardAmount],
        cos = coss[this.shardAmount];
      for (var i = 0; i < this.shardAmount; ++i) {
        var vel = opts.baseShardVel + opts.addedShardVel * Math.random();
        this.shards[i].reset(x * vel, y * vel)
        var X = x;
        x = x * cos - y * sin;
        y = y * cos + X * sin;
      }
    }
  } else if (this.mode === 1) {
    this.ph = this.hue
    this.hue += opts.runHueAdder;
    var allDead = true;
    for (var i = 0; i < this.shardAmount; ++i) {
      var shard = this.shards[i];
      if (!shard.dead) {
        shard.step();
        allDead = false;
      }
    }
    if (allDead)
      this.reset();
  }
}
function Shard(parent) {
  this.parent = parent;
}
Shard.prototype.reset = function(vx, vy) {
  this.x = this.parent.x;
  this.y = this.parent.y;
  this.vx = this.parent.vx * opts.shardFireworkVelMultiplier + vx;
  this.vy = this.parent.vy * opts.shardFireworkVelMultiplier + vy;
  this.starty = this.y;
  this.dead = false;
  this.tick = 1;
}
Shard.prototype.step = function() {
  this.tick += .05;
  var px = this.x,
    py = this.y;
  this.x += this.vx *= opts.xFriction;
  this.y += this.vy += opts.gravity;
  var proportion = 1 - (this.y - this.starty) / (h - this.starty);
  webgl.data.push(
    px, py, this.parent.ph, opts.projectileAlpha / this.tick,
    this.x, this.y, this.parent.hue, opts.projectileAlpha / this.tick);
  if (this.y > h)
    this.dead = true;
}
function anim() {
  window.requestAnimationFrame(anim)
  webgl.clear();
  ++tick;
  if (fireworks.length < opts.fireworks)
    fireworks.push(new Firework);
  fireworks.map(function(firework) {
    firework.step();
  });
  webgl.draw(gl.LINES);
}
anim();
window.addEventListener('resize', function() {
  w = c.width = window.innerWidth;
  h = c.height = window.innerHeight;
  gl.viewport(0, 0, w, h);
  gl.uniform2f(webgl.resUniformLoc, w, h);
})
window.addEventListener('click', function(e) {
  var firework = new Firework();
  firework.x = e.clientX;
  firework.y = e.clientY;
  firework.vx = 0;
  firework.vy = 0;
  fireworks.push(firework);
});
</script>
</body>
</html>

附:完整实例代码点击此处本站下载

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

jQuery 相关文章推荐
jQuery EasyUI tree增加搜索功能的实现方法
Apr 27 jQuery
jQuery实现的简单在线计算器功能
May 11 jQuery
jQuery Ajax向服务端传递数组参数值的实例代码
Sep 03 jQuery
使用Ajax和Jquery配合数据库实现下拉框的二级联动的示例
Jan 25 jQuery
jQuery实现基本动画效果的方法详解
Sep 06 jQuery
jQuery实现左右两个列表框的内容相互移动功能示例
Jan 27 jQuery
jquery简单实现纵向的无缝滚动代码实例
Apr 01 jQuery
jquery实现二级导航下拉菜单效果实例
May 14 jQuery
jQuery实现简单QQ聊天框
Aug 27 jQuery
如何使用jQuery操作Cookies方法解析
Sep 08 jQuery
JQuery Ajax如何实现注册检测用户名
Sep 25 jQuery
jQuery使用hide()、toggle()函数实现相机品牌展示隐藏功能
Jan 29 jQuery
简单实现jQuery轮播效果
Aug 18 #jQuery
简单实现jQuery手风琴效果
Aug 18 #jQuery
jQuery Layer弹出层传值到父页面的实现代码
Aug 17 #jQuery
jQuery条件分页 代替离线查询(附代码)
Aug 17 #jQuery
使用jquery的jsonp如何发起跨域请求及其原理详解
Aug 17 #jQuery
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
Aug 17 #jQuery
jQuery实现全选、反选和不选功能
Aug 16 #jQuery
You might like
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
php中模拟POST传递数据的两种方法分享
2011/09/16 PHP
xss防御之php利用httponly防xss攻击
2014/03/21 PHP
一个图片地址分解程序(用于PHP小偷程序)
2014/08/23 PHP
PHP下载生成的csv文件及问题总结
2015/08/06 PHP
php+croppic.js实现剪切上传图片功能
2018/08/14 PHP
php语法检查的方法总结
2019/01/21 PHP
不用ajax实现点击文字即可编辑的方法
2007/12/16 Javascript
Javascript this关键字使用分析
2008/10/21 Javascript
汉化英文版的Dreamweaver CS5并自动提示jquery
2010/11/25 Javascript
js中的replace方法使用介绍
2013/10/28 Javascript
自定义的一个简单时尚js下拉选择框
2013/11/20 Javascript
Node.js 去掉种子(torrent)文件里的邪恶信息
2015/03/27 Javascript
JS实现六边形3D拖拽翻转效果的方法
2016/09/11 Javascript
基于JavaScript实现表格滚动分页
2017/11/22 Javascript
JS动态添加元素及绑定事件造成程序重复执行解决
2017/12/07 Javascript
vue init webpack 建vue项目报错的解决方法
2018/09/29 Javascript
微信小程序CSS3动画下拉菜单效果
2018/11/04 Javascript
Vue商品控件与购物车联动效果的实例代码
2019/07/21 Javascript
Laravel 如何在blade文件中使用Vue组件的示例代码
2020/06/28 Javascript
Pandas 数据框增、删、改、查、去重、抽样基本操作方法
2018/04/12 Python
python3 对list中每个元素进行处理的方法
2018/06/29 Python
Python3的介绍、安装和命令行的认识(推荐)
2018/10/20 Python
selenium+python自动化测试环境搭建步骤
2019/06/03 Python
通过pycharm使用git的步骤(图文详解)
2019/06/13 Python
在django-xadmin中APScheduler的启动初始化实例
2019/11/15 Python
pandas 强制类型转换 df.astype实例
2020/04/09 Python
菲律宾优惠券网站:MetroDeal
2019/04/12 全球购物
新驾驶员个人自我评价
2014/01/03 职场文书
《理想》教学反思
2014/02/17 职场文书
办公室主任四风问题对照检查材料思想汇报
2014/09/28 职场文书
中层干部考核评语
2015/01/04 职场文书
机关单位保密工作责任书
2015/05/11 职场文书
导游词之黄果树瀑布
2019/09/20 职场文书
Python 如何安装Selenium
2021/05/06 Python
python实现简单石头剪刀布游戏
2021/10/24 Python