Home >Web Front-end >JS Tutorial >Drawing animations in ScheduleJS
ScheduleJS uses the HTML Canvas rendering engine to draw the grid, activities, additional layers and links. This article explains how to design a simple ScheduleJS rendering animation using the HTML Canvas API
Have you ever been using the Canvas technology before? The canvas element is an HTML container used to draw programmatically using JavaScript at a surprisingly low cost for the browser.
The most significant feature of the canvas element is that its possibilities are endless in terms of design and interactions. The only limit to what’s on the screen is our imagination.
If you want to wrap your head around the canvas element, you can compare it to a blank drawing paper.
According to the MDN web documentation:
MDN: The Canvas API provides a means for drawing graphics via JavaScript and the HTML canvas element. Among other things, it can be used for animation, game graphics, data visualization, photo manipulation, and real-time video processing.
The Canvas API largely focuses on 2D graphics. The WebGL API, which also uses the canvas element, draws hardware-accelerated 2D and 3D graphics.
Once you draw your activities on the canvas, the only way to get it to change is to clean it up and start drawing again.
Under the hood, ScheduleJS implements multiple tools to handle this behavior in the context of a scheduling application. These APIs are sometimes exposed to the developer and sometimes they work silently to let the developer focus on the core features of the application, like the following:
The most significant item for the developer in this architecture is the ScheduleJS Renderer API. Renderers use overridable functions allowing the developer to create his or her unique way of drawing specific parts of the application:
Although this may seem complicated to some people, it is a workflow that developers will get used to quickly. The flexibility of the Renderer architecture and its well-thought implementation allows endless design and interaction scenarios.
To animate your Canvas, you have to break down your animation in frames and tell the renderer how to draw each frame. The main ingredient required to create a simple linear animation is the time at which the animation started. If we want to animate every activity on its own, a good place to store this information is the activity data structure.
// A simple activity class storing the animation start date as a timestamp export class MyActivity extends MutableActivityBase { animationStart: number = undefined; }
Let’s create a simple animated renderer to draw every frame based on animation progression. This simple width animation will animate our activity on creation (from 0% width to full-width).
// Create our activity renderer for our simple animation export class MyActivityRenderer extends ActivityBarRenderer<MyActivity, Row> { // Our animation takes 250ms private _animationDurationMs: number = 250; // Override the drawActivity method of the ActivityBarRenderer protected drawActivity(activityRef: ActivityRef<Action>, position: ViewPosition, ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, selected: boolean, hover: boolean, highlighted: boolean, pressed: boolean): ActivityBounds { // What time is it? :) const now = Date.now(); // Access your activity in the renderer const activity = activityRef.getActivity(); // Set animationStart timestamp if (activity.animationStart === undefined) { activity.animationStart = now; } // The animationTimer tells us the current frame const animationTimer = now - activity.animationStart; // Calculate the sequence: 0 = animation starts, 1 = animation ends const sequence = animationTimer / this._newActionAnimationDurationMs; // Let's play with the width: starts at 0%, ends at 100% w *= sequence > 1 ? 1 : sequence; // Note: Calling directly graphics.redraw() will cause an infinite loop requestAnimationFrame(() => { // Force a redraw on every animation frame this.getGraphics().redraw(); // Our custom drawing method this.drawMyActivity(activity, x, y, w, h, selected, hover, highlighted, pressed); }); return new ActivityBounds(activityRef, x, y, w, h); }
This example focuses on the code required to run the animation. As you can see, we created a ratio (from 0 to 1) describing the duration of our animation and we simply multiply the width by this ratio. As a result, the activity width will expand in a smooth 250ms animation (see below).
Much more can be done using the same principle as every drawing layer in ScheduleJS uses the renderer architecture and implements similar drawing methods. On top of this, the same result can be achieved using many different approaches. Anyways, no matter what graphics animation you want to build, the ScheduleJS renderers will let you design and customize the user experience at a pixel level.
Feel free to contact us if you have any UX/UI challenges or ideas for ScheduleJS!
The above is the detailed content of Drawing animations in ScheduleJS. For more information, please follow other related articles on the PHP Chinese website!