JavaScript HTML5 Canvas Animation Background

JavaScript HTML5 Canvas Animation Background
Code Snippet:Ribbons Effect With HTML5 Canvas and Javascript
Author: Rainner Lins
Published: January 11, 2024
Last Updated: January 22, 2024
Downloads: 7,235
License: MIT
Edit Code online: View on CodePen
Read More

This JavaScript code snippet helps you to create HTML5 canvas animation background. It draws an attractive low-poly ribbons background effect inside a target container. The ribbon’s color and size can be customized according to your needs. You can use this for website background to attract users.

How to Create JavaScript HTML5 Canvas Animation Background

1. First of all, add the following CSS styles to your project:

  1. body {
  2. background-color: #403060;
  3. background-image: radial-gradient(circle, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
  4. background-position: center center;
  5. background-repeat: no-repeat;
  6. background-attachment: fixed;
  7. background-size: cover;
  8. }

3. Then, add the following JavaScript code and done.

  1. /**
  2. * Ribbons Class File.
  3. * Creates low-poly ribbons background effect inside a target container.
  4. */
  5. (function( name, factory )
  6. {
  7. if( typeof window === "object" )
  8. {
  9. window[ name ] = factory();
  10. }
  11.  
  12. })( "Ribbons", function()
  13. {
  14. var _w = window,
  15. _b = document.body,
  16. _d = document.documentElement;
  17.  
  18. // random helper
  19. var random = function()
  20. {
  21. if( arguments.length === 1 ) // only 1 argument
  22. {
  23. if( Array.isArray( arguments[0] ) ) // extract index from array
  24. {
  25. var index = Math.round( random( 0, arguments[0].length - 1 ) );
  26. return arguments[0][ index ];
  27. }
  28. return random( 0, arguments[0] ); // assume numeric
  29. }
  30. else if( arguments.length === 2 ) // two arguments range
  31. {
  32. return Math.random() * ( arguments[1] - arguments[0] ) + arguments[0];
  33. }
  34. return 0; // default
  35. };
  36.  
  37. // screen helper
  38. var screenInfo = function( e )
  39. {
  40. var width = Math.max( 0, _w.innerWidth || _d.clientWidth || _b.clientWidth || 0 ),
  41. height = Math.max( 0, _w.innerHeight || _d.clientHeight || _b.clientHeight || 0 ),
  42. scrollx = Math.max( 0, _w.pageXOffset || _d.scrollLeft || _b.scrollLeft || 0 ) - ( _d.clientLeft || 0 ),
  43. scrolly = Math.max( 0, _w.pageYOffset || _d.scrollTop || _b.scrollTop || 0 ) - ( _d.clientTop || 0 );
  44.  
  45. return {
  46. width : width,
  47. height : height,
  48. ratio : width / height,
  49. centerx : width / 2,
  50. centery : height / 2,
  51. scrollx : scrollx,
  52. scrolly : scrolly,
  53. };
  54. };
  55.  
  56. // mouse/input helper
  57. var mouseInfo = function( e )
  58. {
  59. var screen = screenInfo( e ),
  60. mousex = e ? Math.max( 0, e.pageX || e.clientX || 0 ) : 0,
  61. mousey = e ? Math.max( 0, e.pageY || e.clientY || 0 ) : 0;
  62.  
  63. return {
  64. mousex : mousex,
  65. mousey : mousey,
  66. centerx : mousex - ( screen.width / 2 ),
  67. centery : mousey - ( screen.height / 2 ),
  68. };
  69. };
  70.  
  71. // point object
  72. var Point = function( x, y )
  73. {
  74. this.x = 0;
  75. this.y = 0;
  76. this.set( x, y );
  77. };
  78. Point.prototype = {
  79. constructor: Point,
  80.  
  81. set: function( x, y )
  82. {
  83. this.x = ( x || 0 );
  84. this.y = ( y || 0 );
  85. },
  86. copy: function( point )
  87. {
  88. this.x = ( point.x || 0 );
  89. this.y = ( point.y || 0 );
  90. return this;
  91. },
  92. multiply: function( x, y )
  93. {
  94. this.x *= ( x || 1 );
  95. this.y *= ( y || 1 );
  96. return this;
  97. },
  98. divide: function( x, y )
  99. {
  100. this.x /= ( x || 1 );
  101. this.y /= ( y || 1 );
  102. return this;
  103. },
  104. add: function( x, y )
  105. {
  106. this.x += ( x || 0 );
  107. this.y += ( y || 0 );
  108. return this;
  109. },
  110. subtract: function( x, y )
  111. {
  112. this.x -= ( x || 0 );
  113. this.y -= ( y || 0 );
  114. return this;
  115. },
  116. clampX: function( min, max )
  117. {
  118. this.x = Math.max( min, Math.min( this.x, max ) );
  119. return this;
  120. },
  121. clampY: function( min, max )
  122. {
  123. this.y = Math.max( min, Math.min( this.y, max ) );
  124. return this;
  125. },
  126. flipX: function()
  127. {
  128. this.x *= -1;
  129. return this;
  130. },
  131. flipY: function()
  132. {
  133. this.y *= -1;
  134. return this;
  135. },
  136. };
  137.  
  138. // class constructor
  139. var Factory = function( options )
  140. {
  141. this._canvas = null;
  142. this._context = null;
  143. this._sto = null;
  144. this._width = 0;
  145. this._height = 0;
  146. this._scroll = 0;
  147. this._ribbons = [];
  148. this._options = {
  149. // ribbon color HSL saturation amount
  150. colorSaturation: "80%",
  151. // ribbon color HSL brightness amount
  152. colorBrightness: "60%",
  153. // ribbon color opacity amount
  154. colorAlpha: 0.65,
  155. // how fast to cycle through colors in the HSL color space
  156. colorCycleSpeed : 6,
  157. // where to start from on the Y axis on each side (top|min, middle|center, bottom|max, random)
  158. verticalPosition : "center",
  159. // how fast to get to the other side of the screen
  160. horizontalSpeed : 150,
  161. // how many ribbons to keep on screen at any given time
  162. ribbonCount: 3,
  163. // add stroke along with ribbon fill colors
  164. strokeSize: 0,
  165. // move ribbons vertically by a factor on page scroll
  166. parallaxAmount : -0.5,
  167. // add animation effect to each ribbon section over time
  168. animateSections : true,
  169. };
  170. this._onDraw = this._onDraw.bind( this );
  171. this._onResize = this._onResize.bind( this );
  172. this._onScroll = this._onScroll.bind( this );
  173. this.setOptions( options );
  174. this.init();
  175. };
  176.  
  177. // class prototype
  178. Factory.prototype = {
  179. constructor: Factory,
  180.  
  181. // Set and merge local options
  182. setOptions: function( options )
  183. {
  184. if( typeof options === "object" )
  185. {
  186. for( var key in options )
  187. {
  188. if( options.hasOwnProperty( key ) )
  189. {
  190. this._options[ key ] = options[ key ];
  191. }
  192. }
  193. }
  194. },
  195.  
  196. // Initialize the ribbons effect
  197. init: function()
  198. {
  199. try
  200. {
  201. this._canvas = document.createElement( "canvas" );
  202. this._canvas.style["display"] = "block";
  203. this._canvas.style["position"] = "fixed";
  204. this._canvas.style["margin"] = "0";
  205. this._canvas.style["padding"] = "0";
  206. this._canvas.style["border"] = "0";
  207. this._canvas.style["outline"] = "0";
  208. this._canvas.style["left"] = "0";
  209. this._canvas.style["top"] = "0";
  210. this._canvas.style["width"] = "100%";
  211. this._canvas.style["height"] = "100%";
  212. this._canvas.style["z-index"] = "-1";
  213. this._onResize();
  214.  
  215. this._context = this._canvas.getContext( "2d" );
  216. this._context.clearRect( 0, 0, this._width, this._height );
  217. this._context.globalAlpha = this._options.colorAlpha;
  218.  
  219. window.addEventListener( "resize", this._onResize );
  220. window.addEventListener( "scroll", this._onScroll );
  221. document.body.appendChild( this._canvas );
  222. }
  223. catch( e ) {
  224. console.warn( "Canvas Context Error: " + e.toString() );
  225. return;
  226. }
  227. this._onDraw();
  228. },
  229.  
  230. // Create a new random ribbon and to the list
  231. addRibbon: function()
  232. {
  233. // movement data
  234. var dir = ( Math.round( random( 1, 9 ) ) > 5 ) ? "right" : "left",
  235. stop = 1000,
  236. hide = 200,
  237. min = 0 - hide,
  238. max = this._width + hide,
  239. movex = 0,
  240. movey = 0,
  241. startx = ( dir === "right" ) ? min : max,
  242. starty = Math.round( random( 0, this._height ) );
  243.  
  244. // asjust starty based on options
  245. if( /^(top|min)$/i.test( this._options.verticalPosition ) )
  246. {
  247. starty = 0 + hide;
  248. }
  249. else if( /^(middle|center)$/i.test( this._options.verticalPosition ) )
  250. {
  251. starty = ( this._height / 2 );
  252. }
  253. else if( /^(bottom|max)$/i.test( this._options.verticalPosition ) )
  254. {
  255. starty = this._height - hide;
  256. }
  257.  
  258. // ribbon sections data
  259. var ribbon = [],
  260. point1 = new Point( startx, starty ),
  261. point2 = new Point( startx, starty ),
  262. point3 = null,
  263. color = Math.round( random( 0, 360 ) ),
  264. delay = 0;
  265.  
  266. // buils ribbon sections
  267. while( true )
  268. {
  269. if( stop <= 0 ) break; stop--;
  270.  
  271. movex = Math.round( ( Math.random() * 1 - 0.2 ) * this._options.horizontalSpeed );
  272. movey = Math.round( ( Math.random() * 1 - 0.5 ) * ( this._height * 0.25 ) );
  273.  
  274. point3 = new Point();
  275. point3.copy( point2 );
  276.  
  277. if( dir === "right" )
  278. {
  279. point3.add( movex, movey );
  280. if( point2.x >= max ) break;
  281. }
  282. else if( dir === "left" )
  283. {
  284. point3.subtract( movex, movey );
  285. if( point2.x <= min ) break;
  286. }
  287. // point3.clampY( 0, this._height );
  288.  
  289. ribbon.push({ // single ribbon section
  290. point1 : new Point( point1.x, point1.y ),
  291. point2 : new Point( point2.x, point2.y ),
  292. point3 : point3,
  293. color : color,
  294. delay : delay,
  295. dir : dir,
  296. alpha : 0,
  297. phase : 0,
  298. });
  299.  
  300. point1.copy( point2 );
  301. point2.copy( point3 );
  302.  
  303. delay += 4;
  304. color += this._options.colorCycleSpeed;
  305. }
  306. this._ribbons.push( ribbon );
  307. },
  308.  
  309. // Draw single section
  310. _drawRibbonSection: function( section )
  311. {
  312. if( section )
  313. {
  314. if( section.phase >= 1 && section.alpha <= 0 )
  315. {
  316. return true; // done
  317. }
  318. if( section.delay <= 0 )
  319. {
  320. section.phase += 0.02;
  321. section.alpha = Math.sin( section.phase ) * 1;
  322. section.alpha = ( section.alpha <= 0 ) ? 0 : section.alpha;
  323. section.alpha = ( section.alpha >= 1 ) ? 1 : section.alpha;
  324.  
  325. if( this._options.animateSections )
  326. {
  327. var mod = ( Math.sin( 1 + section.phase * Math.PI / 2 ) * 0.1 );
  328.  
  329. if( section.dir === "right" )
  330. {
  331. section.point1.add( mod, 0 );
  332. section.point2.add( mod, 0 );
  333. section.point3.add( mod, 0 );
  334. } else {
  335. section.point1.subtract( mod, 0 );
  336. section.point2.subtract( mod, 0 );
  337. section.point3.subtract( mod, 0 );
  338. }
  339. section.point1.add( 0, mod );
  340. section.point2.add( 0, mod );
  341. section.point3.add( 0, mod );
  342. }
  343. }
  344. else { section.delay -= 0.5; }
  345.  
  346. var s = this._options.colorSaturation,
  347. l = this._options.colorBrightness,
  348. c = "hsla("+ section.color +", "+ s +", "+ l +", "+ section.alpha +" )";
  349.  
  350. this._context.save();
  351.  
  352. if( this._options.parallaxAmount !== 0 )
  353. {
  354. this._context.translate( 0, this._scroll * this._options.parallaxAmount );
  355. }
  356. this._context.beginPath();
  357. this._context.moveTo( section.point1.x, section.point1.y );
  358. this._context.lineTo( section.point2.x, section.point2.y );
  359. this._context.lineTo( section.point3.x, section.point3.y );
  360. this._context.fillStyle = c;
  361. this._context.fill();
  362.  
  363. if( this._options.strokeSize > 0 )
  364. {
  365. this._context.lineWidth = this._options.strokeSize;
  366. this._context.strokeStyle = c;
  367. this._context.lineCap = "round";
  368. this._context.stroke();
  369. }
  370. this._context.restore();
  371. }
  372. return false; // not done yet
  373. },
  374.  
  375. // Draw ribbons
  376. _onDraw: function()
  377. {
  378. // cleanup on ribbons list to rtemoved finished ribbons
  379. for( var i = 0, t = this._ribbons.length; i < t; ++i )
  380. {
  381. if( !this._ribbons[ i ] )
  382. {
  383. this._ribbons.splice( i, 1 );
  384. }
  385. }
  386. // draw new ribbons
  387. this._context.clearRect( 0, 0, this._width, this._height );
  388.  
  389. for( var a = 0; a < this._ribbons.length; ++a ) // single ribbon
  390. {
  391. var ribbon = this._ribbons[ a ],
  392. numSections = ribbon.length,
  393. numDone = 0;
  394.  
  395. for( var b = 0; b < numSections; ++b ) // ribbon section
  396. {
  397. if( this._drawRibbonSection( ribbon[ b ] ) )
  398. {
  399. numDone++; // section done
  400. }
  401. }
  402. if( numDone >= numSections ) // ribbon done
  403. {
  404. this._ribbons[ a ] = null;
  405. }
  406. }
  407. // maintain optional number of ribbons on canvas
  408. if( this._ribbons.length < this._options.ribbonCount )
  409. {
  410. this.addRibbon();
  411. }
  412. requestAnimationFrame( this._onDraw );
  413. },
  414.  
  415. // Update container size info
  416. _onResize: function( e )
  417. {
  418. var screen = screenInfo( e );
  419. this._width = screen.width;
  420. this._height = screen.height;
  421.  
  422. if( this._canvas )
  423. {
  424. this._canvas.width = this._width;
  425. this._canvas.height = this._height;
  426. if( this._context )
  427. {
  428. this._context.globalAlpha = this._options.colorAlpha;
  429. }
  430. }
  431. },
  432.  
  433. // Update container size info
  434. _onScroll: function( e )
  435. {
  436. var screen = screenInfo( e );
  437. this._scroll = screen.scrolly;
  438. },
  439.  
  440. };
  441.  
  442. // export
  443. return Factory;
  444. });
  445.  
  446.  
  447. new Ribbons({
  448. colorSaturation: "60%",
  449. colorBrightness: "50%",
  450. colorAlpha: 0.5,
  451. colorCycleSpeed : 5,
  452. verticalPosition : "random",
  453. horizontalSpeed : 200,
  454. ribbonCount: 3,
  455. strokeSize: 0,
  456. parallaxAmount : -0.2,
  457. animateSections : true,
  458. });

That’s all! hopefully, you have successfully integrated this HTML5 canvas animation background code snippet into your project. If you have any questions or are facing any issues, please feel free to comment below.

3 thoughts on “JavaScript HTML5 Canvas Animation Background”

  1. Hello, every time i refresh the page it says “Ribbons is not defined” at row 449 “new Ribbons” and i have to delete a part of the code then refres hand put it back for it to work again, however then it breaks again if i refresh

    Reply
    • Hi

      Please make sure Ribbons Class File is included in your project and does not conflict with other JavaScript files. Follow the tutorial carefully to integrate it into your project.

      Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About CodeHim

Free Web Design Code & Scripts - CodeHim is one of the BEST developer websites that provide web designers and developers with a simple way to preview and download a variety of free code & scripts. All codes published on CodeHim are open source, distributed under OSD-compliant license which grants all the rights to use, study, change and share the software in modified and unmodified form. Before publishing, we test and review each code snippet to avoid errors, but we cannot warrant the full correctness of all content. All trademarks, trade names, logos, and icons are the property of their respective owners... find out more...

Please Rel0ad/PressF5 this page if you can't click the download/preview link

X