_animation_data.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. # Javascript template for HTMLWriter
  2. JS_INCLUDE = """
  3. <link rel="stylesheet"
  4. href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/
  5. css/font-awesome.min.css">
  6. <script language="javascript">
  7. function isInternetExplorer() {
  8. ua = navigator.userAgent;
  9. /* MSIE used to detect old browsers and Trident used to newer ones*/
  10. return ua.indexOf("MSIE ") > -1 || ua.indexOf("Trident/") > -1;
  11. }
  12. /* Define the Animation class */
  13. function Animation(frames, img_id, slider_id, interval, loop_select_id){
  14. this.img_id = img_id;
  15. this.slider_id = slider_id;
  16. this.loop_select_id = loop_select_id;
  17. this.interval = interval;
  18. this.current_frame = 0;
  19. this.direction = 0;
  20. this.timer = null;
  21. this.frames = new Array(frames.length);
  22. for (var i=0; i<frames.length; i++)
  23. {
  24. this.frames[i] = new Image();
  25. this.frames[i].src = frames[i];
  26. }
  27. var slider = document.getElementById(this.slider_id);
  28. slider.max = this.frames.length - 1;
  29. if (isInternetExplorer()) {
  30. // switch from oninput to onchange because IE <= 11 does not conform
  31. // with W3C specification. It ignores oninput and onchange behaves
  32. // like oninput. In contrast, Mircosoft Edge behaves correctly.
  33. slider.setAttribute('onchange', slider.getAttribute('oninput'));
  34. slider.setAttribute('oninput', null);
  35. }
  36. this.set_frame(this.current_frame);
  37. }
  38. Animation.prototype.get_loop_state = function(){
  39. var button_group = document[this.loop_select_id].state;
  40. for (var i = 0; i < button_group.length; i++) {
  41. var button = button_group[i];
  42. if (button.checked) {
  43. return button.value;
  44. }
  45. }
  46. return undefined;
  47. }
  48. Animation.prototype.set_frame = function(frame){
  49. this.current_frame = frame;
  50. document.getElementById(this.img_id).src =
  51. this.frames[this.current_frame].src;
  52. document.getElementById(this.slider_id).value = this.current_frame;
  53. }
  54. Animation.prototype.next_frame = function()
  55. {
  56. this.set_frame(Math.min(this.frames.length - 1, this.current_frame + 1));
  57. }
  58. Animation.prototype.previous_frame = function()
  59. {
  60. this.set_frame(Math.max(0, this.current_frame - 1));
  61. }
  62. Animation.prototype.first_frame = function()
  63. {
  64. this.set_frame(0);
  65. }
  66. Animation.prototype.last_frame = function()
  67. {
  68. this.set_frame(this.frames.length - 1);
  69. }
  70. Animation.prototype.slower = function()
  71. {
  72. this.interval /= 0.7;
  73. if(this.direction > 0){this.play_animation();}
  74. else if(this.direction < 0){this.reverse_animation();}
  75. }
  76. Animation.prototype.faster = function()
  77. {
  78. this.interval *= 0.7;
  79. if(this.direction > 0){this.play_animation();}
  80. else if(this.direction < 0){this.reverse_animation();}
  81. }
  82. Animation.prototype.anim_step_forward = function()
  83. {
  84. this.current_frame += 1;
  85. if(this.current_frame < this.frames.length){
  86. this.set_frame(this.current_frame);
  87. }else{
  88. var loop_state = this.get_loop_state();
  89. if(loop_state == "loop"){
  90. this.first_frame();
  91. }else if(loop_state == "reflect"){
  92. this.last_frame();
  93. this.reverse_animation();
  94. }else{
  95. this.pause_animation();
  96. this.last_frame();
  97. }
  98. }
  99. }
  100. Animation.prototype.anim_step_reverse = function()
  101. {
  102. this.current_frame -= 1;
  103. if(this.current_frame >= 0){
  104. this.set_frame(this.current_frame);
  105. }else{
  106. var loop_state = this.get_loop_state();
  107. if(loop_state == "loop"){
  108. this.last_frame();
  109. }else if(loop_state == "reflect"){
  110. this.first_frame();
  111. this.play_animation();
  112. }else{
  113. this.pause_animation();
  114. this.first_frame();
  115. }
  116. }
  117. }
  118. Animation.prototype.pause_animation = function()
  119. {
  120. this.direction = 0;
  121. if (this.timer){
  122. clearInterval(this.timer);
  123. this.timer = null;
  124. }
  125. }
  126. Animation.prototype.play_animation = function()
  127. {
  128. this.pause_animation();
  129. this.direction = 1;
  130. var t = this;
  131. if (!this.timer) this.timer = setInterval(function() {
  132. t.anim_step_forward();
  133. }, this.interval);
  134. }
  135. Animation.prototype.reverse_animation = function()
  136. {
  137. this.pause_animation();
  138. this.direction = -1;
  139. var t = this;
  140. if (!this.timer) this.timer = setInterval(function() {
  141. t.anim_step_reverse();
  142. }, this.interval);
  143. }
  144. </script>
  145. """
  146. # Style definitions for the HTML template
  147. STYLE_INCLUDE = """
  148. <style>
  149. .animation {
  150. display: inline-block;
  151. text-align: center;
  152. }
  153. input[type=range].anim-slider {
  154. width: 374px;
  155. margin-left: auto;
  156. margin-right: auto;
  157. }
  158. .anim-buttons {
  159. margin: 8px 0px;
  160. }
  161. .anim-buttons button {
  162. padding: 0;
  163. width: 36px;
  164. }
  165. .anim-state label {
  166. margin-right: 8px;
  167. }
  168. .anim-state input {
  169. margin: 0;
  170. vertical-align: middle;
  171. }
  172. </style>
  173. """
  174. # HTML template for HTMLWriter
  175. DISPLAY_TEMPLATE = """
  176. <div class="animation">
  177. <img id="_anim_img{id}">
  178. <div class="anim-controls">
  179. <input id="_anim_slider{id}" type="range" class="anim-slider"
  180. name="points" min="0" max="1" step="1" value="0"
  181. oninput="anim{id}.set_frame(parseInt(this.value));"></input>
  182. <div class="anim-buttons">
  183. <button onclick="anim{id}.slower()"><i class="fa fa-minus"></i></button>
  184. <button onclick="anim{id}.first_frame()"><i class="fa fa-fast-backward">
  185. </i></button>
  186. <button onclick="anim{id}.previous_frame()">
  187. <i class="fa fa-step-backward"></i></button>
  188. <button onclick="anim{id}.reverse_animation()">
  189. <i class="fa fa-play fa-flip-horizontal"></i></button>
  190. <button onclick="anim{id}.pause_animation()"><i class="fa fa-pause">
  191. </i></button>
  192. <button onclick="anim{id}.play_animation()"><i class="fa fa-play"></i>
  193. </button>
  194. <button onclick="anim{id}.next_frame()"><i class="fa fa-step-forward">
  195. </i></button>
  196. <button onclick="anim{id}.last_frame()"><i class="fa fa-fast-forward">
  197. </i></button>
  198. <button onclick="anim{id}.faster()"><i class="fa fa-plus"></i></button>
  199. </div>
  200. <form action="#n" name="_anim_loop_select{id}" class="anim-state">
  201. <input type="radio" name="state" value="once" id="_anim_radio1_{id}"
  202. {once_checked}>
  203. <label for="_anim_radio1_{id}">Once</label>
  204. <input type="radio" name="state" value="loop" id="_anim_radio2_{id}"
  205. {loop_checked}>
  206. <label for="_anim_radio2_{id}">Loop</label>
  207. <input type="radio" name="state" value="reflect" id="_anim_radio3_{id}"
  208. {reflect_checked}>
  209. <label for="_anim_radio3_{id}">Reflect</label>
  210. </form>
  211. </div>
  212. </div>
  213. <script language="javascript">
  214. /* Instantiate the Animation class. */
  215. /* The IDs given should match those used in the template above. */
  216. (function() {{
  217. var img_id = "_anim_img{id}";
  218. var slider_id = "_anim_slider{id}";
  219. var loop_select_id = "_anim_loop_select{id}";
  220. var frames = new Array({Nframes});
  221. {fill_frames}
  222. /* set a timeout to make sure all the above elements are created before
  223. the object is initialized. */
  224. setTimeout(function() {{
  225. anim{id} = new Animation(frames, img_id, slider_id, {interval},
  226. loop_select_id);
  227. }}, 0);
  228. }})()
  229. </script>
  230. """
  231. INCLUDED_FRAMES = """
  232. for (var i=0; i<{Nframes}; i++){{
  233. frames[i] = "{frame_dir}/frame" + ("0000000" + i).slice(-7) +
  234. ".{frame_format}";
  235. }}
  236. """