Is there a simple way to reset a TimelineMax JavaScript object? - javascript

I'm having trouble re-initializing a TimelineMax sequence. When the window is resized, I need to revert all the tweens to their default styles and re-initialize them based on the new window size. Is there a simple way to effectively destroy the timeline and start fresh, without manually resetting all the CSS properties?

Depending on what you are trying to achieve, I can suggest two methods.
The first is exactly as you are describing:
myTimeline.pause(0, true); //Go back to the start (true is to suppress events)
myTimeline.remove();
This takes everything back to the way they were at the start of the timeline. You can remove any initialization properties by calling .invalidate() as well.
The second method, I'm adding because it may be worth thinking about...
Rather than completely restarting the tweens/timeline, why not .invalidate() (items stay where they are, just the timeline itself is cleared) and use the tweening method .to() rather than .from(), as you'll get a nicer user experience when everything moves from it's previous position to it's new position rather than completely restarting.
Also, the majority of users don't resize the window. So think about whether or not it's worth it if it becomes a major time consumer.
API/Docs: http://api.greensock.com/js/

Related

How to completely dispose EaselJS canvas?

I'm working on a ReactJS app in which I'm using EaselJS to handle multiple canvases, on same page I have to add and remove different canvases on the base of different conditions to render different views. Even after removing a canvas using following code to dispose a canvas component
createjs.Touch.disable(this.stage);
this.stage.removeAllChildren();
this.stage.removeAllEventListeners();
this.stage.enableDOMEvents(false);
some events are being triggered. After using application for some time it start to use a lot of processing and memory. After having a look at performance tab in developer tools in chrome, I came to know a timer event is being called for every canvas which ever was added. After inspecting code I come to know that
this.stage.enableMouseOver();
is setting an setInterval timer which is not being removed even after calling all above code and I can't find any way to remove it.
Can anyone please help me to get rid of it.
Thanks in advance
The enableMouseOver method is documented to both add and remove the functionality from a Stage. By passing 0 as the frequency, the interval should be cleared.
stage.enableMouseOver(0);
From the documentation:
Enables or disables (by passing a frequency of 0)
and
frequency: Optional param specifying the maximum number of times per second to broadcast mouse over/out events. Set to 0 to disable mouse over events completely.
I did a quick pass on the code, and it definitely removes the interval.

How to restart a canvas without reload

I simply want to restart a canvas on a website. I do not want to reload the page, so the restart has to be done dynamically. Problem : after few restarts the animation gets slower and the memory increases.
Actually i face a more complex situation : I use a javascript framework to load pages, MeteorJS with IronRouter. Changing the URL only changes the DOM (nodes are removed) but the 'page' is not really left. So i thought that coming back to my page with the canvas can be assimilated to a dynamic canvas restart, since i have no solution to that too.
That is why i describe the problem from two points of view (same problem on both) :
first a simple page where a button asks the canvas to restart
then applying the solution to MeteorJS with IronRouter and try to come back on my page many times.
Note : my canvas content is some WebGL (in ThreeJS).
1. Deleting and re-initializing canvas dynamically.
In this case i face those two problems :
animation not smooth
memory increase. To be precise :
(source: hostingpics.net)
Page loaded, playing with canvas / 2. Restarting the canvas 30-40 times (i did not stop restarting so i do not know why the increase is not linear) / 3. Playing with canvas / 4. Closing the tab (reloading the page only frees a small fraction of what has been mobilized)
Few questions on SO yet asked how to solve those issues, but reproducing the solutions partially solves the problem. I have read two main things :
the canvas-related parts (nodes, variables, functions) have to be cleaned from the DOM (That is something Meteor does. But in this first part it stays relevant and yet is not enough to prevent the issues).
if requestAnimationFrame has been called, it needs to get assigned to a variable so cancelAnimationFrame(variable) can stop it. That indeed seems to prevent the frame rate drop. While memory stays high, at least the movements remain fluent.
With those solutions the memory problem still happens.
Here is an example : http://codepen.io/Astrak/pen/RNYLxd
2. In MeteorJS : i cannot get this partial solution work.
Here is what i wrote in my app, with id=requestAnimationFrame(myAnimation) declared globaly :
Template.myTemplate.destroyed=function(){
cancelAnimationFrame(id);
document.body.removeChild(document.querySelector('canvas'));//useful in Meteor ?
};
Despite those instructions, my animation gets slow much quicker with MeteorJS than in the previous example : it becomes unusable after 3-4 page change. And same memory problem.
Thanks for every comment and answer and happy coding :)
Related questions :
Performance drop on multiple restart of scene from threejs
Performance drops when trying to reset whole scene with Three.js
How do we handle webgl context lost event in Three.js
Pause, resume and restart Canvas animations with JS
How can I restart my function?
JavaScript restart canvas script
For memory problem, I'd recommend Chrome's javascript profiler - you can compare snapshots before and after canvas is reloaded and see which objects are not freed from memory.
Problem usually comes from event handlers and/or using closures. If you, for example, hook a function to window object's onresize event, all objects referenced in this function will stay in memory as long as window exists. So always remove event handlers from global objects if you want to refresh page content without actually refreshing the browser session.
Similar with closures. They will create link between function's scope and referenced variables preventing GC to collect them. Check this https://www.meteor.com/blog/2013/08/13/an-interesting-kind-of-javascript-memory-leak

Animation of features in OpenLayers3

I was curious about the possibilities of animating features in OpenLayers3.
I'm very aware of the examples presented here
http://openlayers.org/en/v3.0.0/examples/animation.html and here
https://gis.stackexchange.com/questions/26546/openlayers-animation-examples-and-algorithms
However, the official examples for OL3 don't quite fit my needs.
Let's assume that I have a layer (geojson for instance) that has a "time" column with lots and lots of time values.
I'd like to implement something like a slider that adds/removes features (or changes their style) depending on the user's actions.
The thing is that there are some APIs that might be able to do that, but they seem to be outdated (code examples were still working with ol2).
Do you have any suggestions on how to build a simple animation slider with OL3?
EDIT: It doesn't necessarily have to be proper animation. A possibility that came to my mind is changing the style of a layer whenever the slider is moved. Still no clue though on how to realise that.
This image illustrates what I have in mind:
EDIT: My current approach is to have a slider, that triggers code everytime it is moved. I somehow try do change the layer style dynamically, but I still haven't gotten a viable result.
Ok. I've come up with a solution myself. It's not really a full-fledged animation, but it works for me.
Basically what I do is that I load a wfs-layer to my map.
Now, here is the trick:
When I do that, I simply sort the time-values of the features one by one and add every feature with the time value of 1 to one layer, every feature with a time value of 2 to another and so and so forth.
This basically does the trick. The rest is simple.
Next step is that I implement a slider that ranges from 1 (the lowest time value) to whatever the highest time value is. Everytime the slider is moved it triggers an event that finds out to which time value the slider is set to and then adds/removes the corresponding layers.
So, if the slider is set to 5. It will add every layer from 1 to 5 to the map and remove every other layer. Again, this is not really an animation, but it does work in my case.
If anyone comes up with another possible solution, please post it here. I'd appreciate it.
(Btw, this is what my solution looks like in action:)
EDIT: I can now also confirm that it is possible to build "proper" animations with this approach. I simply built a js-function that includes multiple "setTimeout"s to time when a layer is added and added a play button that triggers this function. This amounts to an animation that visualises the growth from t=1 to tmax.

Animating multiple DIV-Elements with JS and the DOM results in a low Framerate

Preface
I just started programming with javascript and I am currently working on this hobby web-site project of mine. The site is supposed to display pages filled with product images than can be "panned" to either the left or right. Each "page" containing about 24 medium sized pictures, one page almost completely fills out an entire screen. When the user chooses to look at the next page he needs to click'n'drag to the left (for example) to let a new page (dynamically loaded through an AJAX script) slides into the view.
The Issue
This requires for my javascript to "slide" two of these mentioned pages synchronously by the width of a screen. This results in a really low framerate. Firefox and Opera lag a bit, Chrome has it especially bad: 1 frame of animation takes approx. 100 milliseconds, thus making the animation look very "laggy".
I do not use jQuery, nor do I want to use it or any other library to "do the work for me". At least not until I know for sure that what I am trying to do can not be done with a couple of lines of self-written code.
So far I have figured out that the specific way I manipulate the DOM is causing the performance-drop. The routine looks like this:
function slide() {
this.t = new Date().getTime() - this.msBase;
if( this.t > this.msDura ) {
this.callB.call(this.ref,this.nFrames);
return false;
}
//calculating the displacement of both elements
this.pxProg = this.tRatio * this.t;
this.eA.style.left = ( this.pxBaseA + this.pxProg ) + 'px';
this.eB.style.left = (this.pxBaseB + this.pxProg) + 'px';
if ( bRequestAnimationStatus )
requestAnimationFrame( slide.bind(this) );
else
window.setTimeout( slide.bind(this), 16 );
this.nFrames++;
}
//starting an animation
slide.call({
eA: theMiddlePage,
eB: neighboorPage,
callB: theCallback,
msBase: new Date().getTime(),
msDura: 400,
tRatio: ((0-pxScreenWidth)/400),
nFrames: 0,
ref: myObject,
pxBaseA: theMiddlePage.offsetLeft,
pxBaseB: neighboorPage.offsetLeft
});
Question
I noticed that when I let the AJAX script load less images into each page, the animation becomes much faster. The separate images seem to create more overhead than I have expected.
Is there another way to do this?
THE JAVASCRIPT SOLUTION
OK, there are two possible things for you to try to speed this up.
First of all, when you modify the style of an element, you force the browser to rerender the page. This is called a repaint. Certain changes also force a recalculation of the page's geometry. This is called a reflow. A reflow always triggers a repaint immediately after it. I think why you're experiencing worse performance with more elements is that each update to each one triggers at least a repaint. What is normally recommended in the case of modifying multiple styles on a single element is to either do them all at once by adding or removing a class, or hide the element, do your manipulations, and then show it, which means only two repaints (and possibly reflows).
It appears that in this particular case, you're probably already doing just fine, as you're only manipulating each item once per iteration.
Second of all, requestAnimationFrame() is good for doing animations on a canvas element, but seems to have somewhat dodgy performance on DOM elements. Open your page in Chrome's profiler to see exactly where it hangs up. Try JUST using setTimeout() to see if that ends up being the case. Again, the profiler will tell you where the hang-ups are. requestAnimationFrame() should be better, but validate this. I've had it backfire on me, before.
THE REAL SOLUTION
Don't do this in JavaScript, if you can at all avoid it. Use CSS transitions and translation to do the animation with a JavaScript function registered as the onTransitionEnd event handler for each animated element. Letting the browser do this stuff natively is almost always faster than any JS code anyone can write.
The only catch is that CSS3 animations are only supported by the newer browers. For your own edification, do it this way. For real, practical applications, delegate to a library. A good library will do it natively, if possible, and fall back to the best way of doing it in JS for the older browsers.
Good link to read regarding this stuff: http://www.html5rocks.com/en/tutorials/speed/html5/

jQuery: Dequeue Specific Animations

I've got some borders that animate around thumbnails in on mouseenter and out on mouseleave. Say a user moves their mouse between two repeatedly, quickly enough that the animation doesn't have time to finish between before the user moves on. The result is that, even if the mouse isn't moving, the border bounces back and forth between the two images they switched between until all the queued animations finish, which can take a while. To prevent this, I've added a .dequeue() before the .animate(). This works well, except that I may have some other animations running. I don't want to stop/dequeue these.
Is there a way to selectively dequeue animations, excluding some? The ones I want to exclude are scroll animations, also triggered on mouseenter.
Are you looking for something like this?
EDIT:
Ah I see, here is the closest solution that i can think of.
There's no built-in way to do this, I don't think you'll find an approach that doesn't involve re-writing a fair portion of the animation engine. The animations take an object when queued. It loops though all properties in the object and determines the start value and end value. To get the value at the step of the animation (depending on your easing, we'll use linear as an example here), it multiplies that difference by the percentage along the animation is.
It's all handled as a group of properties, you can't really split them off and stop the animation of some and not others...it just isn't built to be handled that way. If it were, it's be a huge performance penalty to handle them separately (think about how many times this code runs)...so for such a rare case (your needs here), the library is going to choose the high-performance route that fits the other 99% of cases.

Categories