10-21-animate-along-arc.html 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Animate along an arc</title>
  6. <style>
  7. /* "housekeeping" to set the stage. */
  8. body {
  9. font-family: "Myriad Pro", Frutiger, "Lucida Grande", "Lucida Sans", "Lucida Sans Unicode", Verdana, sans-serif;
  10. background-color: #edf5f8;
  11. margin: 0;
  12. padding: 1em;
  13. }
  14. button {
  15. margin-top: 2em;
  16. cursor: pointer;
  17. border: 0;
  18. padding: .5em 1em;
  19. color: #fff;
  20. border-radius: .25em;
  21. outline: none;
  22. font-size: 1em;
  23. background-color: #173b6d;
  24. background-image: -webkit-linear-gradient(top, #1a4a8e, #173b6d);
  25. background-image: -moz-linear-gradient(top, #1a4a8e, #173b6d);
  26. background-image: -o-linear-gradient(top, #1a4a8e, #173b6d);
  27. background-image: linear-gradient(to bottom, #1a4a8e, #173b6d);
  28. box-shadow: 0 .25em 0 rgba(23, 59, 109, 0.3), inset 0 1px 0 rgba(0, 0, 0, 0.3);
  29. -webkit-transition: all 150ms ease-in;
  30. -moz-transition: all 150ms ease-in;
  31. -o-transition: all 150ms ease-in;
  32. transition: all 150ms ease-in;
  33. }
  34. button:active {
  35. box-shadow: 0 0 0 rgba(23, 59, 109, 0.3), inset 0 1px 0 rgba(0, 0, 0, 0.3);
  36. -webkit-transform: translateY(.25em);
  37. -moz-transform: translateY(.25em);
  38. -ms-transform: translateY(.25em);
  39. -o-transform: translateY(.25em);
  40. transform: translateY(.25em);
  41. }
  42. /* -- end housekeeping. -- */
  43. /**
  44. * Note: we've simplified the prefixed syntax down to just using
  45. * the webkit-prefixed version (which covers most browsers in use today)
  46. * apart from the standard unprefixed syntax.
  47. */
  48. /**
  49. * Make the container be a horizontal flexbox container, distributing the
  50. * items inside to space out all the way to the edges.
  51. */
  52. .upload {
  53. display: -webkit-box;
  54. display: -webkit-flex;
  55. display: -ms-flexbox;
  56. display: -moz-box;
  57. display: flex;
  58. display: -ms-flex;
  59. -webkit-box-pack: justify;
  60. -webkit-justify-content: space-between;
  61. -ms-flex-pack: justify;
  62. -moz-box-pack: justify;
  63. justify-content: space-between;
  64. height: 100px;
  65. width: 400px;
  66. margin-top: 100;
  67. background-color: rgba(0,0,0,0.1);
  68. padding: 1em;
  69. border-radius: .5em;
  70. -webkit-transform: translateZ(0);
  71. transform: translateZ(0);
  72. }
  73. /**
  74. * A class name common for all the icons, setting the background properties
  75. * and common sizing.
  76. */
  77. .icon {
  78. width: 4em;
  79. background: none no-repeat 50% 50%/contain;
  80. }
  81. .computer-icon {
  82. background-image: url(images/monitor.svg);
  83. }
  84. /**
  85. * Here's where we tie in the animation properties.
  86. */
  87. .file-icon {
  88. -webkit-animation: jump 2s ease-in-out infinite;
  89. animation: jump 2s ease-in-out infinite;
  90. /* equal to setting the following animation properties:
  91. animation-name: jump;
  92. animation-duration: 2s;
  93. animation-timing-function: ease-in-out;
  94. animation-iteration-count: infinite;
  95. */
  96. background-image: url(images/file.svg);
  97. }
  98. /**
  99. * We give the server icon positioning to be able to position it on top of
  100. * the file icon with z-index.
  101. */
  102. .server-icon {
  103. position: relative;
  104. z-index: 2;
  105. background-image: url(images/cloud_storage.svg);
  106. }
  107. /**
  108. * When the animation is paused, change the animation-play-state prop.
  109. */
  110. .file-icon.is-paused {
  111. -webkit-animation-play-state: paused;
  112. animation-play-state: paused;
  113. }
  114. /**
  115. * When the animation is stopped (at the start of an iteration), hide the icon
  116. * and set the play state to paused.
  117. */
  118. .file-icon.is-stopped {
  119. display: none;
  120. -webkit-animation-play-state: paused;
  121. animation-play-state: paused;
  122. }
  123. /**
  124. * When the animation is stopped, show a checkmark icon
  125. * after the server icon, using a pseudo-element.
  126. */
  127. .file-icon.is-stopped + .server-icon::after {
  128. content: '';
  129. display: block;
  130. width: 3em;
  131. height: 3em;
  132. background: url(images/checkmark.svg) 50% 50% no-repeat;
  133. background-size: contain;
  134. position: absolute;
  135. bottom: 1.5em;
  136. left: 60%;
  137. }
  138. /**
  139. * Keyframe definitions - note that prefixed versions have to have
  140. * a prefixed @keyframe block as well.
  141. */
  142. @-webkit-keyframes jump {
  143. from {
  144. -webkit-transform: rotate(0deg) translateX(-170px) rotate(0deg) scale(1);
  145. }
  146. 70%, 100% {
  147. -webkit-transform: rotate(175deg) translateX(-170px) rotate(-175deg) scale(.5);
  148. }
  149. }
  150. @keyframes jump {
  151. from {
  152. transform: rotate(0deg) translateX(-170px) rotate(0deg) scale(1);
  153. }
  154. 70%, 100% {
  155. transform: rotate(175deg) translateX(-170px) rotate(-175deg) scale(.5);
  156. }
  157. }
  158. </style>
  159. </head>
  160. <body>
  161. <h1>File uploading animation</h1>
  162. <div class="upload">
  163. <div class="icon computer-icon"></div>
  164. <div class="icon file-icon is-paused"></div>
  165. <div class="icon server-icon"></div>
  166. </div>
  167. <button type="button" class="button-pause">Play/pause animation</button>
  168. <button type="button" class="button-stop">Finish/restart animation</button>
  169. <script>
  170. /**
  171. * This script handles toggling of some states in the demo. It uses animation
  172. * events to trigger the adding and removing of class names to elements to
  173. * demonstrate controlling animations. If you're interested in how to use
  174. * CSS Animation events, read on.
  175. *
  176. * For the animation events, we need to add listeners for both the standardized
  177. * events as well as the prefixed versions. This is done via a helper
  178. * function, adding & removing the listeners for us.
  179. *
  180. * In this case, we want to listen to the event 'animationiteration',
  181. * which is fired when an iteration of an animation on an element is finished.
  182. * This means we have to listen for the various prefixed versions as well.
  183. * WebKit-based browsers call this event 'webkitAnimationIteration', IE calls
  184. * it 'MSAnimationIteration'. If you need to support older versions of Mozilla-
  185. * based browsers (e.g. Firefox), you need to use 'MozAnimationIteration' as
  186. * well, and older versions of Opera support 'oanimationiteration'.
  187. *
  188. */
  189. var icon = document.querySelector('.file-icon'), // The file icon element.
  190. pause = document.querySelector('.button-pause'), // play/pause button.
  191. stop = document.querySelector('.button-stop'), // stop/start button
  192. prefixes = ['webkit', 'MS', ""]; // List of prefixes to support.
  193. // Helper function to generate prefixed versions of the event handlers.
  194. function prefixedEvent(addOrRemove, prefixes, element, evt, callback) {
  195. var l = prefixes.length;
  196. // Loop over all the prefixes to support and run either
  197. // element.addEventListener or element.removeEventListener, based
  198. // on the value of the addOrRemove argument.
  199. for (var current=0; current<l; current++) {
  200. // set the event name to the lowercased standard version if no prefix.
  201. if (prefixes[current] === "") {
  202. evt = evt.toLowerCase();
  203. }
  204. element[addOrRemove + 'EventListener'](prefixes[current]+evt, callback, false);
  205. }
  206. }
  207. // Toggle stop/start
  208. function toggleAnimation() {
  209. // If we are starting, remove the listener to stop at the end of
  210. // the current iteration.
  211. if (icon.classList.contains('is-stopped')) {
  212. // We need 3 listeners to cover the most popular browsers today:
  213. prefixedEvent('remove', prefixes, icon, 'AnimationIteration', stopAnimation);
  214. icon.classList.remove('is-stopped');
  215. } else {
  216. // If we are stopping, wait for the iteration to finish.
  217. waitToStop();
  218. }
  219. }
  220. // Function to toggle play/pause state.
  221. function pauseAnimation() {
  222. icon.classList.toggle('is-paused');
  223. }
  224. // Function to stop the animation.
  225. function stopAnimation() {
  226. icon.classList.add('is-stopped');
  227. }
  228. // Function to add a listener for the animationiteration event.
  229. function waitToStop() {
  230. prefixedEvent('add', prefixes, icon, 'AnimationIteration', stopAnimation);
  231. }
  232. // Finally, add event listeners for the buttons.
  233. pause.addEventListener('click', pauseAnimation, false);
  234. stop.addEventListener('click', toggleAnimation, false);
  235. </script>
  236. </body>
  237. </html>