Nostalgia with CSS Sprites

What?

I made this a long time ago to experiment with css, sprite images and object oriented prototyping in JavaScript. It tracks your mouse movement and assigns a proper section of the sprite depending on mouse location.

Why?

I’m organizing my computer files (Spring cleaning) and I stumbled upon this thing I made back in 2008 (4 years ago) and it cracked me up. So I decided to share the laughter.

How?

If you like your whiskey straight from the bottle then I won’t bore you with lots of details and you can skip straight to the source code or the index.html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<link rel="stylesheet" href="./sprite.css" />
<script src="jquery-1.4.2.min.js"></script>
<script src="animate-sprites.js"></script>

<div id="sprite-container">
<div id="sprite1-border" class="sprite-border"><div id="sprite1" class="sprite"></div></div>
<div id="sprite2-border" class="sprite-border"><div id="sprite2" class="sprite"></div></div>
<div id="sprite3-border" class="sprite-border"><div id="sprite3" class="sprite"></div></div>
</div>

<script>
loadSprite('#sprite1');
loadSprite('#sprite2');
loadSprite('#sprite3');
</script>

In the first attempt I wrote, I set background positions using javascript instead of css. This was slow, the code was more complicated and it was restrictive because my sprite images had to follow a strict width and height pattern.

So in the second version (what you see here), I simplified the javascript greatly by creating a column and row for each sprite in css. Not only did this work better and faster, it allowed me to statically set sprite locations and abstract locations from the javascript coding. Just another case where I should have KISS‘ed. Below is a paste bin of the two major components of what you see here. First the sprite.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.sprite {
background-image: url("./sprite-small.png");
background-repeat : no-repeat ;
background-position: -750px top;
width : 150px ;
height : 112px ;
}

.sprite-container { position: relative; }
.sprite-border {
border: 1px solid #4C3C1B;
padding: 5px;
background-color: #EFEECB;
width : 150px;
height : 112px;
position: absolute;
}

#sprite1-border { z-index: -1; top: 100px; left: 30px; }
#sprite2-border { z-index: -2; top: 30px; left: 150px;}
#sprite3-border { z-index: -3; }


.row0.col0 { background-position: left top; }
.row0.col1 { background-position: -150px top; }
.row0.col2 { background-position: -300px top; }
.row0.col3 { background-position: -450px top; }
.row0.col4 { background-position: -600px top; }
.row0.col5 { background-position: -750px top; }
.row0.col6 { background-position: -900px top; }
.row0.col7 { background-position: -1050px top; }

.row1.col0 { background-position: left -112px; }
.row1.col1 { background-position: -150px -112px; }
.row1.col2 { background-position: -300px -112px; }

... omitted for brevity ...

And here is the animate-sprite.js to go along with it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
var totalNumOfImages = 64;
var sprite = new Array();
var oldClass = new Array();
var xCenter = new Array();
var yCenter = new Array();

function loadSprite(id, x, y)
{
sprite.push(id);
oldClass.push("");

if (x == undefined) x = -1; // -1 means we calculate center each pass
if (y == undefined) y = -1; // in case the center of picture changes
// for example, a moving sprite or width changes

xCenter.push(x);
yCenter.push(y);

$( document ).mousemove(animateSprites);
}

function animateSprites(event)
{
var x = event.pageX;
var y = event.pageY;

for ( var i in sprite )
{
var c = getSpriteClass(sprite[i], i, x, y);
setSpriteClass(sprite[i], i, c);
}
}

function setSpriteClass(s, i, c)
{
if (oldClass[i] != "") $(s).removeClass(oldClass[i]);
$(s).addClass(c);
oldClass[i] = c;
}

function getSpriteClass(s, e, x, y)
{
var degrees = getSpriteDegree(s, e, x, y);
var degreeOffset = Math.abs(45 - degrees % 90);
var numPicsPerQuad = Math.sqrt(totalNumOfImages) * 2;

if (degreeOffset == 0) degreeOffset = 1; // gets rid of a glitch at 45 degree angles
var num = Math.floor(numPicsPerQuad - numPicsPerQuad * degreeOffset / 45);

var row = Math.floor(num / (Math.sqrt(numPicsPerQuad)));
var col = num % Math.sqrt(numPicsPerQuad);

if (degrees <= 90) col = col + Math.sqrt(numPicsPerQuad);
else if (degrees > 180 && degrees <= 270) row = row + Math.sqrt(numPicsPerQuad);
else if (degrees > 270 && degrees < 360)
{
row = row + Math.sqrt(numPicsPerQuad);
col = col + Math.sqrt(numPicsPerQuad);
}
return "row" + row + " col" + col;
}

function getSpriteDegree(s, e, x, y)
{
var cx = xCenter[e];
var cy = yCenter[e];

if (cx == -1) cx = $(s).offset().left + $(s).width() / 2;
if (cy == -1) cy = $(s).offset().top + $(s).height() / 2;

var dx = x - cx;
var dy = y - cy;

// find the angle of mouse pointer relavant to our picture
var degrees = 0;
if (dx != 0) degrees = Math.abs(Math.floor(Math.atan(dy/dx) * 180/Math.PI));

if (x >= cx)
{
if (y > cy && degrees != 0) degrees = 360 - degrees;
}
else
{
if (y < cy) degrees = 180 - degrees;
if (y >= cy) degrees = 180 + degrees;
}

return degrees;
}