WebDevelopersJournal.comTips on Web Page Design, HTML and Graphics
SITE SEARCH
Newsletters
HTML (M-F) Text (M,TH)



Jobs at webdeveloper.com

Resources By Subject
Technical
Graphical
Authoring
Business
WDJ resources
Archive

internet.com

internet.commerce
  • Partner With Us
















Developer Channel


Find a web host with:
CGI Access DB Support Telnet Access
NT Servers UNIX Servers



Semi-automatic?

JavaScript
JavaScript Helper:
Meet Paige Turner, the least geeky geek we've ever come across.

Variables and Operators Explained:
First of a three part guide to JavaScript basics.

Controlling Forms:
Enhance your HTML forms with a touch of JS.

DHTML:
Forget how it works, let's see some in action!


Anatomy of a JavaScript Picture Puzzle

by Guy Laor

Apparent Slicing

This simple JavaScript picture puzzle contains a unique feature. It uses DHTML techniques to show individual sections of a single picture, so it doesn't need multiple graphics files for the various slices. Here's a full explanation of how the code works.
January 17, 2001

First, an introduction to the puzzle. It's a straightforward shuffle-the-pieces puzzle. There's one blank space and the rest of the picture elements are in the wrong place. The player must make use of the blank space to shuffle the nearby pieces until everything's correctly positioned.

Here's a page showing the puzzle in action.

It's not a new kind of puzzle. Similar scripts exist. The difference lies in the way it's generated. Usually, when we want to make an image puzzle, we cut our image into small images, equal in size, so we end up with 16 little gif files created from one big file.

But this new technique uses JavaScript to create the smaller images on the fly. It's a demonstration of a new approach rather than a Copy & Paste script, though you are welcome to use the script yourself if you wish.

As you know, JavaScript is a very limited language that can't manipulate an image file. So how can we take the picture file and slice it for the picture puzzle? All we do is give the impression that we are slicing it. The trick is in the way we set up our div tags (or layers if we want to do it in Netscape). The example here works in Internet Explorer.

To show the first 50 pixels of our image we create a div tag, assign to it a style, and define the crop sizes in the style.

<div id="Holder" style="position: absolute; top: 200; left:100; clip : rect(0px, 50px, 50px, 0px)">

Anything we put inside this tag will be cropped to show only 50 pixels. This is one block of the picture puzzle. We need a few more div tags, each cropping our image, then we order the blocks incorrectly to distort the image. Finally we add functionality allowing the user to change the blocks' positions,

But there are a few extra problems to solve. If our image is 500x100% pixels, we can't make blocks 50 pixels square. The division won't work. This can be solved by a few lines of code that find the image size, divide it by the number of blocks, and so determine the crop dimensions.


var rows = 4;
var lines = 4;
var Ihight, Iwidth, cellH, cellW;
BaseImg = new Image;
BaseImg.src = "birth_of_venus.jpg";
Ihight = BaseImg.height;
Iwidth = BaseImg.width;
cellH = parseFloat(Ihight/rows);
cellW = parseFloat(Iwidth/lines);

Here, the variables cellH and cellW determine the right crop dimensions for our image.

The next problem we face is that so far our blocks show the same top corner of the image - the first 50 pixels (or some other figure). To solve this we create another div tag that goes inside the first and moves the image to different locations inside the first div. You can think of the first div as a window to look at the second div. In the second div we place the <img> tag.

<div id="Holder" style="position: absolute; top: 200; left:100; clip : rect(0px, 50px, 50px, 0px)">
<div id="Inn" style="position: absolute; top:-100; left:-150;">
<img src="birth_of_venus.jpg" name="mag4" border="0">
</div>
</div>

As you can see, the div called "Inn" has a negative position. Because it's displaying the image 100 pixels from the top left corner, to "lift up" the image, it has to have a negative position inside the "Holder" div. Note that the inner div position is relative to the holder div, and the holder div position is relative to the page itself.

All Elements

This code makes the lines and rows:

var Divnum=0;
for (i=0; i<rows; i++) {
for (a=0; a<lines; a++) {
Makeholder(Divnum, Itop, Ileft, cellH, cellW);
Ileft = Ileft+cellW;
MakeInner(Divnum, Ctop, Cleft);
Cleft = Cleft-cellW;
Divnum++;
}
Ileft = 100;
Cleft = 0;
Itop = Itop+cellH;
Ctop = Ctop-cellH;
}

function Makeholder(number, top, left, ctop, cleft)
{
HoldDiv[number] = '<div id="Holder'+number+'" style="position: absolute; top: '+top+'; left:'+left+'; clip : rect(0px, '+cleft+'px, '+ctop+'px, 0px)" onclick="pop('+number+')" >';

}

function MakeInner(number, top, left) {
InnerDiv[number] = '<div id="Inn'+number+'" style="position: absolute; top:'+top+'; left:'+left+';">';
}

These functions create all the blocks of the picture puzzle. Note the onclick event handler inserted in the Makeholder function. This is used to move the blocks.

Out Of Order

Now we need to shuffle the blocks and write them into the browser window. We have an Array of 16 unordered numbers.

RandNum = new Array(7,12,14,3,9,6,0,8,5,10,4,11,1,13,2,15,16);

You can create your own Arrays, but make sure there are no repeated numbers. With this Array we write the puzzle to the same browser window. Our example uses document.write(), though there are problems with this solution. You may find that the script shows the puzzle only on the second try, due to image caching problems. An alternative would be to use an innerHTML method.

Here is the code that writes the blocks. The first line writes JavaScript code that changes their order. Notice that the image tag is inserted in only 15 blocks (cells-1) to keep one block free for the player to use.

document.write(Scrip);
for (q=0; q<cells; q++) {
document.write(HoldDiv[q]);
var Rnumber = RandNum[q];
document.write(InnerDiv[Rnumber]);
if (q != cells-1){
document.write('<img src="'+IMAGE+'" name="mag'+q+'" border="0">');
eval ("document.mag"+q+".src = BaseImg.src");
}
document.write("</div></div>");

}

Next Page >>

Guy Laor is webmaster at PictureVision Israel R&D.
Suits PonytailsPropheadsContact WDJDiscussWeb AudioSearch

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info

Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers