How to animate using requestAnimationFrame? - javascript

I am trying to use requestAnimationFrame to animate my canvas when I click on + and - buttons to zoom in and zoom out like the Google Maps does (When you click on the + button to zoom in, you see a slight transition or a delay). Unlike the traditional canvas implementations, I have a pretty complicated structure in the application.
When the button is clicked, zoomin() function inside a service is called where the values are calculated and then the resultant value is emitted which is captured by a different component A which in turn calls a different class method redraw() which redraws the canvas.
In every example I saw, the images are being animated by manipulating the pixel values with time and the draw() method is available right there. But could anyone tell me where I should handle this and is there any alternative? And also how could I animate like the google maps does in JavaScript?
Could anyone guide me?
Thank you.

The demos that you have seen are right. requestAnimationFrame is a means and not an end. You use it to make your application more smooth and performant by limiting how often a method can be called, not just for the sake of using it to draw because that will not help.
If you want to use requestAnimationFrame for throttling (ie doing a redraw update every 1/60 of a second instead of whenever zoomin is called), you will have to update your logic and indeed store and update the zoom values in the background in a data service somewhere. The requestAnimationFrame loop should indeed have access to and call redraw so it is called every 1/60 of a second instead of whenever something updates. Redraw should have access to all data needed to draw the map (like the current zoom level).
The only alternative is NOT using requestAnimationFrame and doing the debouncing yourself when receiving mousewheel events to prevent to much draws. It sounds like your application could benefit from a more simple structure that would allow the use of requestAnimationFrame.
For the animation part, I would ask a separate question as that is a whole other topic.

Related

Change layer z-index in leaflet

I'm using leaflet to trace underground pipes which I create using the polyline methods.
Since the pipes/lines can sometimes overlap I need to be able to highlight the selected line which requires switching the z-index of the line.
Now it seems that leaflet does offer a setZIndex method, but it's not available for individual layers - so I can change it over an entire featureGroup, but that is less helfpul - and making every line into its own separate featureGroup feels like an overkill.
Any suggestions?
You could create another layer with a superior z-index that would be empty at start. When the mouse is going over a feature, copy the feature into that layer. When the mouse is going out, just remove it from the layer.
It might be a little bit cpu demanding, so I suggest you to debounce the mouseover function in order to make the mouse to wait 1-2 seconds over a feature before copying it into the top layer.
As IvanSanchez noted in a comment, the correct answer seems to be a method called bringToFront.

How to separate canvas update logic from rAF drawing updates

I'm working on my second big canvas project (a game) and are really trying to optimize everything.
I have my mouse and keyboard listeners set up so they change the state of my canvas layers but all drawing is done through my rAF call. This works well.
However, I'd like to do a similar thing with the rest of my game. Could I add an event listener or somehow update all my states/variables after each rAF call completes drawing?
For example, if something must move five pixels left I currently do the subtraction then draw. I would like to be able to do the subtraction after each frame outside the rAF and then inside of it just draw, draw, draw. No calculations.
Thanks!
Combine both. Save variables based on events and draw then with rAF.
see the link below. (the 2 sec loop should be your rAF)
Canvas animation frame rendering: Infinite Loop vs. triggering on mousemover()
(not my best code work)

Animate line in Mapbox.js

I need to animate a curve from one point to another using Mapbox.js.
I looked through the official examples and I saw that simply drawing the line is very easy using Arc.js.
So I thought, is it possible to export points of the curve that is made with Arc.js and use them to animate a line using Mapbox.js?
Or only possible way to animate lines is coming up with formula?
Just like in movies, animation is simply a series of still images: you would take the arc generated by Arc.js, make 'frames' of sub-sections of it, and call .addData or .setGeoJSON() repeatedly, depending on whether you're using L.geoJson or L.mapbox.featureLayer. You would do this on a setInterval or setTimeout or requestAnimationFrame in order to run the calls across time.

Why there is no method draw() in KineticJS documentation?

I've spent hours googling about Kinetic.Layer.draw() method. All that I've found is use-cases - no documentation about how, when and why to use it. Maybe it's deprecated already?
These are primary links which I use while learning and playing with this wonderful framework:
http://kineticjs.com/docs/index.html
http://www.html5canvastutorials.com/kineticjs/html5-canvas-events-tutorials-introduction-with-kineticjs/
It will be really helpful if somebody explains to me such misunderstanding.
Actually draw() and drawHit() are in the docs, but they are poorly documented:
http://kineticjs.com/docs/Kinetic.Stage.html#draw
draw()
draw layer scene graphs
http://kineticjs.com/docs/Kinetic.Stage.html#drawHit
drawHit()
draw layer hit graphs
Surprisingly I was unable to find the 3rd and last draw method: drawScene() in the Kinetic Docs. Also to my surprise, these 3 functions were not found to be extended from the parent class of Kinetic.Stage: Kinetic.Container
Anyways, I think this SO question explains the differences of the methods perfectly: What is the difference between KineticJS draw methods?
And definitely, there's no avoiding using these functions, you'll need to use one of them eventually unless your canvas/stage is static during your entire application. (*There may be an exception, see below)
To answer your questions:
How:
Call .draw() on any Kinetic.Container which includes: stage layer and group, or any Kinetic.Node which includes all the Kinetic.Shape
Examples:
stage.draw(); //Updates the scene renderer and hit graph for the stage
layer.drawHit(); //Updates the hit graph for layer
rect.drawScene(); //Updates the scene renderer for this Kinetic.Rect
Why:
I would think it's a performance thing to not have everything redraw on the Kinetic.Stage every single time there is a change. The use of the draw methods this way we can control programatically when we want the stage to be updated and rendered. As you might imagine, it is quite expensive to have to draw the stage all the time if we have say 10000 nodes in the scene.
When:
drawScene()
Anytime you need to update either the scene renderer (for example using .setFill() to change the fill of a shape)
drawHit()
To update the hit graph if you're binding events to your shapes so that the hit area for any events will be updated to the node changes.
draw()
Whenever you need to do both of the above.
Finally, perhaps an example/lab will be the most beneficial learning tool here, so I've prepared a JSFIDDLE for you to test out the differences. Follow the instructions and read my comments inside to get a better understanding of what's going on.
*NOTE: I mentioned above there was an exception to having to use the draw methods. That is because whenever you add a layer to the stage, everything in the layer is automatically drawn. There is small example of this described at the bottom of the fiddle.
The draw() method is basically used for drawing all the (visible) elements associated with the container you call the method on.
It is therefore not just limited to Kinetic.Layer but can also be used on Kinetic.Group, Kinetic.Container and so on...
When & Why to use:
Whenever you make any change to the canvas, you call the appropriate container's Draw() method. KineticJS does not refresh the canvas unless you explicitly say it using Draw(). In general, try to call the smallest container affected by your changes to make use of the efficient caching and redrawing only a part of canvas that was affected.
Take for instance:
You have 2 layers in your application. Layer1 is used for a static background and some other static items that need not be redrawn everytime.
And Layer2 contains your moving elements, or active objects. Then you can simply make a call to Layer2.draw()
To add the complexity, you have a group of objects, lets say all menu items. When a user presses any menu btn, its better to call menuGroup.draw() rather than the draw function of the its parent layer.

How to animate shapes on top of a leaflet map

I'm new to leaflet, looking for some advice.
I'd like to create an animation of a marker of some sort (for example, an html5 filled arc or shape) to replay GPS tracks on a map. I may want several animated markers and I want to stay flexible with the behavior and performance. Can anyone recommend a good way to go about creating this type of animation?
It looks like I could create a canvas layer (L.TileLayer.Canvas) and draw on it using a technique for linear animation (e.g. http://www.html5canvastutorials.com/advanced/html5-canvas-linear-motion-animation/), but I'm not yet sure if this works, or if I need to call redraw() and how the performance would be. Or I could try and make customer markers and move them by setting the lat/lon on them at some interval.
Has anyone come across this and can recommend a solution (above ideas or other)? Ideally as I change zoom levels, the animation will "scale" and have good performance. Thanks!
The RaphaelLayer plugin lets you create some pretty fancy animations:
http://dynmeth.github.com/RaphaelLayer/
yes there are a couple of ways to approach the problem...
drawing onto an interactive map is challenging because you need to recalculate your position on pan and zoom events; in addition to managing your actual animation.
This is an excellent example using the D3 library to manage the animation in a continuous loop, you may be a able to modify the code for multiple animations.
http://zevross.com/blog/2014/09/30/use-the-amazing-d3-library-to-animate-a-path-on-a-leaflet-map/
If you want a little more of the knuts and bolts of how the drawing process works then this project might be a better starting point
http://bl.ocks.org/Sumbera/11114288#L.CanvasOverlay.js
This grabs the overlay pane (a leaflet canvas which you can draw on) and... draws on it...
and you will absolutely want to check out this link which describes the drawing process for an interactive map

Categories

Resources