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读取本地的json文件(实例讲解)
Oct 31 jQuery
JS/jQuery实现DIV延时几秒后消失或显示的方法
Feb 12 jQuery
jQuery实现判断上传图片类型和大小的方法示例
Apr 11 jQuery
jQuery+datatables插件实现ajax加载数据与增删改查功能示例
Apr 17 jQuery
使用jquery的cookie实现登录页记住用户名和密码的方法
Mar 13 jQuery
jquery实现二级导航下拉菜单效果实例
May 14 jQuery
jQuery实现的记住帐号密码功能完整示例
Aug 03 jQuery
JQuery中的常用事件、对象属性与使用方法分析
Dec 23 jQuery
JQuery事件委托(适用于给动态生成的脚本元素添加事件)
Feb 01 jQuery
jQuery弹框插件使用方法详解
May 26 jQuery
JQuery实现折叠式菜单的详细代码
Jun 03 jQuery
js和jquery判断数据类型的4种方法总结
Aug 28 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
PHP注释实例技巧
2008/10/03 PHP
php学习笔记 类的声明与对象实例化
2011/06/13 PHP
PHP实现GIF图片验证码
2015/11/04 PHP
在Mac OS上搭建PHP的Yii框架及相关测试环境
2016/02/14 PHP
PHP实现字符串大小写转函数的功能实例
2019/02/06 PHP
PHP如何获取Cookie并实现模拟登录
2020/07/16 PHP
Javascript操纵Cookie实现购物车程序
2006/11/23 Javascript
Javascript开发包大全整理
2006/12/22 Javascript
深入探讨javascript中的数据类型
2015/03/04 Javascript
微信小程序 在线支付功能的实现
2017/03/14 Javascript
js判断PC端与移动端跳转
2020/12/24 Javascript
vue.js从安装到搭建过程详解
2017/03/17 Javascript
Vue的百度地图插件尝试使用
2017/09/06 Javascript
jQuery基于闭包实现的显示与隐藏div功能示例
2018/06/09 jQuery
微信小程序 MinUI组件库系列之badge徽章组件示例
2018/08/20 Javascript
vue router 跳转后回到顶部的实例
2018/08/31 Javascript
详解JavaScript中的Object.is()与&quot;===&quot;运算符总结
2020/06/17 Javascript
three.js 制作动态二维码的示例代码
2020/07/31 Javascript
Vue 同步异步存值取值实现案例
2020/08/05 Javascript
[50:50]完美世界DOTA2联赛PWL S3 INK ICE vs DLG 第一场 12.20
2020/12/23 DOTA
Python中使用装饰器时需要注意的一些问题
2015/05/11 Python
推荐10款最受Python开发者欢迎的Python IDE
2018/09/16 Python
pycharm重置设置,恢复默认设置的方法
2018/10/22 Python
Python函数中的可变长参数详解
2019/09/12 Python
Python 使用SFTP和FTP实现对服务器的文件下载功能
2020/12/17 Python
AmazeUI 等分网格的实现示例
2020/08/25 HTML / CSS
会计自我鉴定
2013/11/02 职场文书
岗位职责风险防控
2014/02/18 职场文书
演讲主持词
2014/03/18 职场文书
股东协议书
2014/04/14 职场文书
2014年个人年终总结
2015/03/09 职场文书
公司财务人员岗位职责
2015/04/14 职场文书
小英雄雨来观后感
2015/06/09 职场文书
优秀创业计划书分享
2019/07/19 职场文书
导游词之秦皇岛燕塞湖
2020/01/03 职场文书
MySQL令人咋舌的隐式转换
2021/04/05 MySQL