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手风琴的简单制作
May 12 jQuery
jQuery扩展_动力节点Java学院整理
Jul 05 jQuery
Mui使用jquery并且使用点击跳转新窗口的实例
Aug 19 jQuery
jQuery UI Draggable + Sortable 结合使用(实例讲解)
Sep 07 jQuery
jQuery中图片展示插件highslide.js的简单dom
Apr 22 jQuery
jQuery实现获取动态添加的标签对象示例
Jun 28 jQuery
jQuery实现的监听导航滚动置顶状态功能示例
Jul 23 jQuery
jquery+css实现Tab栏切换的代码实例
May 14 jQuery
jQuery-Citys省市区三级菜单联动插件使用详解
Jul 26 jQuery
jQuery高级编程之js对象、json与ajax用法实例分析
Nov 01 jQuery
jquery实现弹窗(系统提示框)效果
Dec 10 jQuery
jquery实现简易验证插件封装
Sep 13 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中Cannot send session cache limiter 的问题的方法
2007/04/27 PHP
php产生随机数的两种方法实例代码 输出随机IP
2011/04/08 PHP
php XPath对XML文件查找及修改实现代码
2011/07/27 PHP
magento后台无法登录解决办法的两种方法
2016/12/09 PHP
php在windows环境下获得cpu内存实时使用率(推荐)
2018/02/08 PHP
Laravel实现搜索的时候分页并携带参数
2019/10/15 PHP
json 入门基础教程 推荐
2009/10/31 Javascript
javascript实现随机显示星星特效
2016/01/28 Javascript
ES6的新特性概览
2016/03/10 Javascript
JS 日期与时间戮相互转化的简单实例
2016/06/22 Javascript
微信小程序 教程之列表渲染
2016/10/18 Javascript
jQuery插件之validation插件
2017/03/29 jQuery
JS全角与半角转化实例(分享)
2017/07/04 Javascript
微信小程序自定义组件实现tabs选项卡功能
2018/07/14 Javascript
Kettle中使用JavaScrip调用jar包对文件内容进行MD5加密的操作方法
2020/09/04 Javascript
[01:53]3.19 DOTA2发布会 现场精彩Coser表演
2014/03/25 DOTA
使用python Telnet远程登录执行程序的方法
2019/01/26 Python
在Python中构建增广矩阵的实现方法
2019/07/01 Python
解决Python logging模块无法正常输出日志的问题
2020/02/21 Python
如何使用python写截屏小工具
2020/09/29 Python
美国知名的百货清仓店:Neiman Marcus Last Call
2016/08/03 全球购物
安德玛加拿大官网:Under Armour加拿大
2019/10/02 全球购物
杭州-DOTNET笔试题集
2013/09/25 面试题
国际商务专业学生个人的自我评价
2013/09/28 职场文书
毕业生自我鉴定实例
2014/01/21 职场文书
健康教育评估方案
2014/05/25 职场文书
欢迎领导标语
2014/06/27 职场文书
幼儿园六一亲子活动方案
2014/08/26 职场文书
先进党员事迹材料
2014/12/24 职场文书
介绍信格式
2015/01/30 职场文书
综合实践活动报告
2015/02/05 职场文书
实施意见格式范本
2015/06/05 职场文书
小学生班干部竞选稿
2015/11/20 职场文书
小学班主任培训心得体会
2016/01/07 职场文书
2016年学校十一国庆节活动总结
2016/04/01 职场文书
JS继承最简单的理解方式
2021/03/31 Javascript