Playing with some css loading animations, I’ve noticed that they were absolutely awesome! They were smooth, vectorial and mobile friendly. So I thought about the classic loading animation we all know, the rotating arrows.
The whole animation is pretty easy and made in two different steps:
– draw the arrow
– rotate it with a line of CSS3
So the most annoying part: drawing the arrow.
We (me and Lorenzo), divided it in these steps (assuming our arrowhead is an equilateral triangle by the length of X ):
The code is well commented, so if you want to skip this part just look at the code.
– draw an arc (which is the body)
– POINT A: at the end of the arc (point E ) find the point at X/2 distance on the perpendicular of the tangent of the point E, and draw a line between E and A.
– POINT B: then (the most horrific part) find the 2nd point of the arrowhead (look at the code) and draw the line between A and B.
– POINT C: do the same as the 2nd step, but in the other direction, and draw the line between B and C.
– draw the line between C and E.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
//This little script will draw two curved arrows into a canvas, the CSS3 will make it rotating. //It's very verbose because of learning purpose. Feel free to share it! //Author: Edoardo Odorico and some help from Baldarn (2013) - Licensed Under Creative Commons CC-BY-SA //let's define some variables for stylish stuff: var radius = 50; var arrowStrength = 18; var triangleSide = 20; var distanceArrows = 0.3; //this is the distance ( n * pi) between the arrows, do not exagerate var colorBody = '#313131'; var colorTriangle = '#000000'; //now some variables for canvas and math var canvas = document.getElementById('c'); var context = canvas.getContext('2d'); var x = canvas.width / 2; //the center on X axis var y = canvas.height / 2; //the center on Y axis var pi = Math.PI; //and let's draw the arrows! drawArrow( distanceArrows, arrowStrength ); function drawArrow(distanceArrows, arrowStrength){ //From here I will call two functions, for body and for triangle, twice. //But first of all let's calculate the angle of the arc (for arrow body) var lengthArrow = 1 - distanceArrows; var startAngle = 0; var endAngle = lengthArrow ; //draw it! drawArrowBody( startAngle * pi, endAngle * pi, arrowStrength ); //and now draw the triangle: drawTriangle( endAngle * pi ); //math for the other arrow and... startAngle = endAngle + distanceArrows; endAngle = startAngle + lengthArrow ; //...draw them! drawArrowBody( startAngle * pi, endAngle * pi, arrowStrength ); drawTriangle( endAngle * pi); } function drawArrowBody( startAngle, endAngle, arrowStrength ){ //In this function we draw the body of the arrow, which is just an arc var counterClockwise = false; context.beginPath(); //draw it! context.arc( x, y, radius, startAngle, endAngle, counterClockwise ); //stroke it! context.lineWidth = arrowStrength; context.strokeStyle = colorBody; context.stroke(); context.closePath(); } function drawTriangle(endAngle){ //The bloody part: draw the triangle. //A lot of old trigos tricks: //First the center of the triangle base (where we start to draw the triangle) var canterBaseArrowX = x + radius * Math.cos( endAngle ); var canterBaseArrowY = y + radius * Math.sin( endAngle ); context.beginPath(); //We move to the center of the base context.moveTo( canterBaseArrowX, canterBaseArrowY ); //Let's calculate the first point, easy! var ax = canterBaseArrowX + (triangleSide / 2 ) * Math.cos( endAngle ); var ay = canterBaseArrowY + (triangleSide / 2 ) * Math.sin( endAngle ); context.lineTo ( ax, ay ); //Now time to get mad: the farest triangle point from the arrow body var bx = canterBaseArrowX + ( Math.sqrt( 3 ) / 2 ) * triangleSide * ( Math.sin( -endAngle )); var by = canterBaseArrowY + ( Math.sqrt( 3 ) / 2 ) * triangleSide * ( Math.cos( -endAngle )); context.lineTo(bx,by); //Easy , like the a point var cx = canterBaseArrowX - ( triangleSide / 2 ) * Math.cos( endAngle ); var cy = canterBaseArrowY - ( triangleSide / 2 ) * Math.sin( endAngle ); context.lineTo( cx,cy ); //and back to the origin, the center of the triangle base. context.lineTo( canterBaseArrowX, canterBaseArrowY ); context.lineWidth = arrowStrength; //Stroke it with color! context.strokeStyle = colorTriangle; context.stroke(); context.closePath(); } |
Time to make the whole thing rotate with a CSS3 animation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#c{ height:100%; width:100%; position:relative; -webkit-animation: rotate-left 2s linear infinite; } #loadingAnimation{ position:relative; height:100px; width:200px; } @-webkit-keyframes rotate-left { /*let's do the magic: rotate!*/ from { -webkit-transform: rotate(0deg);} to {-webkit-transform: rotate(360deg);} } |
obviously with some html :
1 |
<div id="loadingAnimation"><canvas id="c"></canvas></div> |
and then the demo:
Cool man, thanks for this !