JavaScript Css Loaders with Rebound and Canvas
JavaScript Css Loaders Tutorial A tutorial on how to create a loading spinner (JavaScript Css Loaders) The code presented in this tutorial is written in ES6 and compiled to ES5 using Babel, you’ll find the full gulp setup in the repository.
Creating the Spinner Firstly, we need to create the logic of the spinner; let’s start by thinking of it as a simple triangle:
Inscribed triangle construction with Canvas The idea is to draw a basePolygon and then draw a child so that it is inscribed in the original triangle. The Polygon.js method to compute the base points is the following: /** * Get the points of any regular polygon based on * the number of sides and radius. */ _getRegularPolygonPoints() { let points = []; let i = 0; while (i < this._sides) { // Note that sin and cos are inverted in order to draw // polygon pointing down. let x = -this._radius * Math.sin(i * 2 * Math.PI / this._sides); let y = this._radius * Math.cos(i * 2 * Math.PI / this._sides); points.push({x, y}); i++; } }
return points;
To draw the child we simply need to calculate where the vertex will be on each side at a given progress. Weâ&#x20AC;&#x2122;ll achieve this by using linear interpolation between the points of the basePolygon.
Linear interpolation for a given progress
The Polygon.js methods to compute the inscribed points looks as follows: /** * Get the inscribed polygon points by calling `getInterpolatedPoint` * for the points (start, end) of each side. */ _getInscribedPoints(points, progress) { let inscribedPoints = []; points.forEach((item, i) => { let start = item; let end = points[i + 1]; if (!end) { end = points[0]; } let point = this._getInterpolatedPoint(start, end, progress); inscribedPoints.push(point); }); return inscribedPoints; } /** * Get interpolated point using linear interpolation * on x and y axis. */
_getInterpolatedPoint(start, end, progress) { let Ax = start.x; let Ay = start.y; let Bx = end.x; let By = end.y; // Linear interpolation formula: // point = start + (end - start) * progress; let Cx = Ax + (Bx - Ax) * progress; let Cy = Ay + (By - Ay) * progress; return { };
x: Cx, y: Cy
}
Once done, we can simply use the methods provided by Polygon.js to repeat the process for each child until a certain depth is reached. /** * Update children points array. */ _getUpdatedChildren(progress) { let children = []; for (let i = 0; i < this._depth; i++) { // Get basePolygon points on first lap // then get previous child points. let points = children[i - 1] || this.points; let inscribedPoints = this._getInscribedPoints(points, progress); } }
children.push(inscribedPoints); return children; /** * Render children, first update children array, * then loop and draw each child. */ renderChildren(context, progress) { let children = this._getUpdatedChildren(progress); // child = array of points at a certain progress over the parent sides.
children.forEach((points, i) => { // Draw child. context.beginPath(); points.forEach((point) => context.lineTo(point.x, point.y)); context.closePath(); // Set colors. let strokeColor = this._colors.stroke; let childColor = this._colors.child; if (strokeColor) { context.strokeStyle = strokeColor; context.stroke(); } if (childColor) { let rgb = rebound.util.hexToRGB(childColor); let alphaUnit = 1 / children.length; let alpha = alphaUnit + (alphaUnit * i); let rgba = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`; context.fillStyle = rgba; context.fill(); }
});
}
At this point we have the Spinner system and we can start thinking about the animation. Note that we can plug any animation engine into it, essentially from now on we just need to think about how to make the progress run from 0 to 1. In this case weâ&#x20AC;&#x2122;ll use Rebound, letâ&#x20AC;&#x2122;s see what it is and how to use it. [Download]