05 April 2010

The Alchemist: CSS pseudo 3D.

In the following post, I use a two-and-a-half-dimensional (2.5) technique to fake a three-dimensional (3D) visualization of Joseph Wright of Derby's painting The Alchemist in Search of the Philosopher's Stone This post was mostly inspired by Román Cortès' 3D Menimas and a post on Experiment Garden.

The Alchemist in Search of the Philosopher's Stone


The following image/script was successfully tested under Firefox 3.6. Move your mouse over the image

How it works

Each component of the collage is part of a larger transparent picture:
An array defines each sprite. One sprite is defined by its rectangular clip (x,y,width,height) in the original image, its position (x,y) in the collage and a value (ratio) reflecting the amount of pixels it should scroll
var picts=[
{
/* background */
img:null,
clip:[0,0,image_width,image_height],
ratio:0.0,
x:0,y:0
},
{
/* people */
img:null,
clip:[227,1,111,147],
ratio:0.1,
x:5,y:154
},
(...)
];
The HTML is defined as follow:
<div id='id9879709_main' style='overflow:hidden;position:relative;background-color:red;width:226px;height:320px;border:1px solid black;'>
<span style="position:relative;padding:3px;background-color:white;top:15px;left:15px;border:2px solid black;z-index:100; font-weight: bold;"><a target="_wp" href="http://commons.wikimedia.org/wiki/File:JosephWright-Alchemist.jpg">The Alchemist</a></span>
</div>
.When this html document is loaded, a <div> clipping each sprite is created an inserted into the document:
var main=document.getElementById('main');
main.onmousemove = callback;
for(var i in picts)
{
var pict=picts[i];
pict.img=document.createElement("div"); pict.img.setAttribute("style","position:absolute;top:"+pict.y+"px;left:"+pict.x+"px;width:"+pict.clip[2]+"px;height:"+pict.clip[3]+"px;z-index:"+i+";background:url(alchemy02.png) no-repeat scroll -"+pict.clip[0]+"px -"+pict.clip[1]+"px;");
main.appendChild(pict.img);
}
Lastly a javascript callback is called each time the mouse moves over the image. This method shifts each sprites according to the value of its 'ratio':
var v=document.getElementById('id9879709_main');
var left=v.offsetLeft;
var width=226.0;
var midX= left+width/2.0;
var maxshift=30;
var mouseX=e.clientX;
if(mouseX &gt; left+width) mouseX=left+width;
if(mouseX &lt; left) mouseX=left;
var shift= ((e.clientX-midX)/(width/2.0))*maxshift;
for(var i in picts)
{
var pict=picts[i];
pict.img.style.left=(pict.x+shift*pict.ratio)+"px";
}


That's it
Pierre

4 comments:

  1. I get a javascript error:

    Error: missing ) after condition

    Source File: http://plindenbaum.blogspot.com/2010/04/alchemist-css-pseudo-3d.html
    Line: 444, Column: 138
    Source Code:
    ('id9879709_main'); var left=v.offsetLeft; var width=226.0; var midX= left+width/2.0;var maxshift=30; var mouseX=e.clientX; if(mouseX > left+width) { mouseX=left+width;} if(mouseX < left) {mouseX=left;} var shift= ((e.clientX-midX)/(width/2.0))*ma

    ReplyDelete
  2. Istvan, I fixed the bug. I didn't see the bug at the first time because the code was developped for XHTML and blogger.com uses HTML.

    ReplyDelete
  3. I have been visiting various blogs for my term papers writing research. I have found your blog to be quite useful. Keep updating your blog with valuable information... Regards

    ReplyDelete
  4. Very nice work! It looks great. I'm glad that my blog post at Experiment Garden helped inspire you.

    Nathan - Experiment Garden

    ReplyDelete