Raphaël.js animation resume() fails on set
Asked Answered
N

2

6

I have this piece of code (on jsfiddle)

var paper = new Raphael('holder', 400, 100);

var set = paper.set();

for(var i = 0; i < 10; i++) {
    var circle = paper.circle((i * 30) + 30, 20, 5);
    circle.attr({ fill: '#ff0' });
    circle.animate(Raphael.animation({ transform: 's2,2' }, 2000).repeat('Infinity'));

    set.push(circle);
}

set.hover(function() {
    set.pause();
}, function() {
    set.resume(); // <- things get nasty here
});​

Now when the mouse enters the set, set.pause() is called correctly and all animations stop.
But when leaving the hover area it doesn't resume the animation(s), instead I get following error in the console:

Uncaught TypeError: Cannot read property 'transform' of undefined

I have no idea why this happens; is anybody able to help?

Nerta answered 5/7, 2012 at 16:41 Comment(1)
I linked the uncompressed Räphâël.js for debugging: jsfiddle.net/7nGcR/23 After hover out, it resumes playback, but dies just before looping again at raphael.js:line#2946 with e.totalOrigin is undefinedAllsopp
A
6

On Safari/Firefox, after some time after hovering out, I received this error message (using the uncompressed source at https://raw.github.com/DmitryBaranovskiy/raphael/master/raphael.js ):

`raphael.js`, line 2946: `e.totalOrigin is undefined`

The only place where totalOrigin is set is the runAnimation function:

line 3072: function runAnimation(anim, element, percent, status, totalOrigin, times) {

Your code calls first elproto.pause() (line 3352), then elproto.resume() (line 3361). pause() sets the paused property to true, resume() deletes this property. But resume also calls the status() method right after deleting the paused flag:

var e = animationElements[i];
if (eve("raphael.anim.resume." + this.id, this, e.anim) !== false) {
    delete e.paused;
    this.status(e.anim, e.status);
}

The strange, work-in-progress elproto.status method (line 3323) is only called by elproto.setTime() and elproto.resume(). This function constructs some complex return value, but no active code uses its return value, only the commented out lines starting at line 2980.

This function also calls the runAnimation function, if it has a value parameter:

 runAnimation(anim, this, -1, mmin(value, 1)     );
          totalOrigin should be passed here! ^^^

Unfortunately, it doesn't pass anything for totalOrigin, and this is the cause of the bug.

I tried adding a totalOrigin parameter based on line 3312:

 runAnimation(anim, this, -1, mmin(value, 1), this.attr());

While it seems to work, it goes buggy.

As a second attempt, I commented out the whole line:

 // runAnimation(anim, this, -1, mmin(value, 1));

Result: it works, but the timing is wrong, probably the animation start time should be updated somewhere.

http://jsfiddle.net/7nGcR/26/ https://raw.github.com/gist/3067995/1e82de48eeacf98697b572efdc74c11a9b1d9d03/gistfile1.js

Allsopp answered 7/7, 2012 at 20:35 Comment(2)
Awesome; very good analysis! Thank you very much! That's a good point to start with, and if I don't get it to work, I will file a bug report.Nerta
Exactly, that's why it needs further research, feel free to do the investigation for the bounty :)Allsopp
S
0

in the elproto.status method, you need to replace (lines 5127-5128 in Raphael 2.1.4)

runAnimation(anim, this, -1, mmin(value, 1));
return this;

with

for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
    e = animationElements[i];
    runAnimation(anim, this, -1, mmin(value, 1), e.totalOrigin, e.repeat);
    return this;
}
Svoboda answered 25/1, 2016 at 23:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.