├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── book ├── favicon.ico ├── index.html └── pt.js ├── diffusion ├── index.html └── pt.min.js ├── einstein ├── favicon.ico ├── index.html └── pt.js ├── favicon.ico ├── favicon_4.ico ├── favicon_5.ico ├── favicon_6.ico ├── favicon_7.ico ├── favicon_8.ico ├── favicon_9.ico ├── fittext.js ├── index.html ├── index.js ├── life ├── favicon.ico ├── index.html ├── index.js ├── lodash.js ├── parse.js └── pt.js ├── lorenz ├── favicon.ico ├── index.html ├── index.js ├── pt.js ├── satin.mp3 └── satin.ogg ├── moire ├── favicon.ico ├── index.html ├── jquery.js ├── pt.js ├── velocity.js └── velocity.ui.js ├── ogimage.png ├── perlin.js ├── perlin ├── ifvisible.js ├── index.html ├── perlin.js └── pt.js ├── pt.min.js ├── radial ├── favicon.ico ├── index.html ├── interpolate.js ├── pt.js ├── re.js ├── re.min.js └── reset.css ├── satoshi ├── favicon.ico ├── index.html ├── play.svg ├── pt.js ├── rebound.js ├── satoshi.mp3 └── satoshi.ogg ├── sine ├── favicon.ico ├── index.html └── pt.js ├── springy ├── bliss.min.js ├── favicon.ico ├── index.html └── rebound.min.js ├── template.ico ├── vectorfield ├── favicon.ico ├── index.html └── pt.js └── vortex ├── LBM.js ├── index.html └── pt.min.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.{js,json}] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .log 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Dennis Jin 3 | 4 | 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: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | 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. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eex - eexperiments 2 | 3 | > Collection of tiny *eexperiments* built with web technologies. 4 | 5 | ## ..eex? 6 | 7 | eex is a growing collection of creative code experiments built using web technologies such as Canvas. I will try my best to regularly add new *eexperiments* to the repo and keep things interesting. Looking forward to learning lots of awesome things this year :chicken: 8 | 9 | Go ahead and visit the [project site](http://tofuness.github.io/eex/) if you haven't! 10 | 11 | ## Notes 12 | 13 | Ideally, all experiments should stay small and easily accessible. In other words, keep dependency bloat to a minimum. Most experiments were built using [Pt.js](https://github.com/williamngan/pt). Feel free to send in any PRs. 14 | 15 | ## Install 16 | 17 | Clone the repo. Everything should run in the browser. Report any problems through the issue tracker. 18 | 19 | ## License 20 | 21 | MIT © [Dennis Jin](https://github.com/tofuness) 22 | -------------------------------------------------------------------------------- /book/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/book/favicon.ico -------------------------------------------------------------------------------- /book/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | eex - Studies & Further Studies In a Dying Culture 5 | 6 | 7 | 11 | 16 | 98 | 99 | 100 |
101 | Based on an animation from 102 |
Covers 108 | by Henning M. Lederer 109 |
110 |
111 | Built by Dennis Jin / 112 | dennisjin.com 113 |
114 | Open-sourced on Github

116 | View more eexperiments 117 |
118 |
119 |
120 |
121 | Christopher Caudwell 122 |
123 |
124 | Studies & Further Studies
125 | In a Dying Culture 126 |
127 |
128 | With an Introduction by Sol Yurick 129 |
130 |
131 |
132 | 133 | 170 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /diffusion/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vortex 5 | 63 | 64 | 65 |
66 |
67 | 68 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /einstein/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/einstein/favicon.ico -------------------------------------------------------------------------------- /einstein/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Einstein Waves 5 | 6 | 7 | 8 | 9 | 101 | 102 | 103 |
104 |
105 |
106 |
107 |
108 | Einstein Waves 109 | 110 |
111 |
112 | Move mouse to interact 113 |
114 |
115 |
116 |
Built by Dennis Jin / dennisjin.com
117 |
Souce code on Github · View more eexperiments
118 |
119 |
120 |
121 | 122 | 201 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/favicon.ico -------------------------------------------------------------------------------- /favicon_4.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/favicon_4.ico -------------------------------------------------------------------------------- /favicon_5.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/favicon_5.ico -------------------------------------------------------------------------------- /favicon_6.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/favicon_6.ico -------------------------------------------------------------------------------- /favicon_7.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/favicon_7.ico -------------------------------------------------------------------------------- /favicon_8.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/favicon_8.ico -------------------------------------------------------------------------------- /favicon_9.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/favicon_9.ico -------------------------------------------------------------------------------- /fittext.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * FitText.js 1.0 jQuery free version 3 | * 4 | * Copyright 2011, Dave Rupert http://daverupert.com 5 | * Released under the WTFPL license 6 | * http://sam.zoy.org/wtfpl/ 7 | * Modified by Slawomir Kolodziej http://slawekk.info 8 | * 9 | * Date: Tue Aug 09 2011 10:45:54 GMT+0200 (CEST) 10 | */ 11 | (function(){ 12 | var css = function (el, prop) { 13 | return window.getComputedStyle ? getComputedStyle(el).getPropertyValue(prop) : el.currentStyle[prop]; 14 | }; 15 | 16 | var addEvent = function (el, type, fn) { 17 | if (el.addEventListener) 18 | el.addEventListener(type, fn, false); 19 | else 20 | el.attachEvent('on'+type, fn); 21 | }; 22 | 23 | var extend = function(obj,ext){ 24 | for(var key in ext) 25 | if(ext.hasOwnProperty(key)) 26 | obj[key] = ext[key]; 27 | return obj; 28 | }; 29 | 30 | window.fitText = function (el, kompressor, options) { 31 | 32 | var settings = extend({ 33 | 'minFontSize' : -1/0, 34 | 'maxFontSize' : 1/0 35 | },options); 36 | 37 | var fit = function (el) { 38 | var compressor = kompressor || 1; 39 | 40 | var resizer = function () { 41 | el.style.fontSize = Math.max(Math.min(el.clientWidth / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)) + 'px'; 42 | }; 43 | 44 | // Call once to set. 45 | resizer(); 46 | 47 | // Bind events 48 | // If you have any js library which support Events, replace this part 49 | // and remove addEvent function (or use original jQuery version) 50 | addEvent(window, 'resize', resizer); 51 | }; 52 | 53 | if (el.length) 54 | for(var i=0; i 2 | 3 | 4 | 5 | 6 | 7 | eex - collection of web eexperiments 8 | 9 | 10 | 11 | 12 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 33 | 34 | 38 | 271 | 272 | 273 | 285 |
286 | 291 | 296 | 301 | 306 | 311 | 316 | 321 | 326 | 331 | 336 |
337 |
338 | 339 | 340 | 341 | 475 | 499 | 500 | 501 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | riot.tag2('html', ' tofuness - eex
eex is a collection of web eexperiments
Built by Dennis Jin / dennisjin.com. Open-sourced on Github.
', '* { box-sizing: border-box; } html { overflow-x: hidden; font-family: Arial, sans-serif; background: #111; } #about-description a, #about-description a:visited { color: #fff; text-decoration: none; box-shadow: 0 1px 0 #fff; } #about-description a:hover { color: #fff; box-shadow: 0 2px 0 #fff; } #eex { cursor: default; font-weight: 700; } #about { color: #fff; text-align: center; } #about-title { padding: 40px 20px 10px 20px; font-size: 18px; } #about-description { color: #999; font-size: 12px; line-height: 1.5; } #about-list { padding-top: 40px; width: 100%; } .about-item { padding: 0 20px; overflow: hidden; display: block; margin-bottom: 20px; width: 100%; white-space: nowrap; text-overflow: ellipsis; color: #666; font-size: 82px; text-decoration: none; text-align: center; transform: translateX(0); -webkit-transition: all 240ms cubic-bezier(0.165, 0.84, 0.44, 1); transition: all 240ms cubic-bezier(0.165, 0.84, 0.44, 1); } .about-item:hover { color: #fff; transform: translateX(10px); } .latest { padding: 0 10px; background: #999; } @media (max-width : 730px) { .mobile-newline:after { content: \'\\a\'; white-space: pre; } }', '', function(opts) { 3 | /*! 4 | * FitText.js 1.0 jQuery free version 5 | * 6 | * Copyright 2011, Dave Rupert http://daverupert.com 7 | * Released under the WTFPL license 8 | * http://sam.zoy.org/wtfpl/ 9 | * Modified by Slawomir Kolodziej http://slawekk.info 10 | * 11 | * Date: Tue Aug 09 2011 10:45:54 GMT+0200 (CEST) 12 | */ 13 | (function(){ 14 | var css = function (el, prop) { 15 | return window.getComputedStyle ? getComputedStyle(el).getPropertyValue(prop) : el.currentStyle[prop]; 16 | }; 17 | 18 | var addEvent = function (el, type, fn) { 19 | if (el.addEventListener) 20 | el.addEventListener(type, fn, false); 21 | else 22 | el.attachEvent('on'+type, fn); 23 | }; 24 | 25 | var extend = function(obj,ext){ 26 | for(var key in ext) 27 | if(ext.hasOwnProperty(key)) 28 | obj[key] = ext[key]; 29 | return obj; 30 | }; 31 | 32 | window.fitText = function (el, kompressor, options) { 33 | 34 | var settings = extend({ 35 | 'minFontSize' : -1/0, 36 | 'maxFontSize' : 1/0 37 | },options); 38 | 39 | var fit = function (el) { 40 | var compressor = kompressor || 1; 41 | 42 | var resizer = function () { 43 | el.style.fontSize = Math.max(Math.min(el.clientWidth / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)) + 'px'; 44 | }; 45 | 46 | // Call once to set. 47 | resizer(); 48 | 49 | // Bind events 50 | // If you have any js library which support Events, replace this part 51 | // and remove addEvent function (or use original jQuery version) 52 | addEvent(window, 'resize', resizer); 53 | }; 54 | 55 | if (el.length) 56 | for(var i=0; it?false:(t==n.length-1?n.pop():G.call(n,t,1),true)},o.prototype.get=function(t){var n=this.__data__; 12 | return t=u(n,t),0>t?j:n[t][1]},o.prototype.has=function(t){return-1r?e.push([t,n]):e[r][1]=n,this},i.prototype.clear=function(){this.__data__={hash:new r,map:new(L||o),string:new r}},i.prototype["delete"]=function(t){return c(this,t)["delete"](t)},i.prototype.get=function(t){return c(this,t).get(t)},i.prototype.has=function(t){return c(this,t).has(t)},i.prototype.set=function(t,n){return c(this,t).set(t,n),this; 13 | };var V=_(function(t){var n=[];return d(t).replace($,function(t,e,r,o){n.push(r?o.replace(w,"$1"):e||t)}),n});_.Cache=i;var B=Array.isArray;e.memoize=_,e.set=function(t,n,e){if(null!=t){n=f(n,t)?[n]:a(n);for(var r=-1,o=n.length,i=o-1,u=t;null!=u&&++r-1&&0==p%1&&_>p?[]:{};l=p}}var p=u,_=c,y=p[_];T.call(p,_)&&h(y,l)&&(l!==j||_ in p)||(p[_]=l); 14 | }u=u[c]}}return t},e.eq=h,e.get=function(t,n,e){if(null==t)t=j;else{n=f(n,t)?[n]:a(n);for(var r=0,o=n.length;null!=t&&o>r;)t=t[s(n[r++])];t=r&&r==o?t:j}return t===j?e:t},e.isArray=B,e.isFunction=y,e.isObject=v,e.isObjectLike=g,e.isSymbol=b,e.toString=d,e.VERSION="4.13.1",(A||{})._=e,k._=e}).call(this); -------------------------------------------------------------------------------- /life/parse.js: -------------------------------------------------------------------------------- 1 | // Parses a 1.06 .lif file to stdout 2 | // Works on Node 6.10 3 | 4 | /* 5 | Usage: 6 | $ node parse.js somefile.lif | output 7 | */ 8 | 9 | const fs = require('fs'); 10 | const os = require('os'); 11 | const util = require('util'); 12 | 13 | const args = process.argv.splice(2); 14 | const input = fs.readFileSync(args[0], { encoding: 'utf-8' }) 15 | .split(os.EOL) 16 | .filter((line) => line.indexOf('#') === -1) 17 | .filter((line) => line !== '') 18 | .map((line) => line.split(' ').map((offset) => parseInt(offset, 10))); 19 | 20 | console.log(JSON.stringify(input)); 21 | -------------------------------------------------------------------------------- /lorenz/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/lorenz/favicon.ico -------------------------------------------------------------------------------- /lorenz/satin.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/lorenz/satin.mp3 -------------------------------------------------------------------------------- /lorenz/satin.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/lorenz/satin.ogg -------------------------------------------------------------------------------- /moire/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/moire/favicon.ico -------------------------------------------------------------------------------- /moire/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Simple Moiré Pattern 5 | 6 | 7 | 8 | 9 | 103 | 104 | 105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | simple moiré pattern 114 |
115 |
116 | to interact 117 |
118 |
119 | 120 | 121 |
122 |
123 | 124 | 125 | 126 | 127 | 192 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /moire/velocity.ui.js: -------------------------------------------------------------------------------- 1 | /* VelocityJS.org UI Pack (5.0.4). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License. Portions copyright Daniel Eden, Christian Pucci. */ 2 | !function(t){"function"==typeof require&&"object"==typeof exports?module.exports=t():"function"==typeof define&&define.amd?define(["velocity"],t):t()}(function(){return function(t,a,e,r){function n(t,a){var e=[];return t&&a?($.each([t,a],function(t,a){var r=[];$.each(a,function(t,a){for(;a.toString().length<5;)a="0"+a;r.push(a)}),e.push(r.join(""))}),parseFloat(e[0])>parseFloat(e[1])):!1}if(!t.Velocity||!t.Velocity.Utilities)return void(a.console&&console.log("Velocity UI Pack: Velocity must be loaded first. Aborting."));var i=t.Velocity,$=i.Utilities,s=i.version,o={major:1,minor:1,patch:0};if(n(o,s)){var l="Velocity UI Pack: You need to update Velocity (jquery.velocity.js) to a newer version. Visit http://github.com/julianshapiro/velocity.";throw alert(l),new Error(l)}i.RegisterEffect=i.RegisterUI=function(t,a){function e(t,a,e,r){var n=0,s;$.each(t.nodeType?[t]:t,function(t,a){r&&(e+=t*r),s=a.parentNode,$.each(["height","paddingTop","paddingBottom","marginTop","marginBottom"],function(t,e){n+=parseFloat(i.CSS.getPropertyValue(a,e))})}),i.animate(s,{height:("In"===a?"+":"-")+"="+n},{queue:!1,easing:"ease-in-out",duration:e*("In"===a?.6:1)})}return i.Redirects[t]=function(n,s,o,l,c,u){function f(){s.display!==r&&"none"!==s.display||!/Out$/.test(t)||$.each(c.nodeType?[c]:c,function(t,a){i.CSS.setPropertyValue(a,"display","none")}),s.complete&&s.complete.call(c,c),u&&u.resolver(c||n)}var p=o===l-1;a.defaultDuration="function"==typeof a.defaultDuration?a.defaultDuration.call(c,c):parseFloat(a.defaultDuration);for(var d=0;d1&&($.each(a.reverse(),function(t,e){var r=a[t+1];if(r){var n=e.o||e.options,s=r.o||r.options,o=n&&n.sequenceQueue===!1?"begin":"complete",l=s&&s[o],c={};c[o]=function(){var t=r.e||r.elements,a=t.nodeType?[t]:t;l&&l.call(a,a),i(e)},r.o?r.o=$.extend({},s,c):r.options=$.extend({},s,c)}}),a.reverse()),i(a[0])}}(window.jQuery||window.Zepto||window,window,document)}); 3 | -------------------------------------------------------------------------------- /ogimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/ogimage.png -------------------------------------------------------------------------------- /perlin.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A speed-improved perlin and simplex noise algorithms for 2D. 3 | * 4 | * Based on example code by Stefan Gustavson (stegu@itn.liu.se). 5 | * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu). 6 | * Better rank ordering method by Stefan Gustavson in 2012. 7 | * Converted to Javascript by Joseph Gentle. 8 | * 9 | * Version 2012-03-09 10 | * 11 | * This code was placed in the public domain by its original author, 12 | * Stefan Gustavson. You may use it as you see fit, but 13 | * attribution is appreciated. 14 | * 15 | */ 16 | 17 | (function(global){ 18 | var module = global.noise = {}; 19 | 20 | function Grad(x, y, z) { 21 | this.x = x; this.y = y; this.z = z; 22 | } 23 | 24 | Grad.prototype.dot2 = function(x, y) { 25 | return this.x*x + this.y*y; 26 | }; 27 | 28 | Grad.prototype.dot3 = function(x, y, z) { 29 | return this.x*x + this.y*y + this.z*z; 30 | }; 31 | 32 | var grad3 = [new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0), 33 | new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1), 34 | new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)]; 35 | 36 | var p = [151,160,137,91,90,15, 37 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 38 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 39 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 40 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 41 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 42 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 43 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 44 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 45 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 46 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 47 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 48 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; 49 | // To remove the need for index wrapping, double the permutation table length 50 | var perm = new Array(512); 51 | var gradP = new Array(512); 52 | 53 | // This isn't a very good seeding function, but it works ok. It supports 2^16 54 | // different seed values. Write something better if you need more seeds. 55 | module.seed = function(seed) { 56 | if(seed > 0 && seed < 1) { 57 | // Scale the seed out 58 | seed *= 65536; 59 | } 60 | 61 | seed = Math.floor(seed); 62 | if(seed < 256) { 63 | seed |= seed << 8; 64 | } 65 | 66 | for(var i = 0; i < 256; i++) { 67 | var v; 68 | if (i & 1) { 69 | v = p[i] ^ (seed & 255); 70 | } else { 71 | v = p[i] ^ ((seed>>8) & 255); 72 | } 73 | 74 | perm[i] = perm[i + 256] = v; 75 | gradP[i] = gradP[i + 256] = grad3[v % 12]; 76 | } 77 | }; 78 | 79 | module.seed(0); 80 | 81 | /* 82 | for(var i=0; i<256; i++) { 83 | perm[i] = perm[i + 256] = p[i]; 84 | gradP[i] = gradP[i + 256] = grad3[perm[i] % 12]; 85 | }*/ 86 | 87 | // Skewing and unskewing factors for 2, 3, and 4 dimensions 88 | var F2 = 0.5*(Math.sqrt(3)-1); 89 | var G2 = (3-Math.sqrt(3))/6; 90 | 91 | var F3 = 1/3; 92 | var G3 = 1/6; 93 | 94 | // 2D simplex noise 95 | module.simplex2 = function(xin, yin) { 96 | var n0, n1, n2; // Noise contributions from the three corners 97 | // Skew the input space to determine which simplex cell we're in 98 | var s = (xin+yin)*F2; // Hairy factor for 2D 99 | var i = Math.floor(xin+s); 100 | var j = Math.floor(yin+s); 101 | var t = (i+j)*G2; 102 | var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. 103 | var y0 = yin-j+t; 104 | // For the 2D case, the simplex shape is an equilateral triangle. 105 | // Determine which simplex we are in. 106 | var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords 107 | if(x0>y0) { // lower triangle, XY order: (0,0)->(1,0)->(1,1) 108 | i1=1; j1=0; 109 | } else { // upper triangle, YX order: (0,0)->(0,1)->(1,1) 110 | i1=0; j1=1; 111 | } 112 | // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and 113 | // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where 114 | // c = (3-sqrt(3))/6 115 | var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords 116 | var y1 = y0 - j1 + G2; 117 | var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords 118 | var y2 = y0 - 1 + 2 * G2; 119 | // Work out the hashed gradient indices of the three simplex corners 120 | i &= 255; 121 | j &= 255; 122 | var gi0 = gradP[i+perm[j]]; 123 | var gi1 = gradP[i+i1+perm[j+j1]]; 124 | var gi2 = gradP[i+1+perm[j+1]]; 125 | // Calculate the contribution from the three corners 126 | var t0 = 0.5 - x0*x0-y0*y0; 127 | if(t0<0) { 128 | n0 = 0; 129 | } else { 130 | t0 *= t0; 131 | n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient 132 | } 133 | var t1 = 0.5 - x1*x1-y1*y1; 134 | if(t1<0) { 135 | n1 = 0; 136 | } else { 137 | t1 *= t1; 138 | n1 = t1 * t1 * gi1.dot2(x1, y1); 139 | } 140 | var t2 = 0.5 - x2*x2-y2*y2; 141 | if(t2<0) { 142 | n2 = 0; 143 | } else { 144 | t2 *= t2; 145 | n2 = t2 * t2 * gi2.dot2(x2, y2); 146 | } 147 | // Add contributions from each corner to get the final noise value. 148 | // The result is scaled to return values in the interval [-1,1]. 149 | return 70 * (n0 + n1 + n2); 150 | }; 151 | 152 | // 3D simplex noise 153 | module.simplex3 = function(xin, yin, zin) { 154 | var n0, n1, n2, n3; // Noise contributions from the four corners 155 | 156 | // Skew the input space to determine which simplex cell we're in 157 | var s = (xin+yin+zin)*F3; // Hairy factor for 2D 158 | var i = Math.floor(xin+s); 159 | var j = Math.floor(yin+s); 160 | var k = Math.floor(zin+s); 161 | 162 | var t = (i+j+k)*G3; 163 | var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. 164 | var y0 = yin-j+t; 165 | var z0 = zin-k+t; 166 | 167 | // For the 3D case, the simplex shape is a slightly irregular tetrahedron. 168 | // Determine which simplex we are in. 169 | var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords 170 | var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords 171 | if(x0 >= y0) { 172 | if(y0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } 173 | else if(x0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } 174 | else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } 175 | } else { 176 | if(y0 < z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } 177 | else if(x0 < z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } 178 | else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } 179 | } 180 | // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), 181 | // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and 182 | // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where 183 | // c = 1/6. 184 | var x1 = x0 - i1 + G3; // Offsets for second corner 185 | var y1 = y0 - j1 + G3; 186 | var z1 = z0 - k1 + G3; 187 | 188 | var x2 = x0 - i2 + 2 * G3; // Offsets for third corner 189 | var y2 = y0 - j2 + 2 * G3; 190 | var z2 = z0 - k2 + 2 * G3; 191 | 192 | var x3 = x0 - 1 + 3 * G3; // Offsets for fourth corner 193 | var y3 = y0 - 1 + 3 * G3; 194 | var z3 = z0 - 1 + 3 * G3; 195 | 196 | // Work out the hashed gradient indices of the four simplex corners 197 | i &= 255; 198 | j &= 255; 199 | k &= 255; 200 | var gi0 = gradP[i+ perm[j+ perm[k ]]]; 201 | var gi1 = gradP[i+i1+perm[j+j1+perm[k+k1]]]; 202 | var gi2 = gradP[i+i2+perm[j+j2+perm[k+k2]]]; 203 | var gi3 = gradP[i+ 1+perm[j+ 1+perm[k+ 1]]]; 204 | 205 | // Calculate the contribution from the four corners 206 | var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; 207 | if(t0<0) { 208 | n0 = 0; 209 | } else { 210 | t0 *= t0; 211 | n0 = t0 * t0 * gi0.dot3(x0, y0, z0); // (x,y) of grad3 used for 2D gradient 212 | } 213 | var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; 214 | if(t1<0) { 215 | n1 = 0; 216 | } else { 217 | t1 *= t1; 218 | n1 = t1 * t1 * gi1.dot3(x1, y1, z1); 219 | } 220 | var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; 221 | if(t2<0) { 222 | n2 = 0; 223 | } else { 224 | t2 *= t2; 225 | n2 = t2 * t2 * gi2.dot3(x2, y2, z2); 226 | } 227 | var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; 228 | if(t3<0) { 229 | n3 = 0; 230 | } else { 231 | t3 *= t3; 232 | n3 = t3 * t3 * gi3.dot3(x3, y3, z3); 233 | } 234 | // Add contributions from each corner to get the final noise value. 235 | // The result is scaled to return values in the interval [-1,1]. 236 | return 32 * (n0 + n1 + n2 + n3); 237 | 238 | }; 239 | 240 | // ##### Perlin noise stuff 241 | 242 | function fade(t) { 243 | return t*t*t*(t*(t*6-15)+10); 244 | } 245 | 246 | function lerp(a, b, t) { 247 | return (1-t)*a + t*b; 248 | } 249 | 250 | // 2D Perlin Noise 251 | module.perlin2 = function(x, y) { 252 | // Find unit grid cell containing point 253 | var X = Math.floor(x), Y = Math.floor(y); 254 | // Get relative xy coordinates of point within that cell 255 | x = x - X; y = y - Y; 256 | // Wrap the integer cells at 255 (smaller integer period can be introduced here) 257 | X = X & 255; Y = Y & 255; 258 | 259 | // Calculate noise contributions from each of the four corners 260 | var n00 = gradP[X+perm[Y]].dot2(x, y); 261 | var n01 = gradP[X+perm[Y+1]].dot2(x, y-1); 262 | var n10 = gradP[X+1+perm[Y]].dot2(x-1, y); 263 | var n11 = gradP[X+1+perm[Y+1]].dot2(x-1, y-1); 264 | 265 | // Compute the fade curve value for x 266 | var u = fade(x); 267 | 268 | // Interpolate the four results 269 | return lerp( 270 | lerp(n00, n10, u), 271 | lerp(n01, n11, u), 272 | fade(y)); 273 | }; 274 | 275 | // 3D Perlin Noise 276 | module.perlin3 = function(x, y, z) { 277 | // Find unit grid cell containing point 278 | var X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z); 279 | // Get relative xyz coordinates of point within that cell 280 | x = x - X; y = y - Y; z = z - Z; 281 | // Wrap the integer cells at 255 (smaller integer period can be introduced here) 282 | X = X & 255; Y = Y & 255; Z = Z & 255; 283 | 284 | // Calculate noise contributions from each of the eight corners 285 | var n000 = gradP[X+ perm[Y+ perm[Z ]]].dot3(x, y, z); 286 | var n001 = gradP[X+ perm[Y+ perm[Z+1]]].dot3(x, y, z-1); 287 | var n010 = gradP[X+ perm[Y+1+perm[Z ]]].dot3(x, y-1, z); 288 | var n011 = gradP[X+ perm[Y+1+perm[Z+1]]].dot3(x, y-1, z-1); 289 | var n100 = gradP[X+1+perm[Y+ perm[Z ]]].dot3(x-1, y, z); 290 | var n101 = gradP[X+1+perm[Y+ perm[Z+1]]].dot3(x-1, y, z-1); 291 | var n110 = gradP[X+1+perm[Y+1+perm[Z ]]].dot3(x-1, y-1, z); 292 | var n111 = gradP[X+1+perm[Y+1+perm[Z+1]]].dot3(x-1, y-1, z-1); 293 | 294 | // Compute the fade curve value for x, y, z 295 | var u = fade(x); 296 | var v = fade(y); 297 | var w = fade(z); 298 | 299 | // Interpolate 300 | return lerp( 301 | lerp( 302 | lerp(n000, n100, u), 303 | lerp(n001, n101, u), w), 304 | lerp( 305 | lerp(n010, n110, u), 306 | lerp(n011, n111, u), w), 307 | v); 308 | }; 309 | 310 | })(this); 311 | -------------------------------------------------------------------------------- /perlin/ifvisible.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | (function(root, factory) { 3 | if (typeof define === 'function' && define.amd) { 4 | return define(function() { 5 | return factory(); 6 | }); 7 | } else if (typeof exports === 'object') { 8 | return module.exports = factory(); 9 | } else { 10 | return root.ifvisible = factory(); 11 | } 12 | })(this, function() { 13 | var addEvent, customEvent, doc, fireEvent, hidden, idleStartedTime, idleTime, ie, ifvisible, init, initialized, status, trackIdleStatus, visibilityChange; 14 | ifvisible = {}; 15 | doc = document; 16 | initialized = false; 17 | status = "active"; 18 | idleTime = 60000; 19 | idleStartedTime = false; 20 | customEvent = (function() { 21 | var S4, addCustomEvent, cgid, fireCustomEvent, guid, listeners, removeCustomEvent; 22 | S4 = function() { 23 | return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); 24 | }; 25 | guid = function() { 26 | return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4(); 27 | }; 28 | listeners = {}; 29 | cgid = '__ceGUID'; 30 | addCustomEvent = function(obj, event, callback) { 31 | obj[cgid] = undefined; 32 | if (!obj[cgid]) { 33 | obj[cgid] = "ifvisible.object.event.identifier"; 34 | } 35 | if (!listeners[obj[cgid]]) { 36 | listeners[obj[cgid]] = {}; 37 | } 38 | if (!listeners[obj[cgid]][event]) { 39 | listeners[obj[cgid]][event] = []; 40 | } 41 | return listeners[obj[cgid]][event].push(callback); 42 | }; 43 | fireCustomEvent = function(obj, event, memo) { 44 | var ev, j, len, ref, results; 45 | if (obj[cgid] && listeners[obj[cgid]] && listeners[obj[cgid]][event]) { 46 | ref = listeners[obj[cgid]][event]; 47 | results = []; 48 | for (j = 0, len = ref.length; j < len; j++) { 49 | ev = ref[j]; 50 | results.push(ev(memo || {})); 51 | } 52 | return results; 53 | } 54 | }; 55 | removeCustomEvent = function(obj, event, callback) { 56 | var cl, i, j, len, ref; 57 | if (callback) { 58 | if (obj[cgid] && listeners[obj[cgid]] && listeners[obj[cgid]][event]) { 59 | ref = listeners[obj[cgid]][event]; 60 | for (i = j = 0, len = ref.length; j < len; i = ++j) { 61 | cl = ref[i]; 62 | if (cl === callback) { 63 | listeners[obj[cgid]][event].splice(i, 1); 64 | return cl; 65 | } 66 | } 67 | } 68 | } else { 69 | if (obj[cgid] && listeners[obj[cgid]] && listeners[obj[cgid]][event]) { 70 | return delete listeners[obj[cgid]][event]; 71 | } 72 | } 73 | }; 74 | return { 75 | add: addCustomEvent, 76 | remove: removeCustomEvent, 77 | fire: fireCustomEvent 78 | }; 79 | })(); 80 | addEvent = (function() { 81 | var setListener; 82 | setListener = false; 83 | return function(el, ev, fn) { 84 | if (!setListener) { 85 | if (el.addEventListener) { 86 | setListener = function(el, ev, fn) { 87 | return el.addEventListener(ev, fn, false); 88 | }; 89 | } else if (el.attachEvent) { 90 | setListener = function(el, ev, fn) { 91 | return el.attachEvent('on' + ev, fn, false); 92 | }; 93 | } else { 94 | setListener = function(el, ev, fn) { 95 | return el['on' + ev] = fn; 96 | }; 97 | } 98 | } 99 | return setListener(el, ev, fn); 100 | }; 101 | })(); 102 | fireEvent = function(element, event) { 103 | var evt; 104 | if (doc.createEventObject) { 105 | return element.fireEvent('on' + event, evt); 106 | } else { 107 | evt = doc.createEvent('HTMLEvents'); 108 | evt.initEvent(event, true, true); 109 | return !element.dispatchEvent(evt); 110 | } 111 | }; 112 | ie = (function() { 113 | var all, check, div, undef, v; 114 | undef = void 0; 115 | v = 3; 116 | div = doc.createElement("div"); 117 | all = div.getElementsByTagName("i"); 118 | check = function() { 119 | return (div.innerHTML = "", all[0]); 120 | }; 121 | while (check()) { 122 | continue; 123 | } 124 | if (v > 4) { 125 | return v; 126 | } else { 127 | return undef; 128 | } 129 | })(); 130 | hidden = false; 131 | visibilityChange = void 0; 132 | if (typeof doc.hidden !== "undefined") { 133 | hidden = "hidden"; 134 | visibilityChange = "visibilitychange"; 135 | } else if (typeof doc.mozHidden !== "undefined") { 136 | hidden = "mozHidden"; 137 | visibilityChange = "mozvisibilitychange"; 138 | } else if (typeof doc.msHidden !== "undefined") { 139 | hidden = "msHidden"; 140 | visibilityChange = "msvisibilitychange"; 141 | } else if (typeof doc.webkitHidden !== "undefined") { 142 | hidden = "webkitHidden"; 143 | visibilityChange = "webkitvisibilitychange"; 144 | } 145 | trackIdleStatus = function() { 146 | var timer, wakeUp; 147 | timer = false; 148 | wakeUp = function() { 149 | clearTimeout(timer); 150 | if (status !== "active") { 151 | ifvisible.wakeup(); 152 | } 153 | idleStartedTime = +(new Date()); 154 | return timer = setTimeout(function() { 155 | if (status === "active") { 156 | return ifvisible.idle(); 157 | } 158 | }, idleTime); 159 | }; 160 | wakeUp(); 161 | addEvent(doc, "mousemove", wakeUp); 162 | addEvent(doc, "keyup", wakeUp); 163 | addEvent(window, "scroll", wakeUp); 164 | ifvisible.focus(wakeUp); 165 | return ifvisible.wakeup(wakeUp); 166 | }; 167 | init = function() { 168 | var blur; 169 | if (initialized) { 170 | return true; 171 | } 172 | if (hidden === false) { 173 | blur = "blur"; 174 | if (ie < 9) { 175 | blur = "focusout"; 176 | } 177 | addEvent(window, blur, function() { 178 | return ifvisible.blur(); 179 | }); 180 | addEvent(window, "focus", function() { 181 | return ifvisible.focus(); 182 | }); 183 | } else { 184 | addEvent(doc, visibilityChange, function() { 185 | if (doc[hidden]) { 186 | return ifvisible.blur(); 187 | } else { 188 | return ifvisible.focus(); 189 | } 190 | }, false); 191 | } 192 | initialized = true; 193 | return trackIdleStatus(); 194 | }; 195 | ifvisible = { 196 | setIdleDuration: function(seconds) { 197 | return idleTime = seconds * 1000; 198 | }, 199 | getIdleDuration: function() { 200 | return idleTime; 201 | }, 202 | getIdleInfo: function() { 203 | var now, res; 204 | now = +(new Date()); 205 | res = {}; 206 | if (status === "idle") { 207 | res.isIdle = true; 208 | res.idleFor = now - idleStartedTime; 209 | res.timeLeft = 0; 210 | res.timeLeftPer = 100; 211 | } else { 212 | res.isIdle = false; 213 | res.idleFor = now - idleStartedTime; 214 | res.timeLeft = (idleStartedTime + idleTime) - now; 215 | res.timeLeftPer = (100 - (res.timeLeft * 100 / idleTime)).toFixed(2); 216 | } 217 | return res; 218 | }, 219 | focus: function(callback) { 220 | if (typeof callback === "function") { 221 | this.on("focus", callback); 222 | } else { 223 | status = "active"; 224 | customEvent.fire(this, "focus"); 225 | customEvent.fire(this, "wakeup"); 226 | customEvent.fire(this, "statusChanged", { 227 | status: status 228 | }); 229 | } 230 | return this; 231 | }, 232 | blur: function(callback) { 233 | if (typeof callback === "function") { 234 | this.on("blur", callback); 235 | } else { 236 | status = "hidden"; 237 | customEvent.fire(this, "blur"); 238 | customEvent.fire(this, "idle"); 239 | customEvent.fire(this, "statusChanged", { 240 | status: status 241 | }); 242 | } 243 | return this; 244 | }, 245 | idle: function(callback) { 246 | if (typeof callback === "function") { 247 | this.on("idle", callback); 248 | } else { 249 | status = "idle"; 250 | customEvent.fire(this, "idle"); 251 | customEvent.fire(this, "statusChanged", { 252 | status: status 253 | }); 254 | } 255 | return this; 256 | }, 257 | wakeup: function(callback) { 258 | if (typeof callback === "function") { 259 | this.on("wakeup", callback); 260 | } else { 261 | status = "active"; 262 | customEvent.fire(this, "wakeup"); 263 | customEvent.fire(this, "statusChanged", { 264 | status: status 265 | }); 266 | } 267 | return this; 268 | }, 269 | on: function(name, callback) { 270 | init(); 271 | customEvent.add(this, name, callback); 272 | return this; 273 | }, 274 | off: function(name, callback) { 275 | init(); 276 | customEvent.remove(this, name, callback); 277 | return this; 278 | }, 279 | onEvery: function(seconds, callback) { 280 | var paused, t; 281 | init(); 282 | paused = false; 283 | if (callback) { 284 | t = setInterval(function() { 285 | if (status === "active" && paused === false) { 286 | return callback(); 287 | } 288 | }, seconds * 1000); 289 | } 290 | return { 291 | stop: function() { 292 | return clearInterval(t); 293 | }, 294 | pause: function() { 295 | return paused = true; 296 | }, 297 | resume: function() { 298 | return paused = false; 299 | }, 300 | code: t, 301 | callback: callback 302 | }; 303 | }, 304 | now: function(check) { 305 | init(); 306 | return status === (check || "active"); 307 | } 308 | }; 309 | return ifvisible; 310 | }); 311 | 312 | }).call(this); 313 | 314 | //# sourceMappingURL=ifvisible.map 315 | -------------------------------------------------------------------------------- /perlin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Perlin Field 7 | 8 | 9 | 59 | 60 | 61 |
62 | Perlin Flow Field 63 |
64 |
65 | 1000 particles. Click to change the field. 66 |
67 |
68 |
69 | 70 | 71 | 72 | 192 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /perlin/perlin.js: -------------------------------------------------------------------------------- 1 | /* 2 | * A speed-improved perlin and simplex noise algorithms for 2D. 3 | * 4 | * Based on example code by Stefan Gustavson (stegu@itn.liu.se). 5 | * Optimisations by Peter Eastman (peastman@drizzle.stanford.edu). 6 | * Better rank ordering method by Stefan Gustavson in 2012. 7 | * Converted to Javascript by Joseph Gentle. 8 | * 9 | * Version 2012-03-09 10 | * 11 | * This code was placed in the public domain by its original author, 12 | * Stefan Gustavson. You may use it as you see fit, but 13 | * attribution is appreciated. 14 | * 15 | */ 16 | 17 | (function(global){ 18 | var module = global.noise = {}; 19 | 20 | function Grad(x, y, z) { 21 | this.x = x; this.y = y; this.z = z; 22 | } 23 | 24 | Grad.prototype.dot2 = function(x, y) { 25 | return this.x*x + this.y*y; 26 | }; 27 | 28 | Grad.prototype.dot3 = function(x, y, z) { 29 | return this.x*x + this.y*y + this.z*z; 30 | }; 31 | 32 | var grad3 = [new Grad(1,1,0),new Grad(-1,1,0),new Grad(1,-1,0),new Grad(-1,-1,0), 33 | new Grad(1,0,1),new Grad(-1,0,1),new Grad(1,0,-1),new Grad(-1,0,-1), 34 | new Grad(0,1,1),new Grad(0,-1,1),new Grad(0,1,-1),new Grad(0,-1,-1)]; 35 | 36 | var p = [151,160,137,91,90,15, 37 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 38 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 39 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 40 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 41 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 42 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 43 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 44 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 45 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 46 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 47 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 48 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180]; 49 | // To remove the need for index wrapping, double the permutation table length 50 | var perm = new Array(512); 51 | var gradP = new Array(512); 52 | 53 | // This isn't a very good seeding function, but it works ok. It supports 2^16 54 | // different seed values. Write something better if you need more seeds. 55 | module.seed = function(seed) { 56 | if(seed > 0 && seed < 1) { 57 | // Scale the seed out 58 | seed *= 65536; 59 | } 60 | 61 | seed = Math.floor(seed); 62 | if(seed < 256) { 63 | seed |= seed << 8; 64 | } 65 | 66 | for(var i = 0; i < 256; i++) { 67 | var v; 68 | if (i & 1) { 69 | v = p[i] ^ (seed & 255); 70 | } else { 71 | v = p[i] ^ ((seed>>8) & 255); 72 | } 73 | 74 | perm[i] = perm[i + 256] = v; 75 | gradP[i] = gradP[i + 256] = grad3[v % 12]; 76 | } 77 | }; 78 | 79 | module.seed(0); 80 | 81 | /* 82 | for(var i=0; i<256; i++) { 83 | perm[i] = perm[i + 256] = p[i]; 84 | gradP[i] = gradP[i + 256] = grad3[perm[i] % 12]; 85 | }*/ 86 | 87 | // Skewing and unskewing factors for 2, 3, and 4 dimensions 88 | var F2 = 0.5*(Math.sqrt(3)-1); 89 | var G2 = (3-Math.sqrt(3))/6; 90 | 91 | var F3 = 1/3; 92 | var G3 = 1/6; 93 | 94 | // 2D simplex noise 95 | module.simplex2 = function(xin, yin) { 96 | var n0, n1, n2; // Noise contributions from the three corners 97 | // Skew the input space to determine which simplex cell we're in 98 | var s = (xin+yin)*F2; // Hairy factor for 2D 99 | var i = Math.floor(xin+s); 100 | var j = Math.floor(yin+s); 101 | var t = (i+j)*G2; 102 | var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. 103 | var y0 = yin-j+t; 104 | // For the 2D case, the simplex shape is an equilateral triangle. 105 | // Determine which simplex we are in. 106 | var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords 107 | if(x0>y0) { // lower triangle, XY order: (0,0)->(1,0)->(1,1) 108 | i1=1; j1=0; 109 | } else { // upper triangle, YX order: (0,0)->(0,1)->(1,1) 110 | i1=0; j1=1; 111 | } 112 | // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and 113 | // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where 114 | // c = (3-sqrt(3))/6 115 | var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords 116 | var y1 = y0 - j1 + G2; 117 | var x2 = x0 - 1 + 2 * G2; // Offsets for last corner in (x,y) unskewed coords 118 | var y2 = y0 - 1 + 2 * G2; 119 | // Work out the hashed gradient indices of the three simplex corners 120 | i &= 255; 121 | j &= 255; 122 | var gi0 = gradP[i+perm[j]]; 123 | var gi1 = gradP[i+i1+perm[j+j1]]; 124 | var gi2 = gradP[i+1+perm[j+1]]; 125 | // Calculate the contribution from the three corners 126 | var t0 = 0.5 - x0*x0-y0*y0; 127 | if(t0<0) { 128 | n0 = 0; 129 | } else { 130 | t0 *= t0; 131 | n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient 132 | } 133 | var t1 = 0.5 - x1*x1-y1*y1; 134 | if(t1<0) { 135 | n1 = 0; 136 | } else { 137 | t1 *= t1; 138 | n1 = t1 * t1 * gi1.dot2(x1, y1); 139 | } 140 | var t2 = 0.5 - x2*x2-y2*y2; 141 | if(t2<0) { 142 | n2 = 0; 143 | } else { 144 | t2 *= t2; 145 | n2 = t2 * t2 * gi2.dot2(x2, y2); 146 | } 147 | // Add contributions from each corner to get the final noise value. 148 | // The result is scaled to return values in the interval [-1,1]. 149 | return 70 * (n0 + n1 + n2); 150 | }; 151 | 152 | // 3D simplex noise 153 | module.simplex3 = function(xin, yin, zin) { 154 | var n0, n1, n2, n3; // Noise contributions from the four corners 155 | 156 | // Skew the input space to determine which simplex cell we're in 157 | var s = (xin+yin+zin)*F3; // Hairy factor for 2D 158 | var i = Math.floor(xin+s); 159 | var j = Math.floor(yin+s); 160 | var k = Math.floor(zin+s); 161 | 162 | var t = (i+j+k)*G3; 163 | var x0 = xin-i+t; // The x,y distances from the cell origin, unskewed. 164 | var y0 = yin-j+t; 165 | var z0 = zin-k+t; 166 | 167 | // For the 3D case, the simplex shape is a slightly irregular tetrahedron. 168 | // Determine which simplex we are in. 169 | var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords 170 | var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords 171 | if(x0 >= y0) { 172 | if(y0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } 173 | else if(x0 >= z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } 174 | else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } 175 | } else { 176 | if(y0 < z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } 177 | else if(x0 < z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } 178 | else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } 179 | } 180 | // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), 181 | // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and 182 | // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where 183 | // c = 1/6. 184 | var x1 = x0 - i1 + G3; // Offsets for second corner 185 | var y1 = y0 - j1 + G3; 186 | var z1 = z0 - k1 + G3; 187 | 188 | var x2 = x0 - i2 + 2 * G3; // Offsets for third corner 189 | var y2 = y0 - j2 + 2 * G3; 190 | var z2 = z0 - k2 + 2 * G3; 191 | 192 | var x3 = x0 - 1 + 3 * G3; // Offsets for fourth corner 193 | var y3 = y0 - 1 + 3 * G3; 194 | var z3 = z0 - 1 + 3 * G3; 195 | 196 | // Work out the hashed gradient indices of the four simplex corners 197 | i &= 255; 198 | j &= 255; 199 | k &= 255; 200 | var gi0 = gradP[i+ perm[j+ perm[k ]]]; 201 | var gi1 = gradP[i+i1+perm[j+j1+perm[k+k1]]]; 202 | var gi2 = gradP[i+i2+perm[j+j2+perm[k+k2]]]; 203 | var gi3 = gradP[i+ 1+perm[j+ 1+perm[k+ 1]]]; 204 | 205 | // Calculate the contribution from the four corners 206 | var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; 207 | if(t0<0) { 208 | n0 = 0; 209 | } else { 210 | t0 *= t0; 211 | n0 = t0 * t0 * gi0.dot3(x0, y0, z0); // (x,y) of grad3 used for 2D gradient 212 | } 213 | var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; 214 | if(t1<0) { 215 | n1 = 0; 216 | } else { 217 | t1 *= t1; 218 | n1 = t1 * t1 * gi1.dot3(x1, y1, z1); 219 | } 220 | var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; 221 | if(t2<0) { 222 | n2 = 0; 223 | } else { 224 | t2 *= t2; 225 | n2 = t2 * t2 * gi2.dot3(x2, y2, z2); 226 | } 227 | var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; 228 | if(t3<0) { 229 | n3 = 0; 230 | } else { 231 | t3 *= t3; 232 | n3 = t3 * t3 * gi3.dot3(x3, y3, z3); 233 | } 234 | // Add contributions from each corner to get the final noise value. 235 | // The result is scaled to return values in the interval [-1,1]. 236 | return 32 * (n0 + n1 + n2 + n3); 237 | 238 | }; 239 | 240 | // ##### Perlin noise stuff 241 | 242 | function fade(t) { 243 | return t*t*t*(t*(t*6-15)+10); 244 | } 245 | 246 | function lerp(a, b, t) { 247 | return (1-t)*a + t*b; 248 | } 249 | 250 | // 2D Perlin Noise 251 | module.perlin2 = function(x, y) { 252 | // Find unit grid cell containing point 253 | var X = Math.floor(x), Y = Math.floor(y); 254 | // Get relative xy coordinates of point within that cell 255 | x = x - X; y = y - Y; 256 | // Wrap the integer cells at 255 (smaller integer period can be introduced here) 257 | X = X & 255; Y = Y & 255; 258 | 259 | // Calculate noise contributions from each of the four corners 260 | var n00 = gradP[X+perm[Y]].dot2(x, y); 261 | var n01 = gradP[X+perm[Y+1]].dot2(x, y-1); 262 | var n10 = gradP[X+1+perm[Y]].dot2(x-1, y); 263 | var n11 = gradP[X+1+perm[Y+1]].dot2(x-1, y-1); 264 | 265 | // Compute the fade curve value for x 266 | var u = fade(x); 267 | 268 | // Interpolate the four results 269 | return lerp( 270 | lerp(n00, n10, u), 271 | lerp(n01, n11, u), 272 | fade(y)); 273 | }; 274 | 275 | // 3D Perlin Noise 276 | module.perlin3 = function(x, y, z) { 277 | // Find unit grid cell containing point 278 | var X = Math.floor(x), Y = Math.floor(y), Z = Math.floor(z); 279 | // Get relative xyz coordinates of point within that cell 280 | x = x - X; y = y - Y; z = z - Z; 281 | // Wrap the integer cells at 255 (smaller integer period can be introduced here) 282 | X = X & 255; Y = Y & 255; Z = Z & 255; 283 | 284 | // Calculate noise contributions from each of the eight corners 285 | var n000 = gradP[X+ perm[Y+ perm[Z ]]].dot3(x, y, z); 286 | var n001 = gradP[X+ perm[Y+ perm[Z+1]]].dot3(x, y, z-1); 287 | var n010 = gradP[X+ perm[Y+1+perm[Z ]]].dot3(x, y-1, z); 288 | var n011 = gradP[X+ perm[Y+1+perm[Z+1]]].dot3(x, y-1, z-1); 289 | var n100 = gradP[X+1+perm[Y+ perm[Z ]]].dot3(x-1, y, z); 290 | var n101 = gradP[X+1+perm[Y+ perm[Z+1]]].dot3(x-1, y, z-1); 291 | var n110 = gradP[X+1+perm[Y+1+perm[Z ]]].dot3(x-1, y-1, z); 292 | var n111 = gradP[X+1+perm[Y+1+perm[Z+1]]].dot3(x-1, y-1, z-1); 293 | 294 | // Compute the fade curve value for x, y, z 295 | var u = fade(x); 296 | var v = fade(y); 297 | var w = fade(z); 298 | 299 | // Interpolate 300 | return lerp( 301 | lerp( 302 | lerp(n000, n100, u), 303 | lerp(n001, n101, u), w), 304 | lerp( 305 | lerp(n010, n110, u), 306 | lerp(n011, n111, u), w), 307 | v); 308 | }; 309 | 310 | })(this); 311 | -------------------------------------------------------------------------------- /radial/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/radial/favicon.ico -------------------------------------------------------------------------------- /radial/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Radial Wave Engine 5 | 6 | 7 | 8 | 9 | 59 | 60 | 61 |
62 |
63 |
Radial Wave Engine
64 |
65 | Built by Dennis Jin | View more eexperiments 66 |
67 | 70 |
71 | 72 | 73 | 74 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /radial/interpolate.js: -------------------------------------------------------------------------------- 1 | (function(root) { 2 | 'use strict'; 3 | 4 | /** 5 | * interpolateRGB 6 | * @desc Interpolate RGB colors. 7 | * @param {number[]} rgb1 - rgb array 8 | * @param {number[]} rgb2 - rgb array 9 | * @param {number} target - target value between units 0 - 1 10 | * @return interpolated rgb color array 11 | */ 12 | function interpolateRGB(rgb1, rgb2, t) { 13 | rgb1 = interpolateRGB._clipRGB(rgb1); 14 | rgb2 = interpolateRGB._clipRGB(rgb2); 15 | 16 | var r_1 = rgb1[0]; 17 | var g_1 = rgb1[1]; 18 | var b_1 = rgb1[2]; 19 | var a_1 = rgb1[3]; 20 | 21 | var r_2 = rgb2[0]; 22 | var g_2 = rgb2[1]; 23 | var b_2 = rgb2[2]; 24 | var a_2 = rgb2[3]; 25 | 26 | var interpolate = function(t) { 27 | t = interpolateRGB._clipT(t); 28 | 29 | var r_3 = r_1 + t * (r_2 - r_1); 30 | var g_3 = g_1 + t * (g_2 - g_1); 31 | var b_3 = b_1 + t * (b_2 - b_1); 32 | var result = [r_3, g_3, b_3]; 33 | 34 | if (rgb1.length === 4 && rgb2.length === 4) { 35 | var a_3 = a_1 + t * (a_2 - a_1); 36 | result.push(a_3); 37 | } 38 | 39 | return result; 40 | }; 41 | 42 | if (arguments.length === 2) { 43 | return interpolate; 44 | } else { 45 | return interpolate(t); 46 | } 47 | } 48 | 49 | /** 50 | * clipRGB 51 | * @desc Clips rgb values to stay within constraints 0-255 52 | * @param {number[]} rgb - rgb array 53 | * @return clipped values 54 | */ 55 | interpolateRGB._clipRGB = function(rgb) { 56 | if (!(Array.isArray(rgb) && rgb.length >= 3)) { 57 | rgb = [0,0,0]; 58 | } 59 | 60 | for (var i = 0; i < rgb.length; i++) { 61 | if (i < 3) { 62 | if (rgb[i] < 0) { 63 | rgb[i] = 0; 64 | } else if (rgb[i] > 255) { 65 | rgb[i] = 255; 66 | } 67 | } else if (i === 3) { 68 | if (rgb[i] < 0) { 69 | rgb[i] = 0; 70 | } else if (rgb[i] > 1) { 71 | rgb[i] = 1; 72 | } 73 | } 74 | } 75 | 76 | return rgb; 77 | }; 78 | 79 | /** 80 | * clipT 81 | * @desc Clips target value to stay within constraints 0-1 82 | * @param {number} target - target value 83 | * @return clipped value 84 | */ 85 | interpolateRGB._clipT = function(t) { 86 | if (typeof t !== 'number') { 87 | t = 0; 88 | } 89 | 90 | if (t > 1) { 91 | t = 1; 92 | } else if (t < 0) { 93 | t = 0; 94 | } 95 | 96 | return t; 97 | }; 98 | 99 | if (typeof exports !== 'undefined') { 100 | if (typeof module !== 'undefined' && module.exports) { 101 | exports = module.exports = interpolateRGB; 102 | } 103 | exports.interpolateRGB = interpolateRGB; 104 | } else if (typeof define === 'function' && define.amd) { 105 | define([], function() { 106 | return interpolateRGB; 107 | }); 108 | } else { 109 | root.interpolateRGB = interpolateRGB; 110 | } 111 | 112 | })(this); 113 | -------------------------------------------------------------------------------- /radial/re.js: -------------------------------------------------------------------------------- 1 | window.onload = () => { 2 | const interpolator = interpolateRGB([100, 100, 100], [255, 255, 255]); 3 | const space = new CanvasSpace('mount').setup({ 4 | bgcolor: '#111' 5 | }); 6 | const form = new Form(space); 7 | 8 | class Component { 9 | constructor(x, y) { 10 | this.x = x; 11 | this.y = y; 12 | } 13 | } 14 | 15 | class Crank extends Component { 16 | constructor(ops) { 17 | super(ops.x, ops.y); 18 | this.angle = 0; 19 | this.radius = ops.radius; 20 | this.speed = ops.speed; 21 | this.stagger = ops.stagger; 22 | this.p1 = { x: 0, y: 0 }; 23 | } 24 | stroke() { 25 | const angleX = Math.cos(this.angle); 26 | const angleY = -Math.sin(this.angle); 27 | this.p1 = { 28 | x: this.x + angleX * this.radius, 29 | y: this.y + angleY * this.radius 30 | }; 31 | return this.p1; 32 | } 33 | update(time) { 34 | this.angle = (this.speed * (time + this.stagger)) / 1000 % 1 * Math.PI * 2; 35 | this.stroke(); 36 | } 37 | render(form, time) { 38 | this.update(time); 39 | } 40 | } 41 | 42 | class ConnectingRod extends Component { 43 | constructor(ops) { 44 | super(0, 0); 45 | this.crank = ops.crank; 46 | this.angle = ops.angle; 47 | this.size = ops.size; 48 | this.p1 = { x: 0, y: 0 }; 49 | this.h = 0; 50 | this.hMin = Infinity; 51 | this.hMax = -Infinity; 52 | if (this.size < this.crank.radius) { 53 | throw new Error('Connecting rod needs to be equal or larger than crank radius'); 54 | } 55 | } 56 | littleEnd() { 57 | const rcos = this.crank.radius * Math.cos(this.angle - this.crank.angle); 58 | const l2 = Math.pow(this.size, 2); 59 | const r2 = Math.pow(this.crank.radius, 2); 60 | const sin2 = Math.pow(Math.sin(this.crank.angle), 2); 61 | const h = rcos + Math.sqrt(l2 - r2 * sin2); 62 | 63 | this.hMin = Math.min(h, this.hMin); 64 | this.hMax = Math.max(h, this.hMax); 65 | 66 | let nH = 0; 67 | if (this.hMin !== this.hMax) { 68 | nH = Util.mapToRange(this.h, this.hMin, this.hMax, 0, 1); 69 | } 70 | const dX = Math.cos(this.angle) * h + Math.sin(nH * Math.PI) * 20; 71 | const dY = -Math.sin(this.angle) * h + Math.sin(nH * Math.PI) * 60; 72 | this.h = h; 73 | this.p1 = { 74 | x: this.crank.x + dX, 75 | y: this.crank.y + dY 76 | }; 77 | return this.p1; 78 | } 79 | bigEnd() { 80 | this.x = this.crank.p1.x; 81 | this.y = this.crank.p1.y 82 | } 83 | update() { 84 | this.bigEnd(); 85 | this.littleEnd(); 86 | } 87 | render() { 88 | this.update(); 89 | form.line(new Line(this).to(this.p1)); 90 | } 91 | } 92 | 93 | class Piston extends ConnectingRod { 94 | constructor(ops) { 95 | super(ops); 96 | this.radius = ops.radius * Math.random(); 97 | } 98 | render(form, time) { 99 | this.update(); 100 | if (this.hMin !== this.hMax) { 101 | const nH = Util.mapToRange(this.h, this.hMin, this.hMax, 0, 1); 102 | const clr = `rgb(${interpolator(nH).map(c => Math.floor(c)).join(',')}`; 103 | form.stroke(clr, 1); 104 | form.stroke(false); 105 | form.fill(clr); 106 | form.circle(new Circle(this.p1).setRadius(Math.max(nH, 0.5) * this.radius)); 107 | } 108 | } 109 | } 110 | 111 | class CrankPin extends Crank { 112 | render(form, time) { 113 | this.update(time); 114 | form.stroke('#333', 3, 'round', 'round'); 115 | // form.line(new Line(this).to(this.p1)); 116 | form.stroke(false); 117 | form.fill('#fff'); 118 | form.circle(new Circle(this.p1).setRadius(1)); 119 | } 120 | } 121 | 122 | class MovingCrank extends Crank { 123 | constructor(ops) { 124 | super(ops); 125 | this.origX = ops.x; 126 | this.origY = ops.y; 127 | } 128 | update(time) { 129 | this.angle = (this.speed * (time + this.stagger)) / 1000 % 1 * Math.PI * 2; 130 | this.x = this.origX + Math.cos(time / 5000 % 1 * Math.PI * 2) * 100; 131 | this.y = this.origY + Math.sin(time / 5000 % 1 * Math.PI * 2) * 100; 132 | this.stroke(); 133 | } 134 | } 135 | 136 | const cranks = []; 137 | const rods = []; 138 | for (var i = 1; i <= 7; i++) { 139 | cranks.push( 140 | new Crank({ 141 | x: space.center.x, 142 | y: space.center.y, 143 | radius: i * 10, 144 | speed: 0.2, 145 | stagger: i * 100 146 | }) 147 | ); 148 | for (var j = 1; j <= (30 + i * 3); j++) { 149 | rods.push( 150 | new Piston({ 151 | size: Math.pow(i, 0.9) * 30, 152 | angle: j / (30 + i * 3) * Math.PI * 2, 153 | crank: cranks[i - 1], 154 | radius: 2.5 155 | }) 156 | ); 157 | } 158 | } 159 | 160 | // Quick run through the experiement and find min/max displacement 161 | let dummyTime = 0; 162 | while (dummyTime < 5000) { 163 | dummyTime++; 164 | cranks.forEach(c => c.update(dummyTime)); 165 | rods.forEach(r => r.update(dummyTime)); 166 | } 167 | 168 | space.add({ 169 | animate: (time, dt) => { 170 | cranks.forEach(c => c.update(time)); 171 | rods.forEach(r => r.render(form, time)); 172 | } 173 | }); 174 | space.play(); 175 | } 176 | -------------------------------------------------------------------------------- /radial/re.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | See Github repo for the unminified/untranspiled code! 3 | */ 4 | 5 | 'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i=n;n++){l.push(new f({x:b.center.x,y:b.center.y,radius:10*n,speed:0.2,stagger:100*n}));for(var o=1;o<=30+3*n;o++)m.push(new k({size:30*Math.pow(n,0.9),angle:2*(o/(30+3*n)*Math.PI),crank:l[n-1],radius:2.5}))}// Quick run through the experiement and find min/max displacement 6 | var _loop=function _loop(_p2){_p2++,l.forEach(function(q){return q.update(_p2)}),m.forEach(function(q){return q.update(_p2)}),_p=_p2};for(var _p=0;5e3>_p;)_loop(_p);b.add({animate:function animate(q){l.forEach(function(s){return s.update(q)}),m.forEach(function(s){return s.render(d,q)})}}),b.play()}; 7 | -------------------------------------------------------------------------------- /radial/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | -------------------------------------------------------------------------------- /satoshi/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/satoshi/favicon.ico -------------------------------------------------------------------------------- /satoshi/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | Satoshi Visualizer 11 | 12 | 13 | 14 | 198 | 199 | 200 |
201 | 205 | 206 | Gramatik - Satoshi Nakamoto (feat. Adrian Lau & ProbCause) 207 | 208 | 212 |
213 |
214 |
215 | Turn on volume. Press play. 216 |
217 |
218 | 219 |
220 | 221 | 222 | 409 | 418 | 419 | 420 | -------------------------------------------------------------------------------- /satoshi/play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /satoshi/rebound.js: -------------------------------------------------------------------------------- 1 | !function(){function a(a,b){var c=a.indexOf(b);-1!=c&&a.splice(c,1)}var b={},c=b.util={},d=Array.prototype.concat,e=Array.prototype.slice;c.bind=function(a,b){var c=e.call(arguments,2);return function(){a.apply(b,d.call(c,e.call(arguments)))}},c.extend=function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])};var f=b.SpringSystem=function(a){this._springRegistry={},this._activeSprings=[],this.listeners=[],this._idleSpringIndices=[],this.looper=a||new j,this.looper.springSystem=this};c.extend(f.prototype,{_springRegistry:null,_isIdle:!0,_lastTimeMillis:-1,_activeSprings:null,listeners:null,_idleSpringIndices:null,setLooper:function(a){this.looper=a,a.springSystem=this},createSpring:function(a,b){var c;return c=void 0===a||void 0===b?i.DEFAULT_ORIGAMI_SPRING_CONFIG:i.fromOrigamiTensionAndFriction(a,b),this.createSpringWithConfig(c)},createSpringWithBouncinessAndSpeed:function(a,b){var c;return c=void 0===a||void 0===b?i.DEFAULT_ORIGAMI_SPRING_CONFIG:i.fromBouncinessAndSpeed(a,b),this.createSpringWithConfig(c)},createSpringWithConfig:function(a){var b=new g(this);return this.registerSpring(b),b.setSpringConfig(a),b},getIsIdle:function(){return this._isIdle},getSpringById:function(a){return this._springRegistry[a]},getAllSprings:function(){var a=[];for(var b in this._springRegistry)this._springRegistry.hasOwnProperty(b)&&a.push(this._springRegistry[b]);return a},registerSpring:function(a){this._springRegistry[a.getId()]=a},deregisterSpring:function(b){a(this._activeSprings,b),delete this._springRegistry[b.getId()]},advance:function(a,b){for(;this._idleSpringIndices.length>0;)this._idleSpringIndices.pop();for(var c=0,d=this._activeSprings.length;d>c;c++){var e=this._activeSprings[c];e.systemShouldAdvance()?e.advance(a/1e3,b/1e3):this._idleSpringIndices.push(this._activeSprings.indexOf(e))}for(;this._idleSpringIndices.length>0;){var f=this._idleSpringIndices.pop();f>=0&&this._activeSprings.splice(f,1)}},loop:function(a){var b;-1===this._lastTimeMillis&&(this._lastTimeMillis=a-1);var c=a-this._lastTimeMillis;this._lastTimeMillis=a;var d=0,e=this.listeners.length;for(d=0;e>d;d++)b=this.listeners[d],b.onBeforeIntegrate&&b.onBeforeIntegrate(this);for(this.advance(a,c),0===this._activeSprings.length&&(this._isIdle=!0,this._lastTimeMillis=-1),d=0;e>d;d++)b=this.listeners[d],b.onAfterIntegrate&&b.onAfterIntegrate(this);this._isIdle||this.looper.run()},activateSpring:function(a){var b=this._springRegistry[a];-1==this._activeSprings.indexOf(b)&&this._activeSprings.push(b),this.getIsIdle()&&(this._isIdle=!1,this.looper.run())},addListener:function(a){this.listeners.push(a)},removeListener:function(b){a(this.listeners,b)},removeAllListeners:function(){this.listeners=[]}});var g=b.Spring=function p(a){this._id="s"+p._ID++,this._springSystem=a,this.listeners=[],this._currentState=new h,this._previousState=new h,this._tempState=new h};c.extend(g,{_ID:0,MAX_DELTA_TIME_SEC:.064,SOLVER_TIMESTEP_SEC:.001}),c.extend(g.prototype,{_id:0,_springConfig:null,_overshootClampingEnabled:!1,_currentState:null,_previousState:null,_tempState:null,_startValue:0,_endValue:0,_wasAtRest:!0,_restSpeedThreshold:.001,_displacementFromRestThreshold:.001,listeners:null,_timeAccumulator:0,_springSystem:null,destroy:function(){this.listeners=[],this.frames=[],this._springSystem.deregisterSpring(this)},getId:function(){return this._id},setSpringConfig:function(a){return this._springConfig=a,this},getSpringConfig:function(){return this._springConfig},setCurrentValue:function(a,b){return this._startValue=a,this._currentState.position=a,b||this.setAtRest(),this.notifyPositionUpdated(!1,!1),this},getStartValue:function(){return this._startValue},getCurrentValue:function(){return this._currentState.position},getCurrentDisplacementDistance:function(){return this.getDisplacementDistanceForState(this._currentState)},getDisplacementDistanceForState:function(a){return Math.abs(this._endValue-a.position)},setEndValue:function(a){if(this._endValue==a&&this.isAtRest())return this;this._startValue=this.getCurrentValue(),this._endValue=a,this._springSystem.activateSpring(this.getId());for(var b=0,c=this.listeners.length;c>b;b++){var d=this.listeners[b],e=d.onSpringEndStateChange;e&&e(this)}return this},getEndValue:function(){return this._endValue},setVelocity:function(a){return a===this._currentState.velocity?this:(this._currentState.velocity=a,this._springSystem.activateSpring(this.getId()),this)},getVelocity:function(){return this._currentState.velocity},setRestSpeedThreshold:function(a){return this._restSpeedThreshold=a,this},getRestSpeedThreshold:function(){return this._restSpeedThreshold},setRestDisplacementThreshold:function(a){this._displacementFromRestThreshold=a},getRestDisplacementThreshold:function(){return this._displacementFromRestThreshold},setOvershootClampingEnabled:function(a){return this._overshootClampingEnabled=a,this},isOvershootClampingEnabled:function(){return this._overshootClampingEnabled},isOvershooting:function(){var a=this._startValue,b=this._endValue;return this._springConfig.tension>0&&(b>a&&this.getCurrentValue()>b||a>b&&this.getCurrentValue()g.MAX_DELTA_TIME_SEC&&(d=g.MAX_DELTA_TIME_SEC),this._timeAccumulator+=d;for(var e,f,h,i,j,k,l,m,n,o,p=this._springConfig.tension,q=this._springConfig.friction,r=this._currentState.position,s=this._currentState.velocity,t=this._tempState.position,u=this._tempState.velocity;this._timeAccumulator>=g.SOLVER_TIMESTEP_SEC;)this._timeAccumulator-=g.SOLVER_TIMESTEP_SEC,this._timeAccumulator0&&this._interpolate(this._timeAccumulator/g.SOLVER_TIMESTEP_SEC),(this.isAtRest()||this._overshootClampingEnabled&&this.isOvershooting())&&(this._springConfig.tension>0?(this._startValue=this._endValue,this._currentState.position=this._endValue):(this._endValue=this._currentState.position,this._startValue=this._endValue),this.setVelocity(0),c=!0);var v=!1;this._wasAtRest&&(this._wasAtRest=!1,v=!0);var w=!1;c&&(this._wasAtRest=!0,w=!0),this.notifyPositionUpdated(v,w)}},notifyPositionUpdated:function(a,b){for(var c=0,d=this.listeners.length;d>c;c++){var e=this.listeners[c];a&&e.onSpringActivate&&e.onSpringActivate(this),e.onSpringUpdate&&e.onSpringUpdate(this),b&&e.onSpringAtRest&&e.onSpringAtRest(this)}},systemShouldAdvance:function(){return!this.isAtRest()||!this.wasAtRest()},wasAtRest:function(){return this._wasAtRest},isAtRest:function(){return Math.abs(this._currentState.velocity)=a?this.b3Friction1(a):a>18&&44>=a?this.b3Friction2(a):this.b3Friction3(a)}}),c.extend(i,{fromOrigamiTensionAndFriction:function(a,b){return new i(k.tensionFromOrigamiValue(a),k.frictionFromOrigamiValue(b))},fromBouncinessAndSpeed:function(a,c){var d=new b.BouncyConversion(a,c);return this.fromOrigamiTensionAndFriction(d.bouncyTension,d.bouncyFriction)},coastingConfigWithOrigamiFriction:function(a){return new i(0,k.frictionFromOrigamiValue(a))}}),i.DEFAULT_ORIGAMI_SPRING_CONFIG=i.fromOrigamiTensionAndFriction(40,7),c.extend(i.prototype,{friction:0,tension:0});var m={};c.hexToRGB=function(a){if(m[a])return m[a];a=a.replace("#",""),3===a.length&&(a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]);var b=a.match(/.{2}/g),c={r:parseInt(b[0],16),g:parseInt(b[1],16),b:parseInt(b[2],16)};return m[a]=c,c},c.rgbToHex=function(a,b,c){return a=a.toString(16),b=b.toString(16),c=c.toString(16),a=a.length<2?"0"+a:a,b=b.length<2?"0"+b:b,c=c.length<2?"0"+c:c,"#"+a+b+c};var n=b.MathUtil={mapValueInRange:function(a,b,c,d,e){var f=c-b,g=e-d,h=(a-b)/f;return d+h*g},interpolateColor:function(a,b,d,e,f,g){e=void 0===e?0:e,f=void 0===f?1:f,b=c.hexToRGB(b),d=c.hexToRGB(d);var h=Math.floor(c.mapValueInRange(a,e,f,b.r,d.r)),i=Math.floor(c.mapValueInRange(a,e,f,b.g,d.g)),j=Math.floor(c.mapValueInRange(a,e,f,b.b,d.b));return g?"rgb("+h+","+i+","+j+")":c.rgbToHex(h,i,j)},degreesToRadians:function(a){return a*Math.PI/180},radiansToDegrees:function(a){return 180*a/Math.PI}};c.extend(c,n);var o;"undefined"!=typeof window&&(o=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}),o||"undefined"==typeof process||"node"!==process.title||(o=setImmediate),c.onFrame=function(a){return o(a)},"undefined"!=typeof exports?c.extend(exports,b):"undefined"!=typeof window&&(window.rebound=b)}(); 2 | -------------------------------------------------------------------------------- /satoshi/satoshi.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/satoshi/satoshi.mp3 -------------------------------------------------------------------------------- /satoshi/satoshi.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/satoshi/satoshi.ogg -------------------------------------------------------------------------------- /sine/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/sine/favicon.ico -------------------------------------------------------------------------------- /sine/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | eex - Sine Wave and Circles 5 | 6 | 7 | 8 | 39 | 40 | 41 |
42 |
43 |
44 | Mouse over to interact
45 | Built by Dennis Jin / dennisjin.com / Open-sourced on Github / View more eexperiments 46 |
47 | 48 | 49 | 117 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /springy/bliss.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2015 Lea Verou 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | !function(){"use strict";function t(e,r,i){return r=void 0===r?1:r,i=i||r+1,1>=i-r?function(){if("string"===n.type(arguments[r]))return e.apply(this,arguments);var t,i=arguments[r];for(var s in i){var o=Array.from(arguments);o.splice(r,1,s,i[s]),t=e.apply(this,o)}return t}:t(t(e,r+1,i),r,i-1)}function e(t,e,r){for(var i in e){if(r){var s=n.type(r);if("own"===r&&!e.hasOwnProperty(i)||"array"===s&&-1===r.indexOf(i)||"regexp"===s&&!r.test(i)||"function"===s&&!r.call(e,i))continue}var o=Object.getOwnPropertyDescriptor(e,i);!o||o.writable&&o.configurable&&o.enumerable&&!o.get&&!o.set?t[i]=e[i]:(delete t[i],Object.defineProperty(t,i,o))}return t}var n=self.Bliss=e(function(t,e){return"string"===n.type(t)?(e||document).querySelector(t):t||null},self.Bliss);e(n,{extend:e,overload:t,property:n.property||"_",sources:{},noop:function(){},$:function(t,e){return t instanceof Node||t instanceof Window?[t]:Array.from("string"==typeof t?(e||document).querySelectorAll(t):t||[])},type:function(t){if(null===t)return"null";if(void 0===t)return"undefined";var e=(Object.prototype.toString.call(t).match(/^\[object\s+(.*?)\]$/)[1]||"").toLowerCase();return"number"==e&&isNaN(t)?"nan":e},defined:function(){for(var t=0;t=200&&i.xhr.status<300||304===i.xhr.status?t(i.xhr):e(Error(i.xhr.statusText))},i.xhr.onerror=function(){document.body.removeAttribute("data-loading"),e(Error("Network Error"))},i.xhr.send("GET"===i.method?null:i.data)})},value:function(t){var e="string"!==n.type(t);return $$(arguments).slice(+e).reduce(function(t,e){return t&&t[e]},e?t:self)}}),n.Hooks=new n.Class({add:function(t,e){this[t]=this[t]||[],this[t].push(e)},run:function(t,e){(this[t]||[]).forEach(function(t){t(e)})}}),n.hooks=new n.Hooks;var r=n.property;n.Element=function(t){this.subject=t,this.data={},this.bliss={}},n.Element.prototype={set:t(function(t,e){t in n.setProps?n.setProps[t].call(this,e):t in this?this[t]=e:this.setAttribute(t,e)},0),transition:function(t,e){return e=+e||400,new Promise(function(r,i){if("transition"in this.style){var s=n.extend({},this.style,/^transition(Duration|Property)$/);n.style(this,{transitionDuration:(e||400)+"ms",transitionProperty:Object.keys(t).join(", ")}),n.once(this,"transitionend",function(){clearTimeout(o),n.style(this,s),r(this)});var o=setTimeout(r,e+50,this);n.style(this,t)}else n.style(this,t),r(this)}.bind(this))},fire:function(t,e){var r=document.createEvent("HTMLEvents");r.initEvent(t,!0,!0),this.dispatchEvent(n.extend(r,e))}},n.setProps={style:function(t){n.extend(this.style,t)},attributes:function(t){for(var e in t)this.setAttribute(e,t[e])},properties:function(t){n.extend(this,t)},events:function(t){if(t&&t.addEventListener){var e=this;if(t[r]&&t[r].bliss){var n=t[r].bliss.listeners;for(var i in n)n[i].forEach(function(t){e.addEventListener(i,t.callback,t.capture)})}for(var s in t)0===s.indexOf("on")&&(this[s]=t[s])}else for(var o in t)o.split(/\s+/).forEach(function(e){this.addEventListener(e,t[o])},this)},once:t(function(t,e){t=t.split(/\s+/);var n=this,r=function(){return t.forEach(function(t){n.removeEventListener(t,r)}),e.apply(n,arguments)};t.forEach(function(t){n.addEventListener(t,r)})},0),delegate:t(function(t,e,n){this.addEventListener(t,function(t){t.target.closest(e)&&n.call(this,t)})},0,2),contents:function(t){(t||0===t)&&(Array.isArray(t)?t:[t]).forEach(function(t){var e=n.type(t);/^(string|number)$/.test(e)?t=document.createTextNode(t+""):"object"===e&&(t=n.create(t)),t instanceof Node&&this.appendChild(t)},this)},inside:function(t){t.appendChild(this)},before:function(t){t.parentNode.insertBefore(this,t)},after:function(t){t.parentNode.insertBefore(this,t.nextSibling)},start:function(t){t.insertBefore(this,t.firstChild)},around:function(t){t.parentNode&&n.before(this,t),(/^template$/i.test(this.nodeName)?this.content||this:this).appendChild(t)}},n.Array=function(t){this.subject=t},n.Array.prototype={all:function(t){var e=$$(arguments).slice(1);return this[t].apply(this,e)}},n.add=t(function(t,e,r,i){r=n.extend({$:!0,element:!0,array:!0},r),"function"==n.type(e)&&(!r.element||t in n.Element.prototype&&i||(n.Element.prototype[t]=function(){return this.subject&&n.defined(e.apply(this.subject,arguments),this.subject)}),!r.array||t in n.Array.prototype&&i||(n.Array.prototype[t]=function(){var t=arguments;return this.subject.map(function(r){return r&&n.defined(e.apply(r,t),r)})}),r.$&&(n.sources[t]=n[t]=e,(r.array||r.element)&&(n[t]=function(){var e=[].slice.apply(arguments),i=e.shift(),s=r.array&&Array.isArray(i)?"Array":"Element";return n[s].prototype[t].apply({subject:i},e)})))},0),n.add(n.Array.prototype,{element:!1}),n.add(n.Element.prototype),n.add(n.setProps),n.add(n.classProps,{element:!1,array:!1});var i=document.createElement("_");n.add(n.extend({},HTMLElement.prototype,function(t){return"function"===n.type(i[t])}),null,!0)}(),function(t){"use strict";if(Bliss&&!Bliss.shy){var e=Bliss.property;if(t.add({clone:function(){var e=this.cloneNode(!0),n=t.$("*",e).concat(e);return t.$("*",this).concat(this).forEach(function(e,r,i){t.events(n[r],e)}),e}},{array:!1}),Object.defineProperty(Node.prototype,e,{get:function o(){return Object.defineProperty(Node.prototype,e,{get:void 0}),Object.defineProperty(this,e,{value:new t.Element(this)}),Object.defineProperty(Node.prototype,e,{get:o}),this[e]},configurable:!0}),Object.defineProperty(Array.prototype,e,{get:function(){return Object.defineProperty(this,e,{value:new t.Array(this)}),this[e]},configurable:!0}),self.EventTarget&&"addEventListener"in EventTarget.prototype){var n=EventTarget.prototype.addEventListener,r=EventTarget.prototype.removeEventListener,i=function(t,e,n){return n.callback===t&&n.capture==e},s=function(){return!i.apply(this,arguments)};EventTarget.prototype.addEventListener=function(t,r,s){if(this&&this[e]&&r){var o=this[e].bliss.listeners=this[e].bliss.listeners||{};o[t]=o[t]||[],0===o[t].filter(i.bind(null,r,s)).length&&o[t].push({callback:r,capture:s})}return n.call(this,t,r,s)},EventTarget.prototype.removeEventListener=function(t,n,i){if(this&&this[e]&&n){var o=this[e].bliss.listeners=this[e].bliss.listeners||{};o[t]&&(o[t]=o[t].filter(s.bind(null,n,i)))}return r.call(this,t,n,i)}}self.$=self.$||t,self.$$=self.$$||t.$}}(Bliss); 25 | -------------------------------------------------------------------------------- /springy/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/springy/favicon.ico -------------------------------------------------------------------------------- /springy/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Springy 7 | 8 | 9 | 10 | 11 | 147 | 148 | 149 | 345 | 346 | 347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 | letters · to reveal 356 |

357 | built by Dennis Jin · dennisjin.com
358 | source code on Github · view more eexperiments 359 |

360 | based on a video by Eric Hu 361 |
362 |
363 | 372 | 373 | 374 | -------------------------------------------------------------------------------- /springy/rebound.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | BSD License 3 | 4 | For the rebound-js software 5 | 6 | Copyright (c) 2014, Facebook, Inc. All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, 9 | are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, this 12 | list of conditions and the following disclaimer. 13 | 14 | * Redistributions in binary form must reproduce the above copyright notice, 15 | this list of conditions and the following disclaimer in the documentation 16 | and/or other materials provided with the distribution. 17 | 18 | * Neither the name Facebook nor the names of its contributors may be used to 19 | endorse or promote products derived from this software without specific 20 | prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 26 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 29 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | !function(){function a(a,b){var c=a.indexOf(b);-1!=c&&a.splice(c,1)}var b={},c=b.util={},d=Array.prototype.concat,e=Array.prototype.slice;c.bind=function(a,b){var c=e.call(arguments,2);return function(){a.apply(b,d.call(c,e.call(arguments)))}},c.extend=function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])};var f=b.SpringSystem=function(a){this._springRegistry={},this._activeSprings=[],this.listeners=[],this._idleSpringIndices=[],this.looper=a||new j,this.looper.springSystem=this};c.extend(f.prototype,{_springRegistry:null,_isIdle:!0,_lastTimeMillis:-1,_activeSprings:null,listeners:null,_idleSpringIndices:null,setLooper:function(a){this.looper=a,a.springSystem=this},createSpring:function(a,b){var c;return c=void 0===a||void 0===b?i.DEFAULT_ORIGAMI_SPRING_CONFIG:i.fromOrigamiTensionAndFriction(a,b),this.createSpringWithConfig(c)},createSpringWithBouncinessAndSpeed:function(a,b){var c;return c=void 0===a||void 0===b?i.DEFAULT_ORIGAMI_SPRING_CONFIG:i.fromBouncinessAndSpeed(a,b),this.createSpringWithConfig(c)},createSpringWithConfig:function(a){var b=new g(this);return this.registerSpring(b),b.setSpringConfig(a),b},getIsIdle:function(){return this._isIdle},getSpringById:function(a){return this._springRegistry[a]},getAllSprings:function(){var a=[];for(var b in this._springRegistry)this._springRegistry.hasOwnProperty(b)&&a.push(this._springRegistry[b]);return a},registerSpring:function(a){this._springRegistry[a.getId()]=a},deregisterSpring:function(b){a(this._activeSprings,b),delete this._springRegistry[b.getId()]},advance:function(a,b){for(;this._idleSpringIndices.length>0;)this._idleSpringIndices.pop();for(var c=0,d=this._activeSprings.length;d>c;c++){var e=this._activeSprings[c];e.systemShouldAdvance()?e.advance(a/1e3,b/1e3):this._idleSpringIndices.push(this._activeSprings.indexOf(e))}for(;this._idleSpringIndices.length>0;){var f=this._idleSpringIndices.pop();f>=0&&this._activeSprings.splice(f,1)}},loop:function(a){var b;-1===this._lastTimeMillis&&(this._lastTimeMillis=a-1);var c=a-this._lastTimeMillis;this._lastTimeMillis=a;var d=0,e=this.listeners.length;for(d=0;e>d;d++)b=this.listeners[d],b.onBeforeIntegrate&&b.onBeforeIntegrate(this);for(this.advance(a,c),0===this._activeSprings.length&&(this._isIdle=!0,this._lastTimeMillis=-1),d=0;e>d;d++)b=this.listeners[d],b.onAfterIntegrate&&b.onAfterIntegrate(this);this._isIdle||this.looper.run()},activateSpring:function(a){var b=this._springRegistry[a];-1==this._activeSprings.indexOf(b)&&this._activeSprings.push(b),this.getIsIdle()&&(this._isIdle=!1,this.looper.run())},addListener:function(a){this.listeners.push(a)},removeListener:function(b){a(this.listeners,b)},removeAllListeners:function(){this.listeners=[]}});var g=b.Spring=function p(a){this._id="s"+p._ID++,this._springSystem=a,this.listeners=[],this._currentState=new h,this._previousState=new h,this._tempState=new h};c.extend(g,{_ID:0,MAX_DELTA_TIME_SEC:.064,SOLVER_TIMESTEP_SEC:.001}),c.extend(g.prototype,{_id:0,_springConfig:null,_overshootClampingEnabled:!1,_currentState:null,_previousState:null,_tempState:null,_startValue:0,_endValue:0,_wasAtRest:!0,_restSpeedThreshold:.001,_displacementFromRestThreshold:.001,listeners:null,_timeAccumulator:0,_springSystem:null,destroy:function(){this.listeners=[],this.frames=[],this._springSystem.deregisterSpring(this)},getId:function(){return this._id},setSpringConfig:function(a){return this._springConfig=a,this},getSpringConfig:function(){return this._springConfig},setCurrentValue:function(a,b){return this._startValue=a,this._currentState.position=a,b||this.setAtRest(),this.notifyPositionUpdated(!1,!1),this},getStartValue:function(){return this._startValue},getCurrentValue:function(){return this._currentState.position},getCurrentDisplacementDistance:function(){return this.getDisplacementDistanceForState(this._currentState)},getDisplacementDistanceForState:function(a){return Math.abs(this._endValue-a.position)},setEndValue:function(a){if(this._endValue==a&&this.isAtRest())return this;this._startValue=this.getCurrentValue(),this._endValue=a,this._springSystem.activateSpring(this.getId());for(var b=0,c=this.listeners.length;c>b;b++){var d=this.listeners[b],e=d.onSpringEndStateChange;e&&e(this)}return this},getEndValue:function(){return this._endValue},setVelocity:function(a){return a===this._currentState.velocity?this:(this._currentState.velocity=a,this._springSystem.activateSpring(this.getId()),this)},getVelocity:function(){return this._currentState.velocity},setRestSpeedThreshold:function(a){return this._restSpeedThreshold=a,this},getRestSpeedThreshold:function(){return this._restSpeedThreshold},setRestDisplacementThreshold:function(a){this._displacementFromRestThreshold=a},getRestDisplacementThreshold:function(){return this._displacementFromRestThreshold},setOvershootClampingEnabled:function(a){return this._overshootClampingEnabled=a,this},isOvershootClampingEnabled:function(){return this._overshootClampingEnabled},isOvershooting:function(){var a=this._startValue,b=this._endValue;return this._springConfig.tension>0&&(b>a&&this.getCurrentValue()>b||a>b&&this.getCurrentValue()g.MAX_DELTA_TIME_SEC&&(d=g.MAX_DELTA_TIME_SEC),this._timeAccumulator+=d;for(var e,f,h,i,j,k,l,m,n,o,p=this._springConfig.tension,q=this._springConfig.friction,r=this._currentState.position,s=this._currentState.velocity,t=this._tempState.position,u=this._tempState.velocity;this._timeAccumulator>=g.SOLVER_TIMESTEP_SEC;)this._timeAccumulator-=g.SOLVER_TIMESTEP_SEC,this._timeAccumulator0&&this._interpolate(this._timeAccumulator/g.SOLVER_TIMESTEP_SEC),(this.isAtRest()||this._overshootClampingEnabled&&this.isOvershooting())&&(this._springConfig.tension>0?(this._startValue=this._endValue,this._currentState.position=this._endValue):(this._endValue=this._currentState.position,this._startValue=this._endValue),this.setVelocity(0),c=!0);var v=!1;this._wasAtRest&&(this._wasAtRest=!1,v=!0);var w=!1;c&&(this._wasAtRest=!0,w=!0),this.notifyPositionUpdated(v,w)}},notifyPositionUpdated:function(a,b){for(var c=0,d=this.listeners.length;d>c;c++){var e=this.listeners[c];a&&e.onSpringActivate&&e.onSpringActivate(this),e.onSpringUpdate&&e.onSpringUpdate(this),b&&e.onSpringAtRest&&e.onSpringAtRest(this)}},systemShouldAdvance:function(){return!this.isAtRest()||!this.wasAtRest()},wasAtRest:function(){return this._wasAtRest},isAtRest:function(){return Math.abs(this._currentState.velocity)=a?this.b3Friction1(a):a>18&&44>=a?this.b3Friction2(a):this.b3Friction3(a)}}),c.extend(i,{fromOrigamiTensionAndFriction:function(a,b){return new i(k.tensionFromOrigamiValue(a),k.frictionFromOrigamiValue(b))},fromBouncinessAndSpeed:function(a,c){var d=new b.BouncyConversion(a,c);return this.fromOrigamiTensionAndFriction(d.bouncyTension,d.bouncyFriction)},coastingConfigWithOrigamiFriction:function(a){return new i(0,k.frictionFromOrigamiValue(a))}}),i.DEFAULT_ORIGAMI_SPRING_CONFIG=i.fromOrigamiTensionAndFriction(40,7),c.extend(i.prototype,{friction:0,tension:0});var m={};c.hexToRGB=function(a){if(m[a])return m[a];a=a.replace("#",""),3===a.length&&(a=a[0]+a[0]+a[1]+a[1]+a[2]+a[2]);var b=a.match(/.{2}/g),c={r:parseInt(b[0],16),g:parseInt(b[1],16),b:parseInt(b[2],16)};return m[a]=c,c},c.rgbToHex=function(a,b,c){return a=a.toString(16),b=b.toString(16),c=c.toString(16),a=a.length<2?"0"+a:a,b=b.length<2?"0"+b:b,c=c.length<2?"0"+c:c,"#"+a+b+c};var n=b.MathUtil={mapValueInRange:function(a,b,c,d,e){var f=c-b,g=e-d,h=(a-b)/f;return d+h*g},interpolateColor:function(a,b,d,e,f,g){e=void 0===e?0:e,f=void 0===f?1:f,b=c.hexToRGB(b),d=c.hexToRGB(d);var h=Math.floor(c.mapValueInRange(a,e,f,b.r,d.r)),i=Math.floor(c.mapValueInRange(a,e,f,b.g,d.g)),j=Math.floor(c.mapValueInRange(a,e,f,b.b,d.b));return g?"rgb("+h+","+i+","+j+")":c.rgbToHex(h,i,j)},degreesToRadians:function(a){return a*Math.PI/180},radiansToDegrees:function(a){return 180*a/Math.PI}};c.extend(c,n);var o;"undefined"!=typeof window&&(o=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}),o||"undefined"==typeof process||"node"!==process.title||(o=setImmediate),c.onFrame=function(a){return o(a)},"undefined"!=typeof exports?c.extend(exports,b):"undefined"!=typeof window&&(window.rebound=b)}(); 34 | -------------------------------------------------------------------------------- /template.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/template.ico -------------------------------------------------------------------------------- /vectorfield/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/vectorfield/favicon.ico -------------------------------------------------------------------------------- /vectorfield/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vector Field 5 | 6 | 7 | 8 | 9 | 10 | 54 | 55 | 56 |
57 |
58 |
59 | vector field
60 | built by Dennis Jin · dennisjin.com
open-sourced on Github · view more eexperiments 61 |
62 | 63 | 113 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /vortex/LBM.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tofuness/eex/863efb2eed9a4db5b2e56b9d8c3743607ae07b90/vortex/LBM.js -------------------------------------------------------------------------------- /vortex/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Vortex 5 | 63 | 64 | 65 |
66 |
67 | 68 | 174 | 175 | 176 | --------------------------------------------------------------------------------