I built an animation using a JavaFX Canvas and it is having some performance problems. Before I go to the extensive trouble of rebuilding it relying on scene graph manipulations, I thought I’d check in here for opinions.
The animation has the following elements:
- a trail that has been traced by the mouse (via recording mouse positions at 60fps for several seconds)
- an animation of a cursor-like graphic traversing the trail
- a static background
- a graphic (several octaves of piano keys) that is used as a reference, overlaying a portion of the screen and subject to translation.
Both the trail and the piano key graphic will be subjected to X and Y scaling, independently.
My first instinct was to animate these with an AnimationTimer redrawing a Canvas, kind of like I might have done in the past with drawing on a Swing JPanel. But printing the “mouse trail” using GraphicsContext.strokePolyline method is killing the animation rate. (Actually, the rate is fine on my laptop Windows10, but there is a huge drop on Ubuntu 18.04 desktop.)
So I was thinking, maybe I should try using an actual Polyline node on a scene graph instead? (Assumption, the Polyline is somehow already “assembled” as opposed to the strokePolyline which relies on arrays of all the location data points.)
Am also thinking of other things where I don’t know if they are reasonable or not.
Maybe the Canvas performance would improve drastically if I put the drawing of the trail on a separate pane and didn’t update it except when the scaling events occur. (But having the speed go wonky when scaling happens would not be desirable.)
Maybe the trail should be “drawn” one time into a WritableImage instead of redrawing it every iteration? (I’d want to find some code to do this with some smoothing/anti-aliasing.) Then, handle the scaling as a ImageView node.
For the “cursor” object that traverses the trail, is it better to draw it on the GraphicsContext as a simple, small shape (8x8 pixels?) or to make it into a WritableImage and animate it as an ImageView? (I’m kind of thinking it could be neat if the cursor could “pulse” which might be easier to do with ImageView.)
I spend so much more time with sound than I do with graphics, and am really feeling the lack of experience. Any guidance or advice?
I posted something on WritableImages backed by NIO ByteBuffers (news a while back on improvements to JavaFX graphics) but I never had a call to actually try it out, and don’t know how to implement it.