gibney.org : Other : related.js_2


just a logo :)

search:


See as: raw | code

terms of service | imprint

gibney.org
is powered by m1d1





related.js_2
(Entry Nr. 494, by user 39 | edit)
/****************************************************************************** * animated item relationship distance map * * Part of Gnod, the Global Network of Dreams. (c) Marek Gibney * * Animates html elements with id's "s0", "s1",... * * Tries to keep the distances between them as given by an array gnodMap.aid[][], * where aid[4][7] is the proposed distance "s4" should have to "s7". * * The element with id "s0" allways stays in the center. * * settings can be made by altering several values in gnodMap, e.g. * gnodMap.scale=0.4; // makes the map smaller * * DEPRECATED (see also end of this file): * settings can be set via a global object "gnodMapSettings": * * minX, maxX, minY, maxY: boundaries of drawing area * * offsetX, offsetY: move center out of the drawing area's center. * * nrItems: maximum number items to be displayed, even if Aid[][] is larger * * *****************************************************************************/ /** * A moving HTML element */ function mg_2d_element(id) { this.id=id; this.x=0; this.y=0; this.speedX=0; this.speedY=0; this.element=document.getElementById("s"+this.id); this.name=this.element.innerHTML; this.width =this.element.offsetWidth; this.height=this.element.offsetHeight; this.inertia=0.7; this.update=function(damper) { this.element.style.left=this.x-this.width /2; this.element.style.top =this.y-this.height/2; this.x+=this.speedX/damper; this.y+=this.speedY/damper; this.speedX*=this.inertia; this.speedY*=this.inertia; } } function GnodMap() { this.aid=null; // aid[i1][i2]: proposed similarity between the two items i1, i2. this.maxItems=0; // max. number of items to draw. if set to 0, dimension of aid[] is used. // adjustable constants ------------------------------------------------------ // window size and scaling this.left =0; // left border of drawing area this.top =0; // top border of drawing area this.bottom =0; // bottom border, automatically detected if not set. this.right =0; // right border, automatically detected if not set. this.offsetX =0; // x displace central item this.offsetY =0; // y displace central item this.scaleFactor =1.4; // scaling in respect to calculated window space this.scaleByCenterDist=-1; // scaling in respect to mean target center distance (mean aid[i][0]) // timing this.frameDelayInitial=25; // initial value of increasing delay at each timestep this.slowdownCycle =300; // number of timesteps after that delay is increased // physics this.inertia =0.7; // part of velocity kept in one timestep this.damperInitial =1; // initial value of increasing damper that cool down motion with time this.damperFactor =1.002; // factor the damper is increased by in one timestep this.damperMax =100; // max. value of damper this.springForce0 =0.025; // force between each item and the central item s0 trying to keep them at aid[][]-distance this.springForce =0.005; // force between each item pair except the central item s0 this.centeringForce =0.1; // force that pulls the center of gravity towards the central item // overlap avoiding this.repelDelay =200; // nr. of timesteps without repulsion this.repelIncrease =0.001; // amount the repelling force that keeps items non overlapping increases each timestep this.repelMax =0.15; // max amount of repelling force. this.paddingFactor =1; // factor by which an item is enlarged while avoiding overlap // ---------------------------------------------------------------------------- var nrItems; // number of items to layout var maxX, maxY, minX, minY; // bounds of drawing area var scaleX,scaleY; // scale to make anything fit var cogX, cogY; // center of gravity of all items var cycle=0; // refresh cycle counter var frameDelay; // delay between redraws var damper; // increasing damper to cool down motion var repel; // increasing force that repells items to not overlap each other /** * update minX,minY,maxX,maxY to window size * may be overridden by gnodMapSettings */ this.updateBoundaries=function() { minX=this.left; minY=this.top; var haveIE4orNewer = (document.all) ? 1 : 0; if (haveIE4orNewer) { maxX = document.body.clientWidth; maxY = document.body.clientHeight; } else { maxX = window.innerWidth; maxY = window.innerHeight; } if (this.right ) maxX=this.right ; if (this.bottom) maxY=this.bottom; } /** * returns the mean item dimensions (width, height) */ this.getMeanItemSize=function() { var meanW=0, meanH=0; for (i=1;imaxX) items[i].x=maxX-w; if (items[i].x-wmaxY) items[i].y=maxY-h; if (items[i].y-h=0 && values[i]0 && !no_overlap) { // calculate minimal overlapping var oMin=positiveMin(Array(oLeft, oRight, oTop, oBottom)); var distance=Math.sqrt(dx*dx+dy*dy); // repel item in respect to current overlapping // we assume that dx,dy is a useful direction to decrease the overlapping var repelScaler=repel*oMin/distance; item1.x+=dx*repelScaler; item1.y+=dy*repelScaler; } } /** * do one layout step. */ this.layoutStep=function () { this.layoutItems(); this.recenterItems(); this.updateItems(); if (damperthis.repelDelay && repelthis.slowdownCycle) frameDelay++; cycle++; // schedule next layout step var thisMap=this; setTimeout(function(){thisMap.layoutStep()},frameDelay); } this.sum_of_squared_errors=function() { var error0=0, error=0; for(i1=0; i1needle) high=mid-1; else if (value0) values.push(this.aid[i][j]); values.sort(); //assign each aid[][] the rank of its value in values[] normalized to 0.0...1.0 for (var i=0; i0) { this.aid[i][j]=1-(search(this.aid[i][j], values)/values.length); } } /** * initially place every item and start refresh timer. */ this.init=function () { // Even though init() gets called on window.onload, in IE it sometimes // gets started with a screen size of 0. If so, we try again later: this.updateBoundaries(); if (maxX<1 || maxY<1) { setTimeout(function(){gnodMap.init()},500); return; } nrItems=this.aid[0].length; if (this.maxItems && nrItems>this.maxItems) nrItems=this.maxItems; this.equalizeAid(); this.resetItemPositions(); setTimeout(function(){gnodMap.layoutStep()},10); // let's go. } // ---------------------------------------------------------------------------- // install event handlers. // // instead of calling init directy, we attach it to the window.onload event // especially when the map is loaded, the screensize might not be set // before that event var thisMap=this; window.onload=function() { thisMap.init(); } document.onkeypress=function(event) { return thisMap.keyPress(event); } window.onresize=function() { thisMap.resetItemPositions(); } } gnodMap=new GnodMap(); //assign deprecated global settings: gnodMap.aid=Aid; gnodMap.maxItems=gnodMapSettings.nrItems; gnodMap.left =gnodMapSettings.minX; gnodMap.top =gnodMapSettings.minY; gnodMap.right =gnodMapSettings.maxX; gnodMap.bottom =gnodMapSettings.maxY; gnodMap.offsetX =gnodMapSettings.offsetX; gnodMap.offsetY =gnodMapSettings.offsetY;
Create a new entry at this position