$(function(){ //粒子 ////////////////////////////粒子 class shaderprogram { constructor( holder, options = {} ) { options = object.assign( { antialias: false, depthtest: false, mousemove: false, autosize: true, side: 'front', vertex: ` precision highp float; attribute vec4 a_position; attribute vec4 a_color; uniform float u_time; uniform vec2 u_resolution; uniform vec2 u_mousemove; uniform mat4 u_projection; varying vec4 v_color; void main() { gl_position = u_projection * a_position; gl_pointsize = (10.0 / gl_position.w) * 100.0; v_color = a_color; }`, fragment: ` precision highp float; uniform sampler2d u_texture; uniform int u_hastexture; varying vec4 v_color; void main() { if ( u_hastexture == 1 ) { gl_fragcolor = v_color * texture2d(u_texture, gl_pointcoord); } else { gl_fragcolor = v_color; } }`, uniforms: {}, buffers: {}, camera: {}, texture: null, onupdate: ( () => {} ), onresize: ( () => {} ), }, options ) const uniforms = object.assign( { time: { type: 'float', value: 0 }, hastexture: { type: 'int', value: 0 }, resolution: { type: 'vec2', value: [ 0, 0 ] }, mousemove: { type: 'vec2', value: [ 0, 0 ] }, projection: { type: 'mat4', value: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] }, }, options.uniforms ) const buffers = object.assign( { position: { size: 3, data: [] }, color: { size: 4, data: [] }, }, options.buffers ) const camera = object.assign( { fov: 60, near: 1, far: 10000, aspect: 1, z: 100, perspective: true, }, options.camera ) const canvas = document.createelement( 'canvas' ) const gl = canvas.getcontext( 'webgl', { antialias: options.antialias } ) if ( ! gl ) return false this.count = 0 this.gl = gl this.canvas = canvas this.camera = camera this.holder = holder this.onupdate = options.onupdate this.onresize = options.onresize this.data = {} holder.appendchild( canvas ) this.createprogram( options.vertex, options.fragment ) this.createbuffers( buffers ) this.createuniforms( uniforms ) this.updatebuffers() this.updateuniforms() this.createtexture( options.texture ) gl.enable( gl.blend ) gl.enable( gl.cull_face ) gl.blendfunc( gl.src_alpha, gl.one ) gl[ options.depthtest ? 'enable' : 'disable' ]( gl.depth_test ) if ( options.autosize ) window.addeventlistener( 'resize', e => this.resize( e ), false ) if ( options.mousemove ) window.addeventlistener( 'mousemove', e => this.mousemove( e ), false ) this.resize() this.update = this.update.bind( this ) this.time = { start: performance.now(), old: performance.now() } this.update() } mousemove( e ) { let x = e.pagex / this.width * 2 - 1 let y = e.pagey / this.height * 2 - 1 this.uniforms.mousemove = [ x, y ] } resize( e ) { const holder = this.holder const canvas = this.canvas const gl = this.gl const width = this.width = holder.offsetwidth const height = this.height = holder.offsetheight const aspect = this.aspect = width / height const dpi = this.dpi = devicepixelratio canvas.width = width * dpi canvas.height = height * dpi canvas.style.width = width + 'px' canvas.style.height = height + 'px' gl.viewport( 0, 0, width * dpi, height * dpi ) gl.clearcolor( 0, 0, 0, 0 ) this.uniforms.resolution = [ width, height ] this.uniforms.projection = this.setprojection( aspect ) this.onresize( width, height, dpi ) } setprojection( aspect ) { const camera = this.camera if ( camera.perspective ) { camera.aspect = aspect const fovrad = camera.fov * ( math.pi / 180 ) const f = math.tan( math.pi * 0.5 - 0.5 * fovrad ) const rangeinv = 1.0 / ( camera.near - camera.far ) const matrix = [ f / camera.aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (camera.near + camera.far) * rangeinv, -1, 0, 0, camera.near * camera.far * rangeinv * 2, 0 ] matrix[ 14 ] += camera.z matrix[ 15 ] += camera.z return matrix } else { return [ 2 / this.width, 0, 0, 0, 0, -2 / this.height, 0, 0, 0, 0, 1, 0, -1, 1, 0, 1, ] } } createshader( type, source ) { const gl = this.gl const shader = gl.createshader( type ) gl.shadersource( shader, source ) gl.compileshader( shader ) if ( gl.getshaderparameter (shader, gl.compile_status ) ) { return shader } else { console.log( gl.getshaderinfolog( shader ) ) gl.deleteshader( shader ) } } createprogram( vertex, fragment ) { const gl = this.gl const vertexshader = this.createshader( gl.vertex_shader, vertex ) const fragmentshader = this.createshader( gl.fragment_shader, fragment ) const program = gl.createprogram() gl.attachshader( program, vertexshader ) gl.attachshader( program, fragmentshader ) gl.linkprogram( program ) if ( gl.getprogramparameter( program, gl.link_status ) ) { gl.useprogram( program ) this.program = program } else { console.log( gl.getprograminfolog( program ) ) gl.deleteprogram( program ) } } createuniforms( data ) { const gl = this.gl const uniforms = this.data.uniforms = data const values = this.uniforms = {} object.keys( uniforms ).foreach( name => { const uniform = uniforms[ name ] uniform.location = gl.getuniformlocation( this.program, 'u_' + name ) object.defineproperty( values, name, { set: value => { uniforms[ name ].value = value this.setuniform( name, value ) }, get: () => uniforms[ name ].value } ) } ) } setuniform( name, value ) { const gl = this.gl const uniform = this.data.uniforms[ name ] uniform.value = value switch ( uniform.type ) { case 'int': { gl.uniform1i( uniform.location, value ) break } case 'float': { gl.uniform1f( uniform.location, value ) break } case 'vec2': { gl.uniform2f( uniform.location, ...value ) break } case 'vec3': { gl.uniform3f( uniform.location, ...value ) break } case 'vec4': { gl.uniform4f( uniform.location, ...value ) break } case 'mat2': { gl.uniformmatrix2fv( uniform.location, false, value ) break } case 'mat3': { gl.uniformmatrix3fv( uniform.location, false, value ) break } case 'mat4': { gl.uniformmatrix4fv( uniform.location, false, value ) break } } // ivec2 : uniform2i, // ivec3 : uniform3i, // ivec4 : uniform4i, // sampler2d : uniform1i, // samplercube : uniform1i, // bool : uniform1i, // bvec2 : uniform2i, // bvec3 : uniform3i, // bvec4 : uniform4i, } updateuniforms() { const gl = this.gl const uniforms = this.data.uniforms object.keys( uniforms ).foreach( name => { const uniform = uniforms[ name ] this.uniforms[ name ] = uniform.value } ) } createbuffers( data ) { const gl = this.gl const buffers = this.data.buffers = data const values = this.buffers = {} object.keys( buffers ).foreach( name => { const buffer = buffers[ name ] buffer.buffer = this.createbuffer( 'a_' + name, buffer.size ) object.defineproperty( values, name, { set: data => { buffers[ name ].data = data this.setbuffer( name, data ) if ( name == 'position' ) this.count = buffers.position.data.length / 3 }, get: () => buffers[ name ].data } ) } ) } createbuffer( name, size ) { const gl = this.gl const program = this.program const index = gl.getattriblocation( program, name ) const buffer = gl.createbuffer() gl.bindbuffer( gl.array_buffer, buffer ) gl.enablevertexattribarray( index ) gl.vertexattribpointer( index, size, gl.float, false, 0, 0 ) return buffer } setbuffer( name, data ) { const gl = this.gl const buffers = this.data.buffers if ( name == null && ! gl.bindbuffer( gl.array_buffer, null ) ) return gl.bindbuffer( gl.array_buffer, buffers[ name ].buffer ) gl.bufferdata( gl.array_buffer, new float32array( data ), gl.static_draw ) } updatebuffers() { const gl = this.gl const buffers = this.buffers object.keys( buffers ).foreach( name => buffers[ name ] = buffer.data ) this.setbuffer( null ) } createtexture( src ) { const gl = this.gl const texture = gl.createtexture() gl.bindtexture( gl.texture_2d, texture ) gl.teximage2d( gl.texture_2d, 0, gl.rgba, 1, 1, 0, gl.rgba, gl.unsigned_byte, new uint8array( [ 0, 0, 0, 0 ] ) ) this.texture = texture if ( src ) { this.uniforms.hastexture = 1 this.loadtexture( src ) } } loadtexture( src ) { const gl = this.gl const texture = this.texture const textureimage = new image() textureimage.onload = () => { gl.bindtexture( gl.texture_2d, texture ) gl.teximage2d( gl.texture_2d, 0, gl.rgba, gl.rgba, gl.unsigned_byte, textureimage ) gl.texparameteri( gl.texture_2d, gl.texture_min_filter, gl.linear ) gl.texparameteri( gl.texture_2d, gl.texture_mag_filter, gl.linear ) gl.texparameteri(gl.texture_2d, gl.texture_wrap_s, gl.clamp_to_edge) gl.texparameteri(gl.texture_2d, gl.texture_wrap_t, gl.clamp_to_edge) // gl.generatemipmap( gl.texture_2d ) } textureimage.src = src } update() { const gl = this.gl const now = performance.now() const elapsed = ( now - this.time.start ) / 5000 const delta = now - this.time.old this.time.old = now this.uniforms.time = elapsed if ( this.count > 0 ) { gl.clear( gl.colorbufferbit ) gl.drawarrays( gl.points, 0, this.count ) } this.onupdate( delta ) requestanimationframe( this.update ) } } const pointsize = .8 const waves = new shaderprogram( document.queryselector( '.waves' ), { texture: 'data:image/png;base64,ivborw0kggoaaaansuheugaaacaaaaagcamaaabepirgaaaab1bmveuaaad///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8v0wlraaaajhrstlmac/gogvdhmwcexrvjwzrm29trqqskenrxvklansiue8mrkgpv+hofaaabceleqvq4y4vt13ldmawlruhteo+r9f/fwmfo6dlapekveecrxoulwsegps9nuldwia2y+alqunbaweg775zv+sa4/ffrmxt8u2fzfcvwjr/yrh4/h9sarclskdpmwkzb8vseehb3m0shkhvcynzexeaq9xl4opeiex2qcgnwgbj6gmyjw9t1k0fk9yzunpxeagsfjtyjwzxabnozggoryz0ypk2hzqsyx1y8dgsro2ewoiyh2qwoek1y9orqv0a8tibm1a8emhwynrmy7cz4t1cmyrkhsuvp3grxyhoclbxnoc3ijv//zrj/kxxuhpub+6jjzzhrpg6gojnqaomzp4ndr48olxn/h27srq08s0zjaaaaaelftksuqmcc', uniforms: { size: { type: 'float', value: pointsize }, field: { type: 'vec3', value: [ 0, 0, 0 ] }, speed: { type: 'float', value: 5 }, }, vertex: ` #define m_pi 3.1415926535897932384626433832795 precision highp float; attribute vec4 a_position; attribute vec4 a_color; uniform float u_time; uniform float u_size; uniform float u_speed; uniform vec3 u_field; uniform mat4 u_projection; varying vec4 v_color; void main() { vec3 pos = a_position.xyz; pos.y += ( cos(pos.x / u_field.x * m_pi * 8.0 + u_time * u_speed) + sin(pos.z / u_field.z * m_pi * 8.0 + u_time * u_speed) ) * u_field.y; gl_position = u_projection * vec4( pos.xyz, a_position.w ); gl_pointsize = ( u_size / gl_position.w ) * 100.0; v_color = a_color; }`, fragment: ` precision highp float; uniform sampler2d u_texture; varying vec4 v_color; void main() { gl_fragcolor = v_color * texture2d(u_texture, gl_pointcoord); }`, onresize( w, h, dpi ) { const position = [], color = [] const width = 80 * ( w / h ) const depth = 400 const height = 3 const distance = 2 for ( let x = 0; x < width; x += distance ) { for ( let z = 0; z < depth; z+= distance ) { position.push( - width / 2 + x, -30, -depth / 2 + z ) //color.push( 0, 1 - ( x / width ) * 1, 0.5 + x / width * 0.5, z / depth ) color.push( 0.0, 0.0 , 0.0 , z / depth ) } } this.uniforms.field = [ width, height, depth ] this.buffers.position = position this.buffers.color = color this.uniforms.size = ( h / 600) * pointsize * dpi }, }) //粒子 end /** * particleground * * @author jonathan nicol - @mrjnicol * @version 1.0.1 * @description creates a canvas based particle system background * * inspired by: * http://requestlab.fr/ * http://disruptivebydesign.com/ * * @license the mit license (mit) * * copyright (c) 2014 jonathan nicol - @mrjnicol * * permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "software"), to deal * in the software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the software, and to permit persons to whom the software is * furnished to do so, subject to the following conditions: * * the above copyright notice and this permission notice shall be included in * all copies or substantial portions of the software. * * the software is provided "as is", without warranty of any kind, express or * implied, including but not limited to the warranties of merchantability, * fitness for a particular purpose and noninfringement. in no event shall the * authors or copyright holders be liable for any claim, damages or other * liability, whether in an action of contract, tort or otherwise, arising from, * out of or in connection with the software or the use or other dealings in * the software. */ !function(a){function b(b,d){function e(){if(w){$canvas=a(''),v.prepend($canvas),p=$canvas[0],q=p.getcontext("2d"),f();for(var b=math.round(p.width*p.height/d.density),c=0;b>c;c++){var e=new l;e.setstackpos(c),x.push(e)}a(window).on("resize",function(){h()}),a(document).on("mousemove",function(a){y=a.pagex,z=a.pagey}),b&&!a&&window.addeventlistener("deviceorientation",function(){d=math.min(math.max(-event.beta,-30),30),c=math.min(math.max(-event.gamma,-30),30)},!0),g(),o("oninit")}}function f(){p.width=v.width(),p.height=v.height(),q.fillstyle=d.dotcolor,q.strokestyle=d.linecolor,q.linewidth=d.linewidth}function g(){if(w){s=a(window).width(),t=a(window).height(),q.clearrect(0,0,p.width,p.height);for(var b=0;b=0;i--)(x[i].position.x>v.width()||x[i].position.y>v.height())&&x.splice(i,1);var a=math.round(p.width*p.height/d.density);if(a>x.length)for(;a>x.length;){var b=new l;x.push(b)}else a=0;i--)x[i].setstackpos(i)}function j(){e=!0}function k(){e=!1,g()}function l(){switch(this.stackpos,this.active=!0,this.layer=math.ceil(3*math.random()),this.parallaxoffsetx=0,this.parallaxoffsety=0,this.position={x:math.ceil(math.random()*p.width),y:math.ceil(math.random()*p.height)},this.speed={},d.directionx){case"left":this.speed.x=+(-d.maxspeedx+math.random()*d.maxspeedx-d.minspeedx).tofixed(2);break;case"right":this.speed.x=+(math.random()*d.maxspeedx+d.minspeedx).tofixed(2);break;default:this.speed.x=+(-d.maxspeedx/2+math.random()*d.maxspeedx).tofixed(2),this.speed.x+=this.speed.x>0?d.minspeedx:-d.minspeedx}switch(d.directiony){case"up":this.speed.y=+(-d.maxspeedy+math.random()*d.maxspeedy-d.minspeedy).tofixed(2);break;case"down":this.speed.y=+(math.random()*d.maxspeedy+d.minspeedy).tofixed(2);break;default:this.speed.y=+(-d.maxspeedy/2+math.random()*d.maxspeedy).tofixed(2),this.speed.x+=this.speed.y>0?d.minspeedy:-d.minspeedy}}function m(a,b){return b?void(d[a]=b):d[a]}function n(){v.find(".pg-canvas").remove(),o("ondestroy"),v.removedata("plugin_"+c)}function o(a){void 0!==d[a]&&d[a].call(u)}var p,q,r,s,t,u=b,v=a(b),w=!!document.createelement("canvas").getcontext,x=[],y=0,z=0,a=!navigator.useragent.match(/(iphone|ipod|ipad|android|blackberry|bb10|mobi|tablet|opera mini|nexus 7)/i),b=!!window.deviceorientationevent,c=0,d=0,e=!1;return d=a.extend({},a.fn[c].defaults,d),l.prototype.draw=function(){q.beginpath(),q.arc(this.position.x+this.parallaxoffsetx,this.position.y+this.parallaxoffsety,d.particleradius/2,0,2*math.pi,!0),q.closepath(),q.fill(),q.beginpath();for(var a=x.length-1;a>this.stackpos;a--){var b=x[a],c=this.position.x-b.position.x,e=this.position.y-b.position.y,f=math.sqrt(c*c+e*e).tofixed(2);fv.width()&&(this.position.x=0-this.parallaxoffsetx);break;default:(this.position.x+this.speed.x+this.parallaxoffsetx>v.width()||this.position.x+this.speed.x+this.parallaxoffsetx<0)&&(this.speed.x=-this.speed.x)}switch(d.directiony){case"up":this.position.y+this.speed.y+this.parallaxoffsety<0&&(this.position.y=v.height()-this.parallaxoffsety);break;case"down":this.position.y+this.speed.y+this.parallaxoffsety>v.height()&&(this.position.y=0-this.parallaxoffsety);break;default:(this.position.y+this.speed.y+this.parallaxoffsety>v.height()||this.position.y+this.speed.y+this.parallaxoffsety<0)&&(this.speed.y=-this.speed.y)}this.position.x+=this.speed.x,this.position.y+=this.speed.y},l.prototype.setstackpos=function(a){this.stackpos=a},e(),{option:m,destroy:n,start:k,pause:j}}var c="particleground";a.fn[c]=function(d){if("string"==typeof arguments[0]){var e,f=arguments[0],g=array.prototype.slice.call(arguments,1);return this.each(function(){a.data(this,"plugin_"+c)&&"function"==typeof a.data(this,"plugin_"+c)[f]&&(e=a.data(this,"plugin_"+c)[f].apply(this,g))}),void 0!==e?e:this}return"object"!=typeof d&&d?void 0:this.each(function(){a.data(this,"plugin_"+c)||a.data(this,"plugin_"+c,new b(this,d))})},a.fn[c].defaults={minspeedx:.1,maxspeedx:.7,minspeedy:.1,maxspeedy:.7,directionx:"center",directiony:"center",density:1e4,dotcolor:"#666666",linecolor:"#666666",particleradius:7,linewidth:1,curvedlines:!1,proximity:100,parallax:!0,parallaxmultiplier:5,oninit:function(){},ondestroy:function(){}}}(jquery),/** * requestanimationframe polyfill by erik möller. fixes from paul irish and tino zijdel * @see: http://paulirish.com/2011/requestanimationframe-for-smart-animating/ * @see: http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating * @license: mit license */ function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c