Go
New
Find
Notify
Tools
Reply
  
-star Rating Rate It!  Login/Join 
Honorary Mechanic
Picture of Geek-u-like (Andrew)
Posted
Something slightly different: a 3d rotating slideshow

I would first like to acknowledge Yusuke Kawasaki http://www.kawa.net/ as the original author of the scripts contained here. The implementation in SS is mine!

See it working here

How to do it.

1. Put the following code in a file called Cube.js (note the capitalised C)

Thats everything from the line below...
// Animation.Cube
//### there is probably nothing in here that needs changing###
//### please not however the credit and license at the bottom###
//###if you use this code, please leave the credit in the code - its only polite###

if ( typeof(Animation) == "undefined" ) Animation = function () {};

Animation.Cube = function ( ifrom, idest ) {
this.imageLoaded = false; // next image is loaded or not
this.startOnLoad = false; // start commanded received
this.is_running = false; // all done flag
var init = this.initialize(ifrom,idest);
if ( ! init ) return;
return this;
};

Animation.Cube.VERSION = "0.04";
Animation.Cube.prototype.onComplete = null; // callback function
Animation.Cube.prototype.onInterval = null; // callback function
Animation.Cube.prototype.background = null;
Animation.Cube.prototype.waitSeconds = 0.000;
Animation.Cube.prototype.rotateSeconds = 0.500;
Animation.Cube.prototype.viewDistance = 2.000; // or 1.414, 1.732
Animation.Cube.prototype.minResolution = 2;
Animation.Cube.prototype.maxResolution = 32;
Animation.Cube.prototype.cursor = 0;
Animation.Cube.prototype.repeat = true;
Animation.Cube.prototype.clockWise = true;

Animation.Cube.prototype.initialize = function ( ifrom, idest ) {
this.canvas = document.createElement( "div" );
this.canvas.style.position = "relative";

// canvas base
this.imgBase = new Animation.Cube.Image( this.canvas );
var ebase = this.imgBase.fromElement( ifrom );
if ( ! ebase ) return;

this.canvasWidth = ebase.offsetWidth;
this.canvasHeight = ebase.offsetHeight;
ebase.parentNode.insertBefore( this.canvas, ebase );

var imglist;
if ( typeof(idest) == "string" ) {
imglist = [ ebase.src, idest ];
this.repeat = false;
} else {
imglist = idest;
this.repeat = true;
}
this.imgBuffer = [];

var __this = this;
var __len = imglist.length;
var trigcheck = function (elem) {
for( var i=0; i<__len; i++ ) {
if ( ! __this.imgBuffer[i].loaded ) return;
}
__this.imageLoaded = true;
if ( __this.startOnLoad ) {
__this.startOnLoad = false;
__this.beginAnimation();
}
};

for( var i=0; i<imglist.length; i++ ) {
this.imgBuffer[i] = new Animation.Cube.Image( this.canvas );
this.imgBuffer[i].onLoad = trigcheck;
this.imgBuffer[i].fromURL( imglist[i] );
}

return true;
};

Animation.Cube.appendEvent = function( elem, type, func ) {
if ( elem.addEventListener ) {
return elem.addEventListener( type, func, false );
} else if ( elem.attachEvent ) {
return elem.attachEvent( "on"+type, func );
}
};

Animation.Cube.prototype.rotate = function() {
if ( this.is_running ) return; // already started
if ( this.imageLoaded ) {
this.beginAnimation();
} else {
this.startOnLoad = true; // wait until image loaded
}
};

Animation.Cube.prototype.beginAnimation = function() {
if ( this.background ) {
this.canvas.style.background = this.background;
}

var curnext = this.nextCursor(this.cursor);

this.imgBase.elem.style.visibility = "hidden";

this.rotation = this.clockWise ? 0.0 : 1.0;
if ( this.clockWise ) {
this.imgLeft = this.imgBuffer[this.cursor];
this.imgRight = this.imgBuffer[curnext];
} else {
this.imgLeft = this.imgBuffer[curnext];
this.imgRight = this.imgBuffer[this.cursor];
}

this.startWise = this.clockWise;

this.is_running = true;
this.timer = new Animation.Cube.Timer(this); // timer object
this.timer.start();
};

Animation.Cube.prototype.nextCursor = function(cur) {
if ( this.clockWise ) {
cur ++;
cur = cur % this.imgBuffer.length;
} else {
cur --;
if ( cur < 0 ) cur += this.imgBuffer.length;
}
return cur;
};

Animation.Cube.prototype.dispEdge = function() {
if ( this.timer ) {
if ( this.timer.is_running() ) this.timer.stop();
this.timer = null;
}
if ( ! this.is_running ) return;

this.imgLeft.hideClip( 0 );
this.imgRight.hideClip( 0 );

if ( this.startWise == this.clockWise ) {
this.cursor = this.nextCursor(this.cursor);
}
this.startWise = null;
this.imgBase.elem.src = this.imgBuffer[this.cursor].elem.src;
this.imgBase.elem.style.width = this.canvasWidth +"px";
this.imgBase.elem.style.height = this.canvasHeight+"px";
this.imgBase.elem.style.visibility = "visible";
};

Animation.Cube.prototype.nextAnimation = function() {
this.dispEdge();
var __this = this;
var func = function () {
if ( ! __this.is_running ) return;
__this.beginAnimation();
}
if ( this.onInterval ) this.onInterval(this.cursor);
if ( ! this.is_running ) return;
setTimeout( func, this.waitSeconds*1000 );
};

Animation.Cube.prototype.finish = function() {
this.dispEdge();
// this.canvas.parentNode.removeChild( this.canvas ); // clear canvas
this.is_running = false;
if ( this.onComplete ) this.onComplete(this.cursor);
};

Animation.Cube.prototype.loop = function(secs,diff,count) {
if ( ! this.is_running ) return;
if ( ! this.clockWise ) diff = - diff;
this.rotation += diff * 0.001 / this.rotateSeconds;

var fincheck = false;
if ( this.rotation > 1.0 ) {
this.rotation = 1.0;
fincheck = true;
} else if ( this.rotation < 0.0 ) {
this.rotation = 0.0;
fincheck = true;
}

this.display( this.rotation );

if ( fincheck ) {
if ( this.repeat ) {
this.nextAnimation();
} else {
this.finish();
}
return false;
} else {
return true;
}
};

Animation.Cube.prototype.display = function( prog ) {
var alpha = (1.0-2.0*prog)/4.0*Math.PI;
var sina = Math.sin( alpha );
var cosa = Math.cos( alpha );
var ah = this.viewDistance / ( this.viewDistance +(cosa+sina));
var bh = 1;
var ch = this.viewDistance / ( this.viewDistance +(cosa-sina));
var aw = cosa * ah;
var bw = sina;
var cw = -cosa * ch;

var ow = 0;
if ( aw > Math.SQRT1_2 ) ow = aw-Math.SQRT1_2;
if ( cw < -Math.SQRT1_2 ) ow = cw+Math.SQRT1_2;
if ( ow ) {
aw -= ow;
bw -= ow;
cw -= ow;
}

if ( aw > bw ) {
this.dispPanel( this.imgRight, bw, bh, aw, ah);
} else {
this.imgRight.hideClip( 0 );
}
if ( cw < bw ) {
this.dispPanel( this.imgLeft, cw, ch, bw, bh );
} else {
this.imgLeft.hideClip( 0 );
}
};

Animation.Cube.prototype.dispPanel = function( img, x1, h1, x2, h2 ) {
if ( x1 > x2 ) {
var x0 = x1;
x1 = x2;
x2 = x0;
var h0 = h1;
h1 = h2;
h2 = h0;
}

var lx = Math.round( Math.SQRT1_2 * this.canvasWidth * (x1+Math.SQRT1_2) );
var lh = Math.round( this.canvasHeight * h1 );
var ly = Math.round((this.canvasHeight-lh)/2);
var rx = Math.round( Math.SQRT1_2 * this.canvasWidth * (x2+Math.SQRT1_2) );
var rh = Math.round( this.canvasHeight * h2 );
var ry = Math.round((this.canvasHeight-rh)/2);

var reso = this.canvasWidth;
if ( ry != ly ) {
reso = Math.round(Math.abs(2.0*(rx-lx)/(ry-ly)));
if ( reso > this.maxResolution ) reso = this.maxResolution;
if ( reso < this.minResolution ) reso = this.minResolution;
}

var ww = rx-lx;
var clipnum = 0;
for( var ix=lx; ix<rx; ix+=reso ) {
var prog = (ix-lx)/(rx-lx);
var iy = Math.round( ly + (ry-ly)*prog );
var ih = Math.round( lh + (rh-lh)*prog );
var iw = reso;
if ( ix+iw > this.canvasWidth ) iw = this.canvasWidth - ix;
img.dispClip( clipnum, ix,iy,iw,ih,prog,ww );
clipnum ++;
}
img.hideClip( clipnum );
};

// Animation.Cube.Image class

Animation.Cube.Image = function( work ) {
this.plane = null;
this.work = work; // work div element
this.elem = null; // image element
this.onLoad = null; // callback function
this.clipbuf = [];
this.loaded = false;
this.lasthided = null;
return this;
};

Animation.Cube.Image.prototype.getClip = function( num ) {
if ( this.clipbuf[num] ) return this.clipbuf[num];
var line = this.elem.cloneNode(true);
line.style.position = "absolute";
line.style.display = "";
line.style.visibility = "hidden";
this.clipbuf[num] = line;
return line;
};

Animation.Cube.Image.prototype.hideClip = function( num ) {
var lastclip = this.clipbuf.length;
if ( this.lasthided != null ) lastclip = this.lasthided;
for( var i=num; i<lastclip; i++ ) {
this.clipbuf[i].style.visibility = "hidden";
}
this.lasthided = num;
};

Animation.Cube.Image.prototype.dispClip = function( num,left,top,width,height,prog,xcomp) {
var line = this.getClip( num );
var offset = Math.round(xcomp*prog);
var lstyle = line.style;
lstyle.left = (left-offset)+"px";
lstyle.width = xcomp+"px";
lstyle.top = top+"px";
lstyle.height = height+"px";
lstyle.visibility = "visible";
lstyle.clip = "rect(0px,"+(offset+width)+"px,"+(height)+"px,"+offset+"px)";
this.work.appendChild( line );
};

Animation.Cube.Image.prototype.fromElement = function( elem ) {
if ( typeof elem == "string" ) {
elem = document.getElementById(elem);
}
if ( ! elem ) return;
if ( elem.tagName != "IMG" ) return;
this.elem = elem;
this.loaded = true;
return elem;
};

Animation.Cube.Image.prototype.fromURL = function( url ) {
var elem = document.createElement( "img" ); // new image
elem.src = url;
elem.style.visibility = "hidden";
elem.style.position = "absolute";
this.work.appendChild( elem );
this.checkLoaded( elem );
this.elem = elem;
return elem;
};

Animation.Cube.Image.prototype.checkLoaded = function( orig ) {
var check = orig.cloneNode(true); // image to check
var __this = this;
var ldfunc = function(e){
if ( ! e && window.event ) e = window.event; // IE event
__this.loaded = true;
check.parentNode.removeChild( check );
if ( __this.onLoad ) __this.onLoad();
};
Animation.Cube.appendEvent( check, "load", ldfunc ); // onload image
this.work.appendChild( check );
};

// Animation.Cube.Timer class

Animation.Cube.Timer = function (target) {
this.target = target;
this.started = false;
this.stoped = false;
this.count = 0;
var __this = this;
this.next = function(){
if ( __this.stoped ) return;
var now_time = (new Date()).getTime();
if ( ! __this.begin_time ) __this.begin_time = now_time;
if ( ! __this.prev_time ) __this.prev_time = now_time;
var spent_time = now_time-__this.begin_time;
var diff_time = now_time - __this.prev_time;
__this.prev_time = now_time;
var flag = __this.target.loop(spent_time,diff_time,__this.count++);
if ( flag ) {
setTimeout( __this.next, 1 );
} else {
__this.stop();
}
};
return this;
};

Animation.Cube.Timer.prototype.start = function () {
this.started = true;
this.stoped = false;
this.next();
};

Animation.Cube.Timer.prototype.now = function () {
return (new Date()).getTime();
};
Animation.Cube.Timer.prototype.stop = function () {
this.stoped = true;
};

Animation.Cube.Timer.prototype.is_running = function () {
return ( this.started && ! this.stoped );
};

/*
// ========================================================================

=head1 NAME

Animation.Cube -- Rotating Cube Animation

=head1 SYNOPSIS

var ras = new Animation.Cube( id_or_elem, image_url );
ras.rotate();

=head1 DESCRIPTION

This library provides a rotating cube animation.

=head1 METHODS

=head2 ras = new Animation.Cube( id_or_elem, image_url );

This constructor method returns a new Animation.Cube object.

=head2 ras.rotate();

This method starts a animation effect.

=head2 ras.finish();

This method forces to stop a animation effect if it's running.

=head1 AUTHOR

Yusuke Kawasaki http://www.kawa.net/

=head1 COPYRIGHT AND LICENSE

Copyright (c) 2005-2006 Yusuke Kawasaki. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the Artistic license. Or whatever license I choose,
which I will do instead of keeping this documentation like it is.

=cut
// ========================================================================
*/
...upto and including the line above

Then put all the following code into a file called cube-demo.js (non capitalised c)
...everything from the line below...
// cube-demo.js

//### Relative paths to your images go in the four or however many lines below ###

var cube_list = [
"images/image1.jpg",
"images/image2.jpg",
"images/image3.jpg",
"images/image4.jpg"
];

function cube2_go (f) {
var img = document.getElementById( "cube2_area" );
var u1 = f.url1.value;
var u2 = f.url2.value;
img.src = u1;
var cube2 = new Animation.Cube( img, u2 );
if ( f.secs.value-0 ) cube2.rotateSeconds = f.secs.value-0;
if ( f.minres.value-0 ) cube2.minResolution = f.minres.value-0;
if ( f.maxres.value-0 ) cube2.maxResolution = f.maxres.value-0;
cube2.clockWise = f.clock.checked ? true : false;
cube2.onComplete = function () {
if ( u1 == f.url1.value && u2 == f.url2.value ) {
f.url1.value = u2;
f.url2.value = u1;
}
};
cube2.rotate();
}
var cube1;

function cube_init () {
cube1 = new Animation.Cube( "cube_area", cube_list );
// cube1.onComplete = function (c) {alert("complete="+c)};
// cube1.onInterval = function (c) {alert("interval="+c)};


//### Variables for the animation go here, values in seconds###
cube1.rotateSeconds = 1.0;
cube1.waitSeconds = 1.0;
}
function cube_start () {
if ( ! cube1 ) cube_init();
cube1.rotate();
}
function cube_retry () {
if ( ! cube1 ) cube_init();
cube1.rotate();
}
function cube_reverse () {
if ( ! cube1 ) cube_init();
cube1.clockWise = ! cube1.clockWise;
}
function cube_stop () {
if ( ! cube1 ) cube_init();
cube1.finish();
}
function cube_speedup () {
if ( ! cube1 ) cube_init();
cube1.rotateSeconds *= 0.5;
}
function cube_speeddown () {
if ( ! cube1 ) cube_init();
cube1.rotateSeconds *= 2.0;
}
...upto and including the line immediately above.

the lines that start //### indicate where you have user variables.

These two files should now be saved into the publish directory of your project.

2. Now in ss.
Create a new header for the page you wish to have the slide show in.
Add the following code into your new header:
Note: the relative paths to your external script files and the capitalisation

<script src="Cube.js"></script>
<script src="cube-demo.js"></script>
<script><!--
var cache = new Image();
cache.src ="images/wheels/image1.jpg";
// window.onload = cube_start;
// --></script>

3. put the following code in a code block on your page:

<form align="center">
<p>
<input type="button" onClick="cube_retry();" value="START" style="font-family:Arial; font-size:9pt">
<input type="button" onClick="cube_stop();" value="STOP" style="font-family:Arial; font-size:9pt">
<input type="button" onClick="cube_reverse();" value="REVERSE" style="font-family:Arial; font-size:9pt">
<input type="button" onClick="cube_speedup();" value="FASTER" style="font-family:Arial; font-size:9pt">
<input type="button" onClick="cube_speeddown();" value="SLOWER" style="font-family:Arial; font-size:9pt">
</p>
</form>

This allows the user to play withe the slideshow

4. Create a code block div to hold a static image and as a destination object for the slideshow

<div>
<img id="cube_area" src="images/image1.jpg">
</div>

You won't see it in preview, only a broken image placeholder, when you vieww the published page, it should work.

Amazing amount of wizzy math being done on the fly in javascript.

I hope this works for you
 
Posts: 122 | Location: Elworth, Sandbach, Cheshire, England | Registered: October 20, 2006Reply With QuoteEdit or Delete MessageReport This Post
Honorary Mechanic
Picture of Geek-u-like (Andrew)
Posted Hide Post
If anybody thinks this is a duplicate post to one they saw in another discussion area, it isn't, looks like I posted it in the wrong place and the very nice VM moderators, kindly moved it somewhere more appropriate. (oops Red Face) Sorry guys.
 
Posts: 122 | Location: Elworth, Sandbach, Cheshire, England | Registered: October 20, 2006Reply With QuoteEdit or Delete MessageReport This Post
Junior Mechanic
Picture of Mahalo
Posted Hide Post
Your site looks nice and loads super fast.
Great job! Thanks for the info on the rotating cube.


Some people think being called a hack is an insult...I think of it as a compliment.
http://www.carvenimage.com
http://www.myspace.com/carvenimage
 
Posts: 3 | Registered: February 06, 2008Reply With QuoteEdit or Delete MessageReport This Post
  Powered by Eve Community  
 


™ & © 1998 - 2008, Virtual Mechanics Inc. All rights reserved.