Direct Link
Source code
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> |
| <html> |
| <head> |
| <title>unchained - interactive DHTML</title> |
| <meta name="Author" content="Gerard Ferrandez at http://www.dhteumeuleu.com"> |
| <meta http-equiv="imagetoolbar" content="no"> |
| <style type="text/css"> |
| html { |
| overflow: hidden; |
| } |
| body { |
| position: absolute; |
| margin: 0px; |
| padding: 0px; |
| background: #111; |
| width: 100%; |
| height: 100%; |
| } |
| #screen { |
| position: absolute; |
| left: 0%; |
| top: 0%; |
| width: 100%; |
| height: 100%; |
| background: #000; |
| } |
| #screen img { |
| position: absolute; |
| } |
| #ground { |
| position: absolute; |
| left: 0%; |
| top: 80%; |
| width: 100%; |
| height: 20%; |
| background: #111; |
| } |
| #bankImages { |
| visibility: hidden; |
| } |
| </style> |
| <script type="text/javascript"> |
| // ============================================================= |
| // ===== chains ===== |
| // script written by Gerard Ferrandez - January 2008 |
| // http://www.dhteumeuleu.com |
| // -------------------------- |
| // music by Poul Lindegaard at www.lindegaard.nakskovnet.dk |
| // ============================================================= |
| /* ==== chain constructor ==== */ |
| var chain = []; |
| function Chain(N, img, r, app, ox, oy) |
| { |
| this.N = N; |
| this.img = img; |
| this.r = r; |
| this.app = app; |
| this.ox = ox; |
| this.oy = oy; |
| /* ==== create points ==== */ |
| this.create(); |
| } |
| /* ==== chain functions ==== */ |
| Chain.prototype = { |
| /* ==== create points ==== */ |
| create : function () { |
| this.points = []; |
| for ( var i = 0; i < this.N; i++) { |
| this.points[i] = new Point(this); |
| if (i > 0) { |
| this.points[i - 1].links.push(this.points[i]); |
| this.points[i - 1].next = this.points[i]; |
| } |
| } |
| this.first = this.points[0]; |
| this.last = this.points[this.N - 1]; |
| }, |
| /* ============ additional procedures for this script ========== */ |
| modPoint : function (N, r, img) { |
| var p = this.points[N]; |
| p.r = r; |
| p.img.src = img.src; |
| p.w = img.width * .5; |
| p.h = img.height * .5; |
| p.img.style.width = img.width + 'px'; |
| p.img.style.height = img.height + 'px'; |
| }, |
| anim : function () { |
| /* ==== mouse collision ==== */ |
| var p = this.last; |
| var dx = mouse.x - p.x; |
| var dy = mouse.y - p.y; |
| var d = Math.sqrt((dx * dx) + (dy * dy)); |
| if (d < p.w) { |
| var a = Math.atan2(dy, dx); |
| p.x -= Math.cos(a) * (p.w - d); |
| p.y -= Math.sin(a) * (p.h - d); |
| } |
| /* ==== head weight ==== */ |
| p.y += (scr.h - p.y) / 400; |
| /* ==== force socle position ==== */ |
| this.first.x = scr.w * this.ox; |
| this.first.y = scr.h * this.oy; |
| /* ==== start chain ==== */ |
| this.first.anim(); |
| }, |
| /* ==== collisions ==== */ |
| collide : function (c1) { |
| var n0 = this.last; |
| var n1 = c1.last; |
| var dx = n0.x - n1.x; |
| var dy = n0.y - n1.y; |
| var d = Math.sqrt((dx * dx) + (dy * dy)); |
| if (d < (n0.w + n1.w) * .8) { |
| n0.x -= 1 / Math.max(1, dx); |
| n1.x += 1 / Math.max(1, dx); |
| n0.y -= 1 / Math.max(1, dy); |
| n1.y += 1 / Math.max(1, dy); |
| } |
| } |
| } |
| /* ==== Point Constructor ==== */ |
| function Point(chain) { |
| this.r = chain.r; |
| this.app = chain.app; |
| this.x = scr.w * .5; |
| this.y = scr.h * .5; |
| this.xb = scr.w * .5; |
| this.yb = scr.h * .5; |
| this.w = chain.img.width * .5; |
| this.h = chain.img.height * .5; |
| this.links = []; |
| /* ==== insert HTML image ==== */ |
| this.img = document.createElement('img'); |
| this.img.src = chain.img.src; |
| scr.o.appendChild(this.img); |
| } |
| /* ==== Point functions ==== */ |
| Point.prototype = { |
| /* ==== main verlet animation ==== */ |
| anim : function() { |
| /* ==== html refresh ==== */ |
| this.img.style.left = Math.round(this.x - this.w) + 'px'; |
| this.img.style.top = Math.round(this.y - this.h) + 'px'; |
| /* ==== inertia ==== */ |
| var x = this.x; |
| var y = this.y; |
| this.x += (this.x - this.xb); |
| this.y += (this.y - this.yb); |
| this.xb = x; |
| this.yb = y; |
| /* ==== constraints linkage ==== */ |
| var i = this.links.length; |
| while (i--) { |
| var link = this.links[i]; |
| var dx = this.x - link.x; |
| var dy = this.y - link.y; |
| var d = Math.sqrt(dx * dx + dy * dy) + .001; |
| d = .5 * (d - (this.w + link.w) * this.r) / d; |
| dx *= d; |
| dy *= d; |
| this.x -= dx; |
| this.y -= dy + this.app; |
| link.x += dx; |
| link.y += dy; |
| } |
| /* ==== loop to the next point ==== */ |
| if (this.next) this.next.anim(); |
| } |
| } |
| /* ============ initialize script ========== */ |
| function init() { |
| var img = document.getElementById('bankImages').getElementsByTagName('img'); |
| scr.resize(); |
| var N = 50; |
| /* ==== create chains ==== */ |
| for (var i = 0; i < 3; i++) { |
| chain.push( |
| new Chain( |
| N, // number of links |
| img[[0,1,0][i]], // images |
| .6, // links distance |
| .1, // links weight |
| ((i + 1) * .166) + .166, // x-origin |
| .9 // y-origin |
| ) |
| ); |
| /* ==== head ==== */ |
| chain[i].modPoint( |
| N - 1, // last link |
| .95, // radius |
| img[[2,3,2][i]] // images |
| ); |
| /* ==== socle ==== */ |
| chain[i].modPoint( |
| 0, // first link |
| .5, // radius |
| img[[4,5,4][i]] // images |
| ); |
| } |
| /* ==== let's go ==== */ |
| run(); |
| } |
| /* ============ main loop ========== */ |
| function run() { |
| chain[0].anim(); |
| chain[1].anim(); |
| chain[2].anim(); |
| chain[0].collide(chain[1]); |
| chain[0].collide(chain[2]); |
| chain[1].collide(chain[2]); |
| setTimeout(run, 16); |
| } |
| /* ==== global mouse position ==== */ |
| var mouse = { |
| x : 0, |
| y : 0 |
| } |
| document.onmousemove = function(e) |
| { |
| if (window.event) e = window.event; |
| mouse.x = e.clientX; |
| mouse.y = e.clientY; |
| return false; |
| } |
| /* ==== global resize ==== */ |
| var scr = { |
| w : 0, |
| h : 0, |
| resize : function () { |
| scr.o = document.getElementById('screen'); |
| scr.w = scr.o.offsetWidth; |
| scr.h = scr.o.offsetHeight; |
| } |
| } |
| /* ==== page loaded ==== */ |
| onload = function () { |
| onresize = scr.resize; |
| init(); |
| } |
| </script> |
| </head> |
| <body> |
| <div id="screen"> |
| <div id="ground"></div> |
| </div> |
| <div id="bankImages"> |
| <!-- links --> |
| <img alt="" src="../images/sp01.gif"> |
| <img alt="" src="../images/sp2r0.gif"> |
| <!-- head --> |
| <img alt="" src="../images/sp2w.gif"> |
| <img alt="" src="../images/sp2r.gif"> |
| <!-- socle --> |
| <img alt="" src="../images/sp2ws.gif"> |
| <img alt="" src="../images/sp2rs.gif"> |
| </div> |
| </body> |
| </html> |

