0

What I'm trying to do:
-A javaScript animation (114 frames in total) that swaps out one image for the next in fast succession.
-onmouseover an image of a door opens. (plays 72 frames and stays on frame 72)
-onmouseout the door closes. (plays 42 frames and stays on the last frame)
-if the mouse is moved away from the element before the animation is completed, it will finish the 72 frames and then play the 42 frames.
-if the mouse is moved back onto the element before the 42 frames have finished, it will finish playing the 42 frames and then play the 72 frames.

The problems:
-I'm a noob at javaScript and don't fully understand it yet.
-Even though it sort of works, it's very buggy, you can't move your mouse away from the element without messing up the animation.
-Also, I can't figure out how to make it do all of the things listed above.

Here's the code I have right now:

HTML:  
<div onmouseover="openDoor()" onmouseout="closeDoor()" id="door2"></div>
<div id="door">
<img src="images/Animation_Door/0001.png">
<img src="images/Animation_Door/0002.png">
<img src="images/Animation_Door/0003.png">
...etc... (114 frames)
</div>

CSS:
#door {
background-color:transparent;
...etc...
}

.door img{
    display: none;
}

.door img:first-child {
display: block;
}


javaScript:
function openDoor() { 
var ti, frame = 0;
var frames = document.getElementById("door").children;
var frameCount = frames.length;

for (i=0; i<72; i++) {
ti = setTimeout(function(){
frames[i % frameCount].style.display = "none";
frames[++i % frameCount].style.display = "block";
}, 50*i);
}
}

function closeDoor() { 
var ti, frame = 0;
var frames = document.getElementById("door_close").children;
var frameCount = frames.length;

for (i=0; i<42; i++) {
setTimeout(function(){
frames[i % frameCount].style.display = "none";
frames[++i % frameCount].style.display = "block";
}, 50*i);
}
}
user1868086
  • 89
  • 1
  • 11
  • 4
    1. Your animation is likely to be much faster and smoother if you have those 72 frames as sprites in one physical image file, instead of requesting 72 separate image files. – techfoobar Dec 02 '12 at 06:08
  • 2. Why not just have a GIF file? – techfoobar Dec 02 '12 at 06:08
  • I tried doing a sprite and didn't have much success because of my general lack of knowledge regarding javaScript. It seems to run fine as individual images, but if I could do it with a sprite that would be great too. – user1868086 Dec 02 '12 at 06:13
  • can you post a fiddle - http://jsfiddle.net - so i can take a look at it and recommend the fixes. It may even be possible to do this with just one flat door image and css transforms. :-) – techfoobar Dec 02 '12 at 06:36
  • here it is, right now the animation is set to onClick. Also, I haven't finished rendering the final images for the end result, so right now doorOpen() and doorClose() are both only 41 frames, but in the end they will be what I originally posted. Alot of the code that is on there is the rest of my site, so I apologize for the cluttered mess. http://jsfiddle.net/reveries/a8Y9J/ – user1868086 Dec 02 '12 at 07:00
  • so 2 animated gifs then - still way faster and smaller (2 server requests vs 114 and proper animated gifs only overlay the difference for each layer, giving up to 90% improvement in compression) I have written an image differencer for gif/png and a sprite generator in c - if interested, I'll post them. – technosaurus Dec 02 '12 at 07:08
  • Check the answer i have posted. I hope it will give you some hints. – techfoobar Dec 02 '12 at 07:11
  • **Note:** Tested only in Chrome (use browser specific variants of `transform` to make it compatible with all browsers) – techfoobar Dec 02 '12 at 07:12

2 Answers2

1

This should give you some hints.

Notes:

  • Uses just 1 image - a flat door (just used some image from google image search for door - replace with your own)
  • Animation handled completely with CSS transforms

Demo: http://jsfiddle.net/LA6VW/3/

HTML

<div class="doorframe">
    <div class="door"></div>
</div>

CSS

.doorframe {
    border: 1px solid black;
    display: inline-block;
}
.door {
    width: 60px;
    height: 140px;
    background-color: #ccc;
    border: 1px solid #444;
    -webkit-transform-origin: left;
    background-image: url("http://www.doorasia.in/images/gallery/moulded_door01.jpg");
    background-position: -49px -7px;
    background-size: 158px 155px;
}​

JS:

var animating = false;

$('.doorframe').mouseenter(function() {
    if(animating) return;
    var door = $('.door');
    animating = true;
    openDoor(door, 5);
});
$('.doorframe').mouseleave(function() {
    if(animating) return;
    var door = $('.door');
    animating = true;
    closeDoor(door, 90);
});

function openDoor(door, angle) {
    if(angle >= 90) {
        animating = false;
        return;        
    }
    door.css('-webkit-transform', 'perspective(200px) rotateY( '+angle+'deg )');
    setTimeout(function() {
        openDoor(door, angle+=5);
    }, 50);
}

function closeDoor(door, angle) {
    if(angle < 0) {
        animating = false;
        return;        
    }
    door.css('-webkit-transform', 'perspective(200px) rotateY( '+angle+'deg )');
    setTimeout(function() {
        closeDoor(door, angle-=5);
    }, 50);
}

​
techfoobar
  • 65,616
  • 14
  • 114
  • 135
  • lol, sorry man, that's not at all what I'm looking for. I don't know if you saw the image on my jsfiddle, but that cannot be replicated with one image. It's a 3D rendering that is designed to look realistic complete with caustics and lighting and everything. I either need to use a sprite, or load the individual images one after another. (or some other way of animating with all 114 frames that I intend to use). This door is also a an alpha transparent png so that I can make it look like the door opens up to another world. – user1868086 Dec 02 '12 at 07:30
  • also, your animation of the door has many of the same bugs as my original post. – user1868086 Dec 02 '12 at 07:32
  • ahh.. ok. :0) Now *that* cannot be done with CSS transforms. I just saw the image on your fiddle. All i can say is maybe animating via JS/CSS is not your best bet if the images are gonna be of such high def and size. – techfoobar Dec 02 '12 at 07:33
  • what's a better language to use then do you think? (other than flash/action script, obviously) I only know html, css, (a little) javaScript, and some php. However, I'd be willing to take the time to learn another language if it could get me better results for this. – user1868086 Dec 02 '12 at 07:35
  • the animation runs fine right now, looks smooth enough for me/doesn't freeze or anything. My big problem is just writing some code that tells it to always finish the animation it's currently running (even if the mouse leaves the element/comes back again/etc...) THEN start the next animation if it's been triggered. – user1868086 Dec 02 '12 at 07:41
  • or maybe even to prevent the next animation from being triggered until the current animation finishes? I just don't know how to do it. – user1868086 Dec 02 '12 at 07:42
  • you can set a flag when starting the animation and check that before starting off another - a sample of which you can see in my code above. – techfoobar Dec 02 '12 at 07:46
0

2 options:

2 animated gifs

  • 1 animated gif for open + 1 animated gif for close
  • faster and smaller than sprites

cons - may lose image quality

css sprites

  • more complex but keeps image quality
  • faster than current situation

for a better understanding of the pros and cons of both see: Animated .GIF vs Spritesheet + JS/CSS

but I have written an image differencer that will take the difference between 2 images and leave the rest transparent

http://www.murga-linux.com/puppy/viewtopic.php?t=81387

that you can use in a css sprite and overlay each sprite to get the benefits of gif with the image quality of png

here is a really generic sprite generator that I put together in C

http://www.murga-linux.com/puppy/viewtopic.php?t=82009

Community
  • 1
  • 1
technosaurus
  • 7,676
  • 1
  • 30
  • 52