wavify.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. * Wavify
  3. * JavaScript library to make some nice waves
  4. * by peacepostman @ potion
  5. */
  6. function wavify(wave_element, options) {
  7. if ("undefined" === typeof options) options = {};
  8. // Options
  9. //
  10. //
  11. var settings = Object.assign(
  12. {},
  13. {
  14. container: options.container ? options.container : "body",
  15. // Height of wave
  16. height: 200,
  17. // Amplitude of wave
  18. amplitude: 100,
  19. // Animation speed
  20. speed: 0.15,
  21. // Total number of articulation in wave
  22. bones: 3,
  23. // Color
  24. color: "rgba(255,255,255, 0.20)"
  25. },
  26. options
  27. );
  28. var wave = wave_element,
  29. width = document.querySelector(settings.container).getBoundingClientRect()
  30. .width,
  31. height = document.querySelector(settings.container).getBoundingClientRect()
  32. .height,
  33. points = [],
  34. lastUpdate,
  35. totalTime = 0,
  36. animationInstance = false,
  37. tweenMaxInstance = false;
  38. // Allow new settings, avoid setting new container for logic purpose please :)
  39. //
  40. function rebuilSettings(params) {
  41. settings = Object.assign({}, settings, params);
  42. }
  43. function drawPoints(factor) {
  44. var points = [];
  45. for (var i = 0; i <= settings.bones; i++) {
  46. var x = (i / settings.bones) * width;
  47. var sinSeed =
  48. (factor + (i + (i % settings.bones))) * settings.speed * 100;
  49. var sinHeight = Math.sin(sinSeed / 100) * settings.amplitude;
  50. var yPos = Math.sin(sinSeed / 100) * sinHeight + settings.height;
  51. points.push({ x: x, y: yPos });
  52. }
  53. return points;
  54. }
  55. function drawPath(points) {
  56. var SVGString = "M " + points[0].x + " " + points[0].y;
  57. var cp0 = {
  58. x: (points[1].x - points[0].x) / 2,
  59. y: points[1].y - points[0].y + points[0].y + (points[1].y - points[0].y)
  60. };
  61. SVGString +=
  62. " C " +
  63. cp0.x +
  64. " " +
  65. cp0.y +
  66. " " +
  67. cp0.x +
  68. " " +
  69. cp0.y +
  70. " " +
  71. points[1].x +
  72. " " +
  73. points[1].y;
  74. var prevCp = cp0;
  75. var inverted = -1;
  76. for (var i = 1; i < points.length - 1; i++) {
  77. var cpLength = Math.sqrt(prevCp.x * prevCp.x + prevCp.y * prevCp.y);
  78. var cp1 = {
  79. x: points[i].x - prevCp.x + points[i].x,
  80. y: points[i].y - prevCp.y + points[i].y
  81. };
  82. SVGString +=
  83. " C " +
  84. cp1.x +
  85. " " +
  86. cp1.y +
  87. " " +
  88. cp1.x +
  89. " " +
  90. cp1.y +
  91. " " +
  92. points[i + 1].x +
  93. " " +
  94. points[i + 1].y;
  95. prevCp = cp1;
  96. inverted = -inverted;
  97. }
  98. SVGString += " L " + width + " " + height;
  99. SVGString += " L 0 " + height + " Z";
  100. return SVGString;
  101. }
  102. // Draw function
  103. //
  104. //
  105. function draw() {
  106. var now = window.Date.now();
  107. if (lastUpdate) {
  108. var elapsed = (now - lastUpdate) / 1000;
  109. lastUpdate = now;
  110. totalTime += elapsed;
  111. var factor = totalTime * Math.PI;
  112. tweenMaxInstance = TweenMax.to(wave, settings.speed, {
  113. attr: {
  114. d: drawPath(drawPoints(factor))
  115. },
  116. ease: Power1.easeInOut
  117. });
  118. } else {
  119. lastUpdate = now;
  120. }
  121. animationInstance = requestAnimationFrame(draw);
  122. }
  123. // Pure js debounce function to optimize resize method
  124. //
  125. //
  126. function debounce(func, wait, immediate) {
  127. var timeout;
  128. return function() {
  129. var context = this,
  130. args = arguments;
  131. clearTimeout(timeout);
  132. timeout = setTimeout(function() {
  133. timeout = null;
  134. if (!immediate) func.apply(context, args);
  135. }, wait);
  136. if (immediate && !timeout) func.apply(context, args);
  137. };
  138. }
  139. // Redraw for resize with debounce
  140. //
  141. var redraw = debounce(function() {
  142. pause();
  143. points = [];
  144. totalTime = 0;
  145. width = document.querySelector(settings.container).getBoundingClientRect()
  146. .width;
  147. height = document.querySelector(settings.container).getBoundingClientRect()
  148. .height;
  149. lastUpdate = false;
  150. play();
  151. }, 250);
  152. function boot() {
  153. if (!animationInstance) {
  154. tweenMaxInstance = TweenMax.set(wave, { attr: { fill: settings.color } });
  155. play();
  156. window.addEventListener("resize", redraw);
  157. }
  158. }
  159. function reboot(options) {
  160. kill();
  161. if (typeof options !== undefined) {
  162. rebuilSettings(options);
  163. }
  164. tweenMaxInstance = TweenMax.set(wave, { attr: { fill: settings.color } });
  165. play();
  166. window.addEventListener("resize", redraw);
  167. }
  168. function play() {
  169. if (!animationInstance) {
  170. animationInstance = requestAnimationFrame(draw);
  171. }
  172. }
  173. function pause() {
  174. if (animationInstance) {
  175. cancelAnimationFrame(animationInstance);
  176. animationInstance = false;
  177. }
  178. }
  179. function updateColor(options) {
  180. if (typeof options.timing === undefined) {
  181. options.timing = 1;
  182. }
  183. if (typeof options.color === undefined) {
  184. options.color = settings.color;
  185. }
  186. tweenMaxInstance = TweenMax.to(wave, parseInt(options.timing), {
  187. attr: { fill: options.color },
  188. onComplete: function() {
  189. if (
  190. typeof options.onComplete !== undefined &&
  191. {}.toString.call(options.onComplete) === "[object Function]"
  192. ) {
  193. options.onComplete();
  194. }
  195. }
  196. });
  197. }
  198. function kill() {
  199. if (animationInstance) {
  200. pause();
  201. tweenMaxInstance.kill();
  202. tweenMaxInstance = TweenMax.set(wave, {
  203. x: 0,
  204. y: 0,
  205. rotation: 0,
  206. opacity: 0,
  207. clearProps: "all",
  208. attr: {
  209. d: "M0,0",
  210. fill: ""
  211. }
  212. });
  213. window.removeEventListener("resize", redraw);
  214. animationInstance = false;
  215. }
  216. }
  217. // Boot Wavify
  218. //
  219. boot();
  220. return {
  221. reboot: reboot,
  222. play: play,
  223. pause: pause,
  224. kill: kill,
  225. updateColor: updateColor
  226. };
  227. }
  228. /*
  229. * Wavify
  230. * Jquery Plugin to make some nice waves
  231. * by peacepostman @ potion
  232. */
  233. ;(function($) {
  234. $.fn.wavify = function(options) {
  235. if ("function" !== typeof wavify) {
  236. console.error(
  237. "wavify is not a function. Be sure to include 'wavify.js' before you include 'jquery.wavify.js'."
  238. );
  239. throw "Error: wavify is not a function";
  240. }
  241. return wavify(this, options);
  242. };
  243. })(jQuery);