{"id":5810,"date":"2013-03-03T23:41:27","date_gmt":"2013-03-04T03:41:27","guid":{"rendered":"http:\/\/www.useragentman.com\/blog\/?p=5810"},"modified":"2013-03-04T10:34:55","modified_gmt":"2013-03-04T14:34:55","slug":"animating-circular-paths-using-css3-transitions","status":"publish","type":"post","link":"http:\/\/www.useragentman.com\/blog\/2013\/03\/03\/animating-circular-paths-using-css3-transitions\/","title":{"rendered":"Animating Circular Paths Using CSS3 Animations."},"content":{"rendered":"<p>For the longest time I assumed that one couldn&#8217;t use <a href=\"http:\/\/css3.bradshawenterprises.com\/transitions\/\">CSS Transitions<\/a> or <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/CSS\/Tutorials\/Using_CSS_animations\">animations<\/a> to move DOM objects in anything but a straight path.  Sure, a developer could use multiple keyframes to create a list of straight paths to simulate a curve, but I didn&#8217;t think one could just define a curve with just two keyframes, or a simple CSS transition.  I was wrong:<\/p>\n<p><a id=\"example2\" href=\"#\" class=\"example\"  onclick=\"return false;\"><img decoding=\"async\" id=\"sun\" src=\"\/tests\/css3-animation-circle\/images\/sun.gif\" \/><img decoding=\"async\" class=\"saturn animated\" src=\"\/tests\/css3-animation-circle\/images\/saturn.png\" \/><\/a><\/p>\n<p><strong>The above example is animated using just two (2) CSS3 Animation keyframes!<\/strong>  Even though you could use <code>jQuery.animate()<\/code> or <code>requestAnimationFrame<\/code> to do this, it is better to use CSS3 instead of JavaScript &mdash; the resultant animation is always <strong>guaranteed to be smoother (especially on mobile devices) <em>plus<\/em> it can save on battery power.<\/strong>  This article will give the CSS recipe for implementing this in all CSS3 Animation enabled browsers with a walk-through on the math involved, as well as a fallback for older versions of IE that don&#8217;t support CSS3 Animations.<\/p>\n<h2>Give Me The CSS!<\/h3>\n<p>The only reason why the CSS is this long is because of the repetive vendor-prefix code:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n.saturn {\r\n    \r\n    \/* \r\n     * Make the initial position to be the center of the circle you want this\r\n     * object follow.\r\n     *\/\r\n    position: absolute;\r\n    left: 315px;\r\n    top: 143px;\r\n\r\n    \/*\r\n     * Sets up the animation duration, timing-function (or easing)\r\n     * and iteration-count. Ensure you use the appropriate vendor-specific \r\n     * prefixes as well as the official syntax for now. Remember, tools like \r\n     * CSS Please are your friends!\r\n     *\/\r\n    -webkit-animation: myOrbit 4s linear infinite; \/* Chrome, Safari 5 *\/\r\n       -moz-animation: myOrbit 4s linear infinite; \/* Firefox 5-15 *\/\r\n         -o-animation: myOrbit 4s linear infinite; \/* Opera 12+ *\/\r\n            animation: myOrbit 4s linear infinite; \/* Chrome, Firefox 16+, \r\n                                                      IE 10+, Safari 5 *\/\r\n    \r\n    \r\n    \r\n}\r\n\r\n\/*\r\n * Set up the keyframes to actually describe the begining and end states of \r\n * the animation.  The browser will interpolate all the frames between these \r\n * points.  Again, remember your vendor-specific prefixes for now!\r\n *\/\r\n@-webkit-keyframes myOrbit {\r\n    from { -webkit-transform: rotate(0deg) translateX(150px) rotate(0deg); }\r\n    to   { -webkit-transform: rotate(360deg) translateX(150px) rotate(-360deg); }\r\n}\r\n\r\n@-moz-keyframes myOrbit {\r\n    from { -moz-transform: rotate(0deg) translateX(150px) rotate(0deg); }\r\n    to   { -moz-transform: rotate(360deg) translateX(150px) rotate(-360deg); }\r\n}\r\n\r\n@-o-keyframes myOrbit {\r\n    from { -o-transform: rotate(0deg) translateX(150px) rotate(0deg); }\r\n    to   { -o-transform: rotate(360deg) translateX(150px) rotate(-360deg); }\r\n}\r\n\r\n@keyframes myOrbit {\r\n    from { transform: <span class=\"hilite\">rotate(0deg)<\/span> <span class=\"hilite2\">translateX(150px)<\/span> <span class=\"hilite\">rotate(0deg)<\/span>; }\r\n    to   { transform: <span class=\"hilite\">rotate(360deg)<\/span> <span class=\"hilite2\">translateX(150px)<\/span> <span class=\"hilite\">rotate(-360deg)<\/span>; }\r\n}\r\n\r\n<\/pre>\n<\/blockquote>\n<p>The really interesting bit is the keyframe code at the bottom.  The <code>translateX()<\/code> value must be equal to the radius of the circle (i.e. the diameter divided by two).  The <code>rotate()<\/code> functions in the <code>from<\/code> and <code>to<\/code> rules must be set to the start and end angles of the animation.  Note that there are <em>two rotate()<\/em> calls &mdash; <strong>the second has to be the negative of the first.<\/strong><\/p>\n<h2>How On <em>Earth<\/em> Does This Work?<\/h2>\n<p>To understand why this works, let me walk you step by step behind the math which generates the frame where Saturn has rotated 45 degrees around the sun.  From there we will show how this applies to the full animation.<\/p>\n<div class=\"steps\">\n<h3>Step 1: Position the Object to the Center<\/h3>\n<p>Position he object you want to move to the center of the circular path.  In the example above, the sun (which is just an animated GIF) is in the center, so let&#8217;s move Saturn to be right on top of it:<\/p>\n<p><a id=\"step1\" href=\"#\" class=\"example\"  onclick=\"return false;\"><img decoding=\"async\" id=\"sun\" src=\"\/tests\/css3-animation-circle\/images\/sun.gif\" \/><img decoding=\"async\" class=\"saturn\" src=\"\/tests\/css3-animation-circle\/images\/saturn.png\" \/><\/a><\/p>\n<blockquote class=\"code\">\n<pre>\r\n.saturn {\r\n    left: 315px;\r\n    position: absolute;\r\n    top: 143px;\r\n}\r\n<\/pre>\n<\/blockquote>\n<h3>Step 2: Use translateX() To Define the Radius of the Circle<\/h3>\n<p>Next we need to move the object to the edge of the circle.  For this example, let&#8217;s say the circle&#8217;s diameter is 300px.  We set CSS3 <code>transform<\/code> property to <code>transformX(150px)<\/code> (150px being half of 300px).<\/p>\n<div id=\"step2\" href=\"#\" class=\"example\"  onclick=\"return false;\"><img decoding=\"async\" id=\"sun\" src=\"\/tests\/css3-animation-circle\/images\/sun.gif\" \/><img decoding=\"async\" class=\"saturn\" src=\"\/tests\/css3-animation-circle\/images\/saturn.png\" \/><\/p>\n<div class=\"ruler\">\n<div class=\"label\">150px<\/div>\n<\/div>\n<\/div>\n<blockquote class=\"code\">\n<pre>\r\n.saturn {\r\n    left: 315px;\r\n    position: absolute;\r\n    top: 143px;\r\n\r\n    \/* Note: I have omitted the vendor prefix code for sake of brevity *\/\r\n    <span class=\"hilite\">transform: translateX(150px);<\/span>\r\n}\r\n<\/pre>\n<\/blockquote>\n<h3>Step 3: Insert A <code>rotate()<\/code> Or Two Into The Mix.<\/h3>\n<p>If we insert a <code>rotate()<\/code> into the <code>transform<\/code> property before the <code>translateX()<\/code>, we can use it to control the circular path.  To show this, let&#8217;s insert one of <code>45deg<\/code>:<\/p>\n<p><a id=\"step3a\" href=\"#\" class=\"example\"  onclick=\"return false;\"><img decoding=\"async\" id=\"sun\" src=\"\/tests\/css3-animation-circle\/images\/sun.gif\" \/><img decoding=\"async\" class=\"saturn\" src=\"\/tests\/css3-animation-circle\/images\/saturn.png\" \/><img decoding=\"async\" class=\"angle\"  src=\"\/tests\/css3-animation-circle\/images\/45degrees.png\" \/><\/a><\/p>\n<blockquote class=\"code\">\n<pre>\r\n.saturn {\r\n    left: 315px;\r\n    position: absolute;\r\n    top: 143px;\r\n\r\n    \/* Note: I have omitted the vendor prefix code for sake of brevity *\/\r\n    transform: <span class=\"hilite\">rotate(45deg)<\/span> translateX(150px);\r\n}\r\n<\/pre>\n<\/blockquote>\n<p>The problem is that in the animation above Saturn shouldn&#8217;t spin around on it&#8217;s axis.  So we must add a <code>rotate(-45deg)<\/code> <em>after<\/em> the <code>translateX()<\/code> to rotate Saturn back to its &#8220;upright&#8221; position:<\/p>\n<p><a id=\"step3b\" href=\"#\" class=\"example\"  onclick=\"return false;\"><img decoding=\"async\" id=\"sun\" src=\"\/tests\/css3-animation-circle\/images\/sun.gif\" \/><img decoding=\"async\" class=\"saturn\" src=\"\/tests\/css3-animation-circle\/images\/saturn.png\" \/><img decoding=\"async\" class=\"angle\"  src=\"\/tests\/css3-animation-circle\/images\/minus45degrees.png\" \/><\/a><\/p>\n<blockquote class=\"code\">\n<pre>\r\n.saturn {\r\n    left: 315px;\r\n    position: absolute;\r\n    top: 143px;\r\n\r\n    \/* Note: I have omitted the vendor prefix code for sake of brevity *\/\r\n    transform: rotate(45deg) translateX(150px) <span class=\"hilite\">rotate(-45deg)<\/span>;\r\n}\r\n<\/pre>\n<\/blockquote>\n<h3>Step 4: Apply The Animation Code<\/h3>\n<p>Now let&#8217;s apply the animation styles to finish our work.  We want to have saturn rotate around the sun in 2 seconds, so we add the appropriate CSS to define the speed, length and easing of our animation:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n#saturn {\r\n    left: 315px;\r\n    position: absolute;\r\n    top: 143px;\r\n\r\n    \/*\r\n     * CSS Please is your friend for ensuring cross browser syntax\r\n     *\/\r\n    -webkit-animation: orbit2 4s linear infinite; \/* Chrome, Safari 5 *\/\r\n       -moz-animation: orbit2 4s linear infinite; \/* Firefox 5-15 *\/\r\n         -o-animation: orbit2 4s linear infinite; \/* Opera 12+ *\/\r\n            animation: orbit2 4s linear infinite; \/* Chrome, Firefox 16+, \r\n                                                     IE 10+, Safari 5 *\/\r\n\t\r\n\t\r\n\t\r\n}\r\n<\/pre>\n<\/blockquote>\n<p>Then we add the keyframes to the CSS to tell the browser that the animation must rotate around the sun (i.e. from 0 to 360 degrees):<\/p>\n<blockquote class=\"code\">\n<pre>\r\n@-webkit-keyframes orbit2 {\r\n\tfrom { \t-webkit-transform: rotate(0deg) translateX(150px) rotate(0deg); }\r\n\tto   {  -webkit-transform: rotate(360deg) translateX(150px) rotate(-360deg); }\r\n}\r\n\r\n@-moz-keyframes orbit2 {\r\n\tfrom { \t-moz-transform: rotate(0deg) translateX(150px) rotate(0deg); }\r\n\tto   {  -moz-transform: rotate(360deg) translateX(150px) rotate(-360deg); }\r\n}\r\n\r\n@-o-keyframes orbit2 {\r\n\tfrom { \t-o-transform: rotate(0deg) translateX(150px) rotate(0deg); }\r\n\tto   {  -o-transform: rotate(360deg) translateX(150px) rotate(-360deg); }\r\n}\r\n\r\n@keyframes orbit2 {\r\n\tfrom { \ttransform: rotate(0deg) translateX(150px) rotate(0deg); }\r\n\tto   {  transform: rotate(360deg) translateX(150px) rotate(-360deg); }\r\n}\r\n<\/pre>\n<\/blockquote>\n<p>Et Voila!  We are done.  Pour yourself a martini &mdash; you deserve it!<\/p>\n<p><a href=\"https:\/\/www.useragentman.com\/tests\/css3-animation-circle\/transition-circle-keyframes.html\" class=\"exampleLink\">Take a look at a &#8220;clean-room&#8221; example of the above code in action<\/a> <\/p>\n<\/div>\n<h2>What About IE?<\/h2>\n<p>IE10 is the only flavour of Internet Explorer that supports CSS3 Animations.  Since IE7 and 8 are still being used in the wild, it would be nice to have some sort of fallback.  Using conditional comments, you could include an IE-only JavaScript that can do this for you, using jQuery.aniamte() or Paul Irish&#8217;s <code>requestAnimationFrame()<\/code> shim.  Since most devs are probably using jQuery anyway, the above &#8220;clean-room&#8221; example uses this code to do the animation in IE.  It does this by including the JS code for IE only:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n &lt;!DOCTYPE html&gt;\r\n&lt;html lang=\"en\"&gt;\r\n    &lt;head&gt;\r\n        &lt;title&gt;Example of Using CSS3 Animations and Circular Paths.&lt;\/title&gt;\r\n        &lt;meta charset=\"utf-8\" \/&gt;\r\n        &lt;!-- Always force latest IE rendering engine (even in intranet) &amp; Chrome Frame\r\n        Remove this if you use the .htaccess --&gt;\r\n        &lt;link rel=\"stylesheet\" href=\"https:\/\/www.useragentman.com\/shared\/css\/useragentmanExample.css\" \/&gt;\r\n        &lt;link rel=\"stylesheet\" href=\"css\/transition-circle-keyframes.css\" \/&gt;\r\n        \r\n<span class=\"hilite\">        &lt;!-- IE doesn't do CSS3 Animations, so let's put in some JS code to fix. --&gt;\r\n        \r\n        &lt;!--[if lte IE 9 ]&gt; \r\n        &lt;script type=\"text\/javascript\" src=\"\/shared\/js\/jquery-1.7.2.min.js\"&gt;&lt;\/script&gt;    \r\n        &lt;script type=\"text\/javascript\" src=\"js\/transition-circle-ie.js\"&gt;&lt;\/script&gt;    \r\n        &lt;![endif]--&gt;<\/span>\r\n    &lt;\/head&gt;    \r\n&lt;\/html&gt;\r\n<\/pre>\n<\/blockquote>\n<p>(Note the IE9-and-under conditional comments!) The <code>transition-circle-ie.js<\/code> contains this code which does the animation using jquery.animate():<\/p>\n<blockquote class=\"code\">\n<pre>\r\nvar ieRotate = new function () {\r\n    var me = this,\r\n        $saturn,\r\n        initialPosition,\r\n        radius = 150;\r\n    \r\n    \/* \r\n     * Initialize the animation here.\r\n     *\/\r\n    me.init = function () {\r\n        \r\n        \/\/ Caches the jQuery object for performance reasons.\r\n        $saturn = $('#saturn');\r\n        \r\n        \/\/ Stores the initial position of Saturn.  Used later when calculating\r\n        \/\/ the orbit animation.\r\n        initialPosition = {\r\n            x: parseInt($saturn.css('left')),\r\n            y: parseInt($saturn.css('top'))\r\n        };\r\n        \r\n        \/\/ starts the aniamtion.\r\n        rotateOnce();\r\n    }\r\n    \r\n    function rotateOnce() {\r\n        \r\n        \/*\r\n         * jQuery.animate() was designed to animate DOM objects by tweening\r\n         * numeric CSS property values.  This is fine when moving these DOM\r\n         * objects in straight lines, but not so good when trying to move an \r\n         * object in a circular path.  This will show you how you can work \r\n         * around this limitation.\r\n         *\/\r\n        \r\n        \/\/ Step 1: Set a dummy property to the angle of the initial position\r\n        \/\/         of Saturn.  We use text-indent, since it doesn't do anything\r\n        \/\/         on an image.\r\n        $saturn.css('text-indent', 0);\r\n        \r\n        \/\/ Step 2: We set up jQuery.animate() to do the animation by ....\r\n        $saturn.animate(\r\n            \/\/ ... first setting the final value of text-indent to be 2*\u03c0 \r\n            \/\/ radians, which is the same as 360 degrees ... \r\n            {\r\n                'text-indent': 2*Math.PI\r\n            }, {\r\n                \r\n                \/*\r\n                 * ... next we set up a step function that will generate the \r\n                 * frame when the angle stored in the text-indent property\r\n                 * at this particular part of the animation.  The formulas used\r\n                 * for the x and y coordinates are derived using the \r\n                 * polar equation of a circle.  For those that are unfamiliar\r\n                 * with polar equations, take a look at \r\n                 * http:\/\/sites.csn.edu\/istewart\/mathweb\/math127\/polar_equ\/polar_equ.htm\r\n                 *\/\r\n                step: function (now) {\r\n                    $saturn.css('left', initialPosition.x + radius * Math.cos(now))\r\n                           .css('top', initialPosition.y + radius * Math.sin(now))\r\n                },\r\n                \r\n                \/\/ This makes the animation last 4000milliseconds (= 4 seconds)\r\n                duration: 4000,\r\n                \r\n                \/\/ The easing property is analogeous to the CSS3 \r\n                \/\/ animation-timing-funciton\r\n                easing: 'linear',\r\n                \r\n                \/\/ Once the animation finishes, we call rotateOnce() again so\r\n                \/\/ that the animation is repeated.\r\n                complete: rotateOnce\r\n            }\r\n        );\r\n    }\r\n}\r\n\r\n$(document).ready(ieRotate.init);\r\n<\/pre>\n<\/blockquote>\n<p>Look at the comments for details on how the code works.  JavaScript uses <a href=\"http:\/\/en.wikipedia.org\/wiki\/Radian\">radians<\/a> instead of degrees when calculating sin() and cos() values &mdash; if you are not familar with radians, <a href=\"http:\/\/www.purplemath.com\">PurpleMath<\/a> has <a href=\"http:\/\/www.purplemath.com\/modules\/radians.htm\">an article that can help you<\/a>.  If you are not familiar with polar equations, <a href=\"http:\/\/sites.csn.edu\/istewart\/mathweb\/\">Dr. Ingrid Stewart<\/a> from the <a href=\"http:\/\/www.csn.edu\/\">College of Southern Nevada<\/a> has a great article called <a href=\"http:\/\/sites.csn.edu\/istewart\/mathweb\/math127\/polar_equ\/polar_equ.htm\">Polar Equarions and Their Graphs<\/a> which I think does a good job explaining how the step() function works above.<\/p>\n<p><a href=\"\/tests\/css3-animation-circle\/transition-circle-keyframes.html\" class=\"exampleLink\">Take a look at a &#8220;clean-room&#8221; example of the above code in action<\/a><\/p>\n<h2>Variations Of This Technique<\/h2>\n<p>How let&#8217;s say that instead of a planet, you wanted a spaceship circling around the sun instead.  Here&#8217;s a &#8220;classic&#8221; example:<\/p>\n<p><a id=\"example1\" href=\"#\" class=\"example\" onclick=\"return false;\"><img decoding=\"async\" id=\"sun\" src=\"\/tests\/css3-animation-circle\/images\/sun.gif\" \/><img decoding=\"async\" id=\"enterprise\" src=\"\/tests\/css3-animation-circle\/images\/enterprise.png\" \/><\/a><\/p>\n<p>Note that the ship is always facing the way it is flying.  You could do this with the same CSS as above, <strong>except you would remove the second <code>rotate()<\/code><\/strong> in the <code>transform<\/code> property:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n\/*\r\n * Vendor prefix code removed for sake of brevity.\r\n *\/\r\n#saturn {\r\n    left: 315px;\r\n    position: absolute;\r\n    top: 143px;\r\n    \r\n    \/* Set up the animation *\/\r\n    animation: orbit 20s linear infinite;\r\n}\r\n\r\n\/* Note that the second rotate in each of the transforms below has been removed *\/\r\n@keyframes orbit {\r\n<span class=\"hilite\">\tfrom { \ttransform: rotate(0deg) translateX(150px); }\r\n\tto   {  transform: rotate(360deg) translateX(150px); }<\/span>\r\n}\r\n<\/pre>\n<\/blockquote>\n<p>The JavaScript for IE would have to be changed &mdash; since the ship actually rotates, I used cssSandpaper to do the heavy-lifting here.<\/p>\n<blockquote class=\"code\">\n<pre>\r\n\r\n\/*\r\n * Replacement function for the one in the previous example where the\r\n * Enterprise always faces the way it is travelling.  \r\n *\/\r\nfunction rotateOnce() {\r\n    \r\n    $enterprise.css('text-indent', 0);\r\n    \r\n    \r\n    $enterprise.animate(\r\n        {\r\n            'text-indent': 2*Math.PI\r\n        }, {\r\n            step: function (now) {\r\n                \r\n                \/* \r\n                 * Unlike the other example, we need to have the object\r\n                 * (in this case the Enterprise) rotate while it is \r\n                 * travelling around the sun, so we use cssSandpaper to\r\n                 * do this work.\r\n                 *\/\r\n<span class=\"hilite\">                cssSandpaper.setTransform($enterprise[0], \r\n                    'rotate(' + now + 'rad) translateX(400px)');<\/span>\r\n            },\r\n            \r\n            duration: 20000,\r\n            \r\n            easing: 'linear',\r\n            \r\n            complete: rotateOnce\r\n        }\r\n    );\r\n}\r\n<\/pre>\n<\/blockquote>\n<p><a href=\"\/tests\/css3-animation-circle\/transition-circle-keyframes-trek.html\" class=\"exampleLink\">Take a look at a &#8220;clean room&#8221; version of the above example<\/a><\/p>\n<h2>Pseudo 3D?<\/h2>\n<p>We can also have <a href=\"\/tests\/css3-animation-circle\/transition-circle-keyframes-spiral.html\">a psuedo-3D animation of a planet plummeting into the sun<\/a>.  I leave it as an exercise to the reader to look at <a href=\"\/tests\/css3-animation-circle\/css\/transition-circle-keyframes-spiral.css\">the CSS<\/a> and <a href=\"\/tests\/css3-animation-circle\/js\/transition-circle-spiral-ie.js\">IE specific JavaScript<\/a> to figure out how it works (if you understand the above examples, you should be able to figure it out).<\/p>\n<h2>Future Research?<\/h2>\n<p>Right after I wrote this article, I came across <a href=\"http:\/\/smashingmagazine.com\/\">Smashing Magazine&#8217;s<\/a> excellent article <a href=\"http:\/\/coding.smashingmagazine.com\/2011\/09\/14\/the-guide-to-css-animation-principles-and-examples\/\">&#8220;The&#8221; Guide To CSS Animation: Principles and Examples<\/a> by <a href=\"http:\/\/www.2dforever.com\">Tom Waterhouse<\/a>.  It has some other excellent examples involving advanced CSS3 Animations, combining the animation of two nested DOM objects to produce a bouncing ball effect.  I am sure there are <em>way<\/em> more interesting techniques that can be done with them, and I will definitely the doing more research on CSS3 Animations in the future.  If you have any more such articles to share below, I (and, I am sure, others who are reading this article) would love to hear from you.<\/p>\n<h2>Acknowledgements<\/h2>\n<p>The assets I used in these demos came from these sources:<\/p>\n<ul>\n<li>Image of the starship from <a href=\"http:\/\/www.flickr.com\/photos\/quantumdriver\/856463394\/\">Flickr user drtel<\/a><\/li>\n<li><a href=\"http:\/\/sohowww.nascom.nasa.gov\/data\/realtime\/gif\/\">Animated GIF of the sun<\/a> was taken from the <a href=\"http:\/\/sohowww.nascom.nasa.gov\/\">The Solar &#038; Heliospheric Observatory&#8217;s website.<\/a><\/li>\n<li>The photos of <a href=\"http:\/\/commons.wikimedia.org\/wiki\/File:Jupiter.jpg\">Jupiter<\/a> and <a href=\"http:\/\/commons.wikimedia.org\/wiki\/File:Solar_system_scale_v.jpg\">Saturn<\/a> were taken from the <a href=\"http:\/\/commons.wikimedia.org\/wiki\/File:Jupiter.jpg\">Wikimedia Commons<\/a>.<\/li>\n<\/ul>\n<p>I would also like to apologize to <a href=\"http:\/\/wellcaffeinated.net\/\">Jasper Palfree<\/a>, who is going to cringe if and when he reads this article for two very good reasons:<\/p>\n<ol>\n<li>Placing planets so close to the sun would cause them to burn.  Do not try this at home.<\/li>\n<li>I must have been smoking something when I thought that a spaceship could be as big as a planet.<\/li>\n<\/ol>\n<p>Dammit Jim &mdash; I am a web developer, not an astrophysics major!<\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"\/tests\/css3-animation-circle\/images\/animation-teaser.jpg\" \/> For the longest time I assumed that one couldn\u2019t use CSS Transitions or animations to move DOM objects in anything but a straight path. Sure, a developer could use multiple keyframes to create a list of straight paths to simulate a curve, but I didn\u2019t think one could just define a curve with just two keyframes. I was wrong.  <strong>If  you are  coding for a modern web browser, then this is very doable!<\/strong>. This article will show you how it&#8217;s done in modern browsers, the math involved, and what to do with older versions of IE that don&#8217;t support CSS3 Animations.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[152,36,9,38,7,95,41,153],"tags":[],"class_list":["post-5810","post","type-post","status-publish","format-standard","hentry","category-animation-css3","category-animation","category-css","category-css3","category-javascript","category-math","category-transform","category-transition"],"_links":{"self":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/5810","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/comments?post=5810"}],"version-history":[{"count":94,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/5810\/revisions"}],"predecessor-version":[{"id":5906,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/5810\/revisions\/5906"}],"wp:attachment":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/media?parent=5810"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/categories?post=5810"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/tags?post=5810"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}