Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
css
body { background-color: #999; margin: 0; overflow: hidden; } .label { position: absolute; top: 0; left: 0; padding: 5px 15px; color: #eee; font-size: 13px; background-color: rgba(0, 0, 0, .15); } .instructions { position: absolute; bottom: 0%; left: 0; padding: 5px 15px; color: #eee; font-size: 13px; background-color: rgba(0, 0, 0, .15); } canvas { display:block; }
JavaScript
(function(global){ var module = global.noise = {}; function Grad(x, y, z) { this.x = x; this.y = y; this.z = z; } Grad.prototype.dot2 = function(x, y) { return this.x*x + this.y*y; }; Grad.prototype.dot3 = function(x, y, z) { return this.x*x + this.y*y + this.z*z; }; var grad3 = [new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0), new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1), new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)]; var p = [151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; // To remove the need for index wrapping, double the permutation table length var perm = new Array(512); var gradP = new Array(512); // This isn't a very good seeding function, but it works ok. It supports 2^16 // different seed values. Write something better if you need more seeds. module.seed = function(seed) { if(seed > 0 && seed < 1) { // Scale the seed out seed *= 65536; } seed = Math.floor(seed); if(seed < 256) { seed |= seed << 8; } for(var i = 0; i < 256; i++) { var v; if (i & 1) { v = p[i] ^ (seed & 255); } else { v = p[i] ^ ((seed>>8) & 255); } perm[i] = perm[i + 256] = v; gradP[i] = gradP[i + 256] = grad3[v % 12]; } }; module.seed(0); /* for(var i=0; i<256; i++) { perm[i] = perm[i + 256] = p[i]; gradP[i] = gradP[i + 256] = grad3[perm[i] % 12]; }*/ // Skewing and unskewing factors for 2, 3, and 4 dimensions var F2 = 0.5*(Math.sqrt(3)-1); var G2 = (3-Math.sqrt(3))/6; var F3 = 1/3; var G3 = 1/6; // 2D simplex noise module.simplex2 = function(xin, yin) { var n0, n1, n2; // Noise contributions from the three corners // Skew the input space to determine which simplex cell we're in var s = (xin+yin)*F2; // Hairy factor for 2D var i = Math.floor(xin+s); var j = Math.floor(yin+s); var t = (i+j)*G2; var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. var y0 = yin-j+t; // For the 2D case, the simplex shape is an equilateral triangle. // Determine which simplex we are in. var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords if(x0>y0) { // lower triangle, XY order: (0,0)->(1,0)->(1,1) i1=1; j1=0; } else { // upper triangle, YX order: (0,0)->(0,1)->(1,1) i1=0; j1=1; } // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where // c = (3-sqrt(3))/6 var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords var y1 = y0 - j1 + G2; var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords var y2 = y0 - 1 + 2 * G2; // Work out the hashed gradient indices of the three simplex corners i &= 255; j &= 255; var gi0 = gradP[i+perm[j]]; var gi1 = gradP[i+i1+perm[j+j1]]; var gi2 = gradP[i+1+perm[j+1]]; // Calculate the contribution from the three corners var t0 = 0.5 - x0*x0-y0*y0; if(t0<0) { n0 = 0; } else { t0 *= t0; n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient } var t1 = 0.5 - x1*x1-y1*y1; if(t1<0) { n1 = 0; } else { t1 *= t1; n1 = t1 * t1 * gi1.dot2(x1, y1); } var t2 = 0.5 - x2*x2-y2*y2; if(t2<0) { n2 = 0; } else { t2 *= t2; n2 = t2 * t2 * gi2.dot2(x2, y2); } // Add contributions from each corner to get the final noise value. // The result is scaled to return values in the interval [-1,1]. return 70 * (n0 + n1 + n2); }; // 3D simplex noise module.simplex3 = function(xin, yin, zin) { var n0, n1, n2, n3; // Noise contributions from the four corners // Skew the input space to determine which simplex cell we're in var s = (xin+yin+zin)*F3; // Hairy factor for 2D var i = Math.floor(xin+s); var j = Math.floor(yin+s); var k = Math.floor(zin+s); var t = (i+j+k)*G3; var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. var y0 = yin-j+t; var z0 = zin-k+t; // For the 3D case, the simplex shape is a slightly irregular tetrahedron. // Determine which simplex we are in. var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords if(x0 >= y0) { if(y0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } else if(x0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } } else { if(y0 < z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } else if(x0 < z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } } // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where // c = 1/6. var x1 = x0 - i1 + G3; // Offsets for second corner var y1 = y0 - j1 + G3; var z1 = z0 - k1 + G3; var x2 = x0 - i2 + 2 * G3; // Offsets for third corner var y2 = y0 - j2 + 2 * G3; var z2 = z0 - k2 + 2 * G3; var x3 = x0 - 1 + 3 * G3; // Offsets for fourth corner var y3 = y0 - 1 + 3 * G3; var z3 = z0 - 1 + 3 * G3; // Work out the hashed gradient indices of the four simplex corners i &= 255; j &= 255; k &= 255; var gi0 = gradP[i+ perm[j+ perm[k ]]]; var gi1 = gradP[i+i1+perm[j+j1+perm[k+k1]]]; var gi2 = gradP[i+i2+perm[j+j2+perm[k+k2]]]; var gi3 = gradP[i+ 1+perm[j+ 1+perm[k+ 1]]]; // Calculate the contribution from the four corners var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; if(t0<0) { n0 = 0; } else { t0 *= t0; n0 = t0 * t0 * gi0.dot3(x0, y0, z0); // (x,y) of grad3 used for 2D gradient } var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; if(t1<0) { n1 = 0; } else { t1 *= t1; n1 = t1 * t1 * gi1.dot3(x1, y1, z1); } var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; if(t2<0) { n2 = 0; } else { t2 *= t2; n2 = t2 * t2 * gi2.dot3(x2, y2, z2); } var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; if(t3<0) { n3 = 0; } else { t3 *= t3; n3 = t3 * t3 * gi3.dot3(x3, y3, z3); } // Add contributions from each corner to get the final noise value. // The result is scaled to return values in the interval [-1,1]. return 32 * (n0 + n1 + n2 + n3); }; // ##### Perlin noise stuff function fade(t) { return t*t*t*(t*(t*6-15)+10); } function lerp(a, b, t) { return (1-t)*a + t*b; } // 2D Perlin Noise module.perlin2 = function(x, y) { // Find unit grid cell containing point var X = Math.floor(x), Y = Math.floor(y); // Get relative xy coordinates of point within that cell x = x - X; y = y - Y; // Wrap the integer cells at 255 (smaller integer period can be introduced here) X = X & 255; Y = Y & 255; // Calculate noise contributions from each of the four corners var n00 = gradP[X+perm[Y]].dot2(x, y); var n01 = gradP[X+perm[Y+1]].dot2(x, y-1); var n10 = gradP[X+1+perm[Y]].dot2(x-1, y); var n11 = gradP[X+1+perm[Y+1]].dot2(x-1, y-1); // Compute the fade curve value for x var u = fade(x); // Interpolate the four results return lerp( lerp(n00, n10, u), lerp(n01, n11, u), fade(y)); }; // 3D Perlin Noise module.perlin3 = function(x, y, z) { // Find unit grid cell containing point var X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z); // Get relative xyz coordinates of point within that cell x = x - X; y = y - Y; z = z - Z; // Wrap the integer cells at 255 (smaller integer period can be introduced here) X = X & 255; Y = Y & 255; Z = Z & 255; // Calculate noise contributions from each of the eight corners var n000 = gradP[X+ perm[Y+ perm[Z ]]].dot3(x, y, z); var n001 = gradP[X+ perm[Y+ perm[Z+1]]].dot3(x, y, z-1); var n010 = gradP[X+ perm[Y+1+perm[Z ]]].dot3(x, y-1, z); var n011 = gradP[X+ perm[Y+1+perm[Z+1]]].dot3(x, y-1, z-1); var n100 = gradP[X+1+perm[Y+ perm[Z ]]].dot3(x-1, y, z); var n101 = gradP[X+1+perm[Y+ perm[Z+1]]].dot3(x-1, y, z-1); var n110 = gradP[X+1+perm[Y+1+perm[Z ]]].dot3(x-1, y-1, z); var n111 = gradP[X+1+perm[Y+1+perm[Z+1]]].dot3(x-1, y-1, z-1); // Compute the fade curve value for x, y, z var u = fade(x); var v = fade(y); var w = fade(z); // Interpolate return lerp( lerp( lerp(n000, n100, u), lerp(n001, n101, u), w), lerp( lerp(n010, n110, u), lerp(n011, n111, u), w), v); }; })(this); //Cloth dynamics based on the tutorial at var ctx = canvas.getContext("2d"); //Fabric nodes var nodes = []; //Connections/constraints between nodes var links = []; //Two arrays to hold two bell curves for 'uniform' setting. Setting the wind field to be the max of the two at the same coordinate gives a repeating bell curve profile var wind_ = []; var wind_2 = []; //Wind field var wind = []; //Array for a pre-generated simplex noise field var _noise = []; canvas.width = window.innerWidth; canvas.height = window.innerHeight; function dist(x,y){ return Math.sqrt(x*x+y*y); } var time = Date.now(); var dt = 1/60; var TWO_PI = 2 * Math.PI; //Node count in x and y axes var width = 30; var height = 30; var nodeCount = width * height; //Noise element count in x axis var noise_width = width * 10; //Use noise.js library to generate a grid of 2D simplex noise values function generate_noise(){ //Pesudorandom seed used to generate simplex noise noise.seed(Math.random()); for (var y = 0; y < height; y++) { for (var x = 0; x < noise_width; x++) { // All noise functions return values in the range of -1 to 1 var value = noise.simplex2(x/width, y/height); //Set noise element to be a positive value of the simplex noise result for gusts in the wind field _noise.push(Math.abs(value)); } } } //Initialise arrays for (i = 0; i < nodeCount; i++) { wind_.push(0); wind_2.push(0); wind.push(0); } //Distance between nodes based on the smallest canvas dimension var delta = Math.min((canvas.width/2)/(width*1.5), (canvas.height/2)/(height*1.5)); var dx = delta; var dy = delta; //Largest distance allowed between nodes var max_dist = delta; var wind_variables = { //Only works for 'uniform' setting. The speed at which the mean of the bell curve travels along the x axis speed: 0.9, //Multiplier of the wind field strength: 50, //Controls the seeming 'elasticity of the fabric' iterations: 25, modes: "Wind mode", //Repeating bell curve uniform: false, //Simplex noise noise: true, //Show the wind field profile: false } //dat.gui library controls var gui = new dat.GUI(); var f0 = gui.addFolder('Cloth solver'); f0.add(wind_variables, 'iterations').min(1).max(100).step(1); var f1 = gui.addFolder('Wind properties'); f1.add(wind_variables, 'strength').min(0).max(100).step(1); f1.add(wind_variables, 'speed').min(0).max(1).step(0.1); var f2 = gui.addFolder('Wind mode'); f2.add(wind_variables, 'uniform').listen().onChange(function(value) { wind_variables.uniform = true; wind_variables.noise = false;} ); f2.add(wind_variables, 'noise').listen().onChange(function(value) { wind_variables.uniform = false; wind_variables.noise = true;} ); gui.add(wind_variables, 'profile'); //Create nodes for (i = 0; i < nodeCount; i++) { var node = { x: canvas.width/2 - width/2 * dx + Math.floor(i%width) * dx, y: canvas.height/2 - height/2 * dy + Math.floor(i/width) * dy, radius: 0, last_x: canvas.width/2 - width/2 * dx + Math.floor(i%width) * dx, last_y: canvas.height/2 - height/2 * dx + Math.floor(i/width) * dx,// + Math.random() * dy, static: false }; nodes.push(node); } //Pin the left hand side of the fabric in place for(i = 0; i < height; i++){ nodes[i*width].static = true; } function create_links(){ //X links for (i = 0; i < (nodes.length-1); i++) { if(((i+1)%width) > 0){ var link = { first: i, second: i+1 }; links.push(link); } } //Y links for (i = 0; i < (nodes.length-width); i++) { var link = { first: i, second: i+width }; links.push(link); } } //The fabric can be manipulated by grabbing it with a mouse canvas.addEventListener('mousemove', mouse_track); canvas.addEventListener('mousedown', mouse_down); canvas.addEventListener('mouseup', mouse_up); //Which node was grabbed var active_node; var mouse_pos_x; var mouse_pos_y; //Is mouse button held down var drag = false; function mouse_track(event) { mouse_pos_x = event.clientX; mouse_pos_y = event.clientY; if(drag){ if(active_node != -1){ nodes[active_node].x = mouse_pos_x; nodes[active_node].y = mouse_pos_y; nodes[active_node].last_x = mouse_pos_x; nodes[active_node].last_y = mouse_pos_y; } } } function mouse_down(event) { drag = true; mouse_pos_x = event.clientX; mouse_pos_y = event.clientY; active_node = -1; for(l = 0; l < nodes.length; l++){ if(dist(mouse_pos_x - nodes[l].x, mouse_pos_y - nodes[l].y) < 20){ active_node = l; if(active_node != -1){ nodes[active_node].x = mouse_pos_x; nodes[active_node].y = mouse_pos_y; nodes[active_node].last_x = mouse_pos_x; nodes[active_node].last_y = mouse_pos_y; } break; } } } function mouse_up(event) { drag = false; active_node = -1; } function resolve_constraints(){ //The two nodes between which we enforce a constraint var first; var second; //Distances in x and y axes var dx; var dy; //Total distance between nodes var d; //Proportional difference between largest allowed distance and actual distance between the nodes var diff; //Amount both nodes are to be moved to enforce constraint var translateX; var translateY; for(i = 0; i < wind_variables.iterations; i++){ for(l = 0; l < links.length; l++){ first = nodes[links[l].first]; second = nodes[links[l].second]; dx = first.x - second.x; dy = first.y - second.y; d = Math.sqrt(dx*dx+dy*dy); if(d > max_dist){ diff = (max_dist - d)/d; //Move both by half the difference, in opposite directions translateX = dx * 0.5 * diff; translateY = dy * 0.5 * diff; //If not pinned in place if(!first.static){ //If not grabbed with mouse if(links[l].first!= active_node){ first.x += translateX; first.y += translateY; } } //If not pinned in place if(!second.static){ //If not grabbed with mouse if(links[l].second!= active_node){ second.x -= translateX; second.y -= translateY; } } } } } } //For the 'noise' setting. Shows the offset of a width*height grid from 0 in a noise_width*height noise field var wind_offset = 0; function set_wind(){ if(wind_variables.uniform){ for(i = 0; i < wind.length; i++){ //Set wind to be the max of the two bell curve arrays wind[i] = Math.max(wind_[i], wind_2[i]); } } if(wind_variables.noise){ for(i = 0; i < wind.length; i++){ //Set the wind to be a section of the noise field wind[i] = wind_variables.strength*_noise[wind_offset + i +(Math.floor(i/width))*(noise_width-width)]; } } } //The two means of the bell curves var mean = 0; var mean_2 = -width; //Movement speed of the bell curves var speed = wind_variables.speed; //Multiplier of the wind field var strength = wind_variables.strength; function move(dt, t) { speed = wind_variables.speed; strength = wind_variables.strength; //Shift grid in noise field wind_offset--; if(wind_offset < 0 ){ //Reset to start of noise field wind_offset = (noise_width - width); } //Shift bell curve mean by speed mean += speed; //Reset mean to start if(mean > width*1.5){ mean = -0.5*width; } mean_2 += speed; if(mean_2 > width*1.5){ mean_2 = -0.5*width; } //Verlet variables var x_vel; var y_vel; var next_x; var next_y; var accX = 0; var accY = 9.8; for(i = 0; i < wind.length; i++){ wind_[i] = strength*Math.exp(-(Math.pow(i%(width) - mean, 2)/(2*width))); wind_2[i] = strength*Math.exp(-(Math.pow(i%width - (mean_2), 2)/(2*width))); } set_wind(); //Verlet integration based on positions, gravity, speed and wind for(i = 0; i < nodes.length; i++){ if(i != active_node){ accX = wind[i]; x_vel = nodes[i].x - nodes[i].last_x + accX * dt; y_vel = nodes[i].y - nodes[i].last_y + accY * dt; next_x = nodes[i].x + x_vel; next_y = nodes[i].y + y_vel; nodes[i].last_x = nodes[i].x; nodes[i].last_y = nodes[i].y; if(!nodes[i].static){ nodes[i].x = next_x; nodes[i].y = next_y; } } } //Nodes stop at canvas borders for(i = 0; i < nodes.length; i++){ if(nodes[i].x < 10){ nodes[i].x = 10; } if(nodes[i].y < 10){ nodes[i].y = 10; } if(nodes[i].x > canvas.width-10){ nodes[i].x = canvas.width-10; } if(nodes[i].y > canvas.height-10){ nodes[i].y = canvas.height-10; } } } create_links(); generate_noise(); //See below var fps; var newtime; var frametime; var accumulator = 0; var alpha; var step = 0; function draw() { step+=0.5; //Time step logic from: //http://gafferongames.com/game-physics/fix-your-timestep/ newtime = Date.now(); frametime = newtime - time; fps = 1000 / (frametime); time = newtime; //Effectively pause simulation when tab is out of focus if (fps > 10) { accumulator += frametime/1000; while ( accumulator >= dt ){ resolve_constraints(); move(dt, step); accumulator -= dt; } alpha = accumulator / dt; } canvas.width = window.innerWidth; canvas.height = window.innerHeight; ctx.fillStyle = "rgba(255,255,255, 0.7)"; //Draw nodes. Default radius is 0 for (i = 0; i < nodes.length; i++) { ctx.beginPath(); ctx.arc(nodes[i].x, nodes[i].y, nodes[i].radius, 0, TWO_PI); ctx.fill(); } if(wind_variables.profile){ //Draw nodes for wind field for (i = 0; i < wind.length; i++) { ctx.beginPath(); ctx.arc(canvas.width/8 + Math.floor(i%width) * dx, canvas.height/2 - (height/2 * dy) + dx * Math.floor(i/width) - wind[i], 1, 0, TWO_PI); ctx.fill(); } } //Draw links between nodes ctx.strokeStyle = "rgba(215,215,215,1)"; ctx.beginPath(); for(l = 0; l < links.length; l++){ ctx.moveTo(nodes[links[l].first].x, nodes[links[l].first].y); ctx.lineTo(nodes[links[l].second].x, nodes[links[l].second].y); } ctx.stroke(); window.requestAnimationFrame(draw); } window.requestAnimationFrame(draw);
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>旗帜-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号