Animated Weather Card in Vanilla JS

Animated Weather Card in Vanilla JS
Code Snippet:Animated Weather Cards
Author: Steve Gardner
Published: January 20, 2024
Last Updated: January 22, 2024
Downloads: 1,378
License: MIT
Edit Code online: View on CodePen
Read More

The code Vanilla JS code snippet helps you to create an animated weather card. It allows you to display weather conditions with animations on a web page.

The major functionalities include:

  • Displaying weather conditions such as snow, wind, rain, thunder, and sunny weather.
  • Animating raindrops, snowflakes, leaves, and clouds based on the selected weather condition.
  • Providing a visually appealing weather summary card with temperature, date, and weather description.

This code helps you create an interactive and visually engaging weather display on your website.

How to Create Animated Weather Card In Vanilla Js

1. In your HTML file, create a structure for your weather card. You’ll need a container for the card, a location label, a temperature display, and an element for the animated weather icon.

  1. <div class="background">
  2. <div class="container">
  3. <svg id="back">
  4. <radialGradient id="SVGID_1_" cx="0" cy="0" r="320.8304" gradientUnits="userSpaceOnUse">
  5. <stop offset="0" style="stop-color:#FFDE17;stop-opacity:0.7"/>
  6. <stop offset="1" style="stop-color:#FFF200;stop-opacity:0"/>
  7. </radialGradient>
  8. <path id="sunburst" style="fill:url(#SVGID_1_);" d="M0,319.7c-18.6,0-37.3-1.6-55.5-4.8L-7.8,41.4c5.1,0.9,10.6,0.9,15.7,0L56,314.8C37.6,318,18.8,319.7,0,319.7z
  9. M-160.8,276.6c-32.5-18.8-61.3-42.9-85.5-71.6L-34,26.2c3.4,4.1,7.4,7.4,12,10.1L-160.8,276.6z M161.3,276.4L22.1,36.2
  10. c4.5-2.6,8.6-6,12-10.1l212.6,178.5C222.5,233.4,193.8,257.6,161.3,276.4z M-302.5,108.3C-315.4,73-321.9,36-322-1.8l277.6-0.5
  11. c0,5.3,0.9,10.4,2.7,15.2L-302.5,108.3z M302.6,107.8L41.8,12.8c1.7-4.7,2.6-9.7,2.6-14.9c0-0.3,0-0.6,0-1H322l0-1.3l0,1.9
  12. C322,35.4,315.5,72.5,302.6,107.8z M-41.8-17.5l-261-94.5c12.8-35.4,31.6-68,55.8-96.9L-34.1-30.8C-37.5-26.8-40.1-22.3-41.8-17.5z
  13. M41.7-17.7c-1.8-4.8-4.4-9.3-7.8-13.3l212-179.2c24.3,28.8,43.3,61.3,56.3,96.6L41.7-17.7z M-22.2-40.8l-139.6-240
  14. c32.7-19,68.1-32,105.2-38.6L-8-46.1C-13-45.2-17.8-43.4-22.2-40.8z M22-40.9c-4.4-2.6-9.2-4.3-14.2-5.1l47.1-273.6
  15. c37.2,6.4,72.7,19.2,105.4,38L22-40.9z"/>
  16. </svg>
  17. <nav>
  18. <ul>
  19. <li><a id="button-snow" class="active"><i class="wi wi-snow"></i></a></li>
  20. <li><a id="button-wind"><i class="wi wi-strong-wind"></i></a></li>
  21. <li><a id="button-rain"><i class="wi wi-rain"></i></a></li>
  22. <li><a id="button-thunder"><i class="wi wi-lightning"></i></a></li>
  23. <li><a id="button-sun"><i class="wi wi-day-sunny"></i></a></li>
  24. </ul>
  25. </nav>
  26. <div id="card" class="weather">
  27. <svg id="inner">
  28. <defs>
  29. <path id="leaf" d="M41.9,56.3l0.1-2.5c0,0,4.6-1.2,5.6-2.2c1-1,3.6-13,12-15.6c9.7-3.1,19.9-2,26.1-2.1c2.7,0-10,23.9-20.5,25 c-7.5,0.8-17.2-5.1-17.2-5.1L41.9,56.3z"/>
  30. </defs>
  31. <circle id="sun" style="fill: #F7ED47" cx="0" cy="0" r="50"/>
  32. <g id="layer3"></g>
  33. <g id="cloud3" class="cloud"></g>
  34. <g id="layer2"></g>
  35. <g id="cloud2" class="cloud"></g>
  36. <g id="layer1"></g>
  37. <g id="cloud1" class="cloud"></g>
  38. </svg>
  39. <div class="details">
  40. <div class="temp">20<span>c</span></div>
  41. <div class="right">
  42. <div id="date">Monday 22 August</div>
  43. <div id="summary"></div>
  44. </div>
  45. </div>
  46. </div>
  47. <svg id="outer"></svg>
  48. </div>
  49. </div>

2. Create a “styles.css” file to style your weather card and the animated weather icon. Customize the styles according to your preferences.

  1. @import 'https://fonts.googleapis.com/css?family=Lato:300';
  2. @import 'https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css';
  3. html, body, .background {
  4. width: 100%;
  5. height: 100%;
  6. margin: 0;
  7. padding: 0;
  8. font-family: "Lato", sans-serif;
  9. }
  10.  
  11. html {
  12. background: #fff;
  13. }
  14.  
  15. body {
  16. background: #eee;
  17. background: linear-gradient(0deg, rgba(0, 0, 200, 0.2), rgba(0, 0, 200, 0));
  18. }
  19.  
  20. .background {
  21. background: #eee;
  22. background: linear-gradient(120deg, rgba(50, 150, 100, 0.2), rgba(0, 0, 100, 0));
  23. }
  24.  
  25. .container {
  26. display: flex;
  27. flex-direction: column;
  28. align-items: center;
  29. justify-content: center;
  30. margin: 0;
  31. padding: 0;
  32. height: 100%;
  33. width: 100%;
  34. overflow: auto;
  35. position: relative;
  36. background: #eee;
  37. background: linear-gradient(240deg, rgba(150, 50, 50, 0.3), rgba(0, 0, 200, 0));
  38. }
  39. nav ul {
  40. margin: 20px 20px 0 20px;
  41. list-style-type: none;
  42. padding: 0;
  43. display: flex;
  44. flex-direction: row;
  45. }
  46. nav li a {
  47. display: block;
  48. width: 50px;
  49. text-align: center;
  50. color: #aaa;
  51. cursor: pointer;
  52. }
  53. nav li a:hover {
  54. color: #444;
  55. }
  56. nav li a.active {
  57. color: #4444ff;
  58. }
  59.  
  60. #card {
  61. box-shadow: 9px 7px 40px -6px rgba(0, 0, 0, 0.25);
  62. overflow: hidden;
  63. width: 300px;
  64. padding: 0;
  65. height: 400px;
  66. min-height: 300px;
  67. margin: 20px;
  68. border-radius: 5px;
  69. position: relative;
  70. }
  71. #card .details {
  72. position: absolute;
  73. top: 0;
  74. left: 0;
  75. right: 0;
  76. padding: 16px 20px;
  77. color: #888;
  78. display: flex;
  79. flex-direction: row;
  80. justify-content: space-between;
  81. transition: color 2s ease;
  82. }
  83. .thunder #card .details {
  84. color: #ddd;
  85. }
  86. #card .details .right {
  87. text-align: right;
  88. }
  89. #card .details #date {
  90. margin: 4px 0;
  91. }
  92. #card .details #summary {
  93. font-weight: 600;
  94. font-size: 22px;
  95. }
  96. #card .details .temp {
  97. font-size: 60px;
  98. line-height: 60px;
  99. }
  100. #card .details .temp span {
  101. font-size: 18px;
  102. line-height: 30px;
  103. vertical-align: top;
  104. margin-left: 5px;
  105. }
  106.  
  107. .weather {
  108. background-color: #DAE3FD;
  109. transition: background-color 2s ease;
  110. }
  111. .thunder .weather {
  112. background-color: #9FA4AD;
  113. }
  114. .rain .weather {
  115. background-color: #D8D8D8;
  116. }
  117. .sun .weather {
  118. background-color: #ccccff;
  119. }
  120. .weather #inner {
  121. background-color: white;
  122. background: linear-gradient(to bottom, rgba(255, 255, 255, 0.5) 50%, rgba(255, 255, 255, 0) 100%);
  123. }
  124. .weather .cloud {
  125. transition: fill 2s ease;
  126. }
  127. .weather #cloud1 {
  128. fill: #efefef;
  129. }
  130. .thunder .weather #cloud1 {
  131. fill: #9FA4AD;
  132. }
  133. .weather #cloud2 {
  134. fill: #E6E6E6;
  135. }
  136. .thunder .weather #cloud2 {
  137. fill: #8B8E98;
  138. }
  139. .weather #cloud3 {
  140. fill: #D5D5D5;
  141. }
  142. .thunder .weather #cloud3 {
  143. fill: #7B7988;
  144. }
  145.  
  146. #outer, #back {
  147. position: fixed;
  148. pointer-events: none;
  149. }

3. Now, load the jQuery, TweenMax JS, and Snap SVG JS by adding the following scripts before closing the body tag:

  1. <script src='https://code.jquery.com/jquery-2.2.4.min.js'></script>
  2. <script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js'></script>
  3. <script src='https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js'></script>
  4. <script src='https://codepen.io/ste-vg/pen/zBVaZw.js'></script>

4. Create a "script.js" file to handle fetching weather data and updating the card. You can use a weather API like OpenWeatherMap to get real weather data.

  1. // 📝 Fetch all DOM nodes in jQuery and Snap SVG
  2.  
  3. var container = $('.container');
  4. var card = $('#card');
  5. var innerSVG = Snap('#inner');
  6. var outerSVG = Snap('#outer');
  7. var backSVG = Snap('#back');
  8. var summary = $('#summary');
  9. var date = $('#date');
  10. var weatherContainer1 = Snap.select('#layer1');
  11. var weatherContainer2 = Snap.select('#layer2');
  12. var weatherContainer3 = Snap.select('#layer3');
  13. var innerRainHolder1 = weatherContainer1.group();
  14. var innerRainHolder2 = weatherContainer2.group();
  15. var innerRainHolder3 = weatherContainer3.group();
  16. var innerLeafHolder = weatherContainer1.group();
  17. var innerSnowHolder = weatherContainer1.group();
  18. var innerLightningHolder = weatherContainer1.group();
  19. var leafMask = outerSVG.rect();
  20. var leaf = Snap.select('#leaf');
  21. var sun = Snap.select('#sun');
  22. var sunburst = Snap.select('#sunburst');
  23. var outerSplashHolder = outerSVG.group();
  24. var outerLeafHolder = outerSVG.group();
  25. var outerSnowHolder = outerSVG.group();
  26.  
  27. var lightningTimeout;
  28.  
  29. // Set mask for leaf holder
  30.  
  31. outerLeafHolder.attr({
  32. 'clip-path': leafMask
  33. });
  34.  
  35. // create sizes object, we update this later
  36.  
  37. var sizes = {
  38. container: {width: 0, height: 0},
  39. card: {width: 0, height: 0}
  40. }
  41.  
  42. // grab cloud groups
  43.  
  44. var clouds = [
  45. {group: Snap.select('#cloud1')},
  46. {group: Snap.select('#cloud2')},
  47. {group: Snap.select('#cloud3')}
  48. ]
  49.  
  50. // set weather types ☁️ 🌬 🌧 ⛈ ☀️
  51.  
  52. var weather = [
  53. { type: 'snow', name: 'Snow'},
  54. { type: 'wind', name: 'Windy'},
  55. { type: 'rain', name: 'Rain'},
  56. { type: 'thunder', name: 'Storms'},
  57. { type: 'sun', name: 'Sunny'}
  58. ];
  59.  
  60. // 🛠 app settings
  61. // in an object so the values can be animated in tweenmax
  62.  
  63. var settings = {
  64. windSpeed: 2,
  65. rainCount: 0,
  66. leafCount: 0,
  67. snowCount: 0,
  68. cloudHeight: 100,
  69. cloudSpace: 30,
  70. cloudArch: 50,
  71. renewCheck: 10,
  72. splashBounce: 80
  73. };
  74.  
  75. var tickCount = 0;
  76. var rain = [];
  77. var leafs = [];
  78. var snow = [];
  79.  
  80. // ⚙ initialize app
  81.  
  82. init();
  83.  
  84. // 👁 watch for window resize
  85.  
  86. $(window).resize(onResize);
  87.  
  88. // 🏃 start animations
  89.  
  90. requestAnimationFrame(tick);
  91.  
  92. function init()
  93. {
  94. onResize();
  95. // 🖱 bind weather menu buttons
  96. for(var i = 0; i < weather.length; i++)
  97. {
  98. var w = weather[i];
  99. var b = $('#button-' + w.type);
  100. w.button = b;
  101. b.bind('click', w, changeWeather);
  102. }
  103. // ☁️ draw clouds
  104. for(var i = 0; i < clouds.length; i++)
  105. {
  106. clouds[i].offset = Math.random() * sizes.card.width;
  107. drawCloud(clouds[i], i);
  108. }
  109. // ☀️ set initial weather
  110. TweenMax.set(sunburst.node, {opacity: 0})
  111. changeWeather(weather[0]);
  112. }
  113.  
  114. function onResize()
  115. {
  116. // 📏 grab window and card sizes
  117. sizes.container.width = container.width();
  118. sizes.container.height = container.height();
  119. sizes.card.width = card.width();
  120. sizes.card.height = card.height();
  121. sizes.card.offset = card.offset();
  122. // 📐 update svg sizes
  123. innerSVG.attr({
  124. width: sizes.card.width,
  125. height: sizes.card.height
  126. })
  127. outerSVG.attr({
  128. width: sizes.container.width,
  129. height: sizes.container.height
  130. })
  131. backSVG.attr({
  132. width: sizes.container.width,
  133. height: sizes.container.height
  134. })
  135. TweenMax.set(sunburst.node, {transformOrigin:"50% 50%", x: sizes.container.width / 2, y: (sizes.card.height/2) + sizes.card.offset.top});
  136. TweenMax.fromTo(sunburst.node, 20, {rotation: 0}, {rotation: 360, repeat: -1, ease: Power0.easeInOut})
  137. // 🍃 The leaf mask is for the leafs that float out of the
  138. // container, it is full window height and starts on the left
  139. // inline with the card
  140. leafMask.attr({x: sizes.card.offset.left, y: 0, width: sizes.container.width - sizes.card.offset.left, height: sizes.container.height});
  141. }
  142.  
  143. function drawCloud(cloud, i)
  144. {
  145. /*
  146. ☁️ We want to create a shape thats loopable but that can also
  147. be animated in and out. So we use Snap SVG to draw a shape
  148. with 4 sections. The 2 ends and 2 arches the same width as
  149. the card. So the final shape is about 4 x the width of the
  150. card.
  151. */
  152. var space = settings.cloudSpace * i;
  153. var height = space + settings.cloudHeight;
  154. var arch = height + settings.cloudArch + (Math.random() * settings.cloudArch);
  155. var width = sizes.card.width;
  156. var points = [];
  157. points.push('M' + [-(width), 0].join(','));
  158. points.push([width, 0].join(','));
  159. points.push('Q' + [width * 2, height / 2].join(','));
  160. points.push([width, height].join(','));
  161. points.push('Q' + [width * 0.5, arch].join(','));
  162. points.push([0, height].join(','));
  163. points.push('Q' + [width * -0.5, arch].join(','));
  164. points.push([-width, height].join(','));
  165. points.push('Q' + [- (width * 2), height/2].join(','));
  166. points.push([-(width), 0].join(','));
  167. var path = points.join(' ');
  168. if(!cloud.path) cloud.path = cloud.group.path();
  169. cloud.path.animate({
  170. d: path
  171. }, 0)
  172. }
  173.  
  174. function makeRain()
  175. {
  176. // 💧 This is where we draw one drop of rain
  177. // first we set the line width of the line, we use this
  178. // to dictate which svg group it'll be added to and
  179. // whether it'll generate a splash
  180. var lineWidth = Math.random() * 3;
  181. // ⛈ line length is made longer for stormy weather
  182. var lineLength = currentWeather.type == 'thunder' ? 35 : 14;
  183. // Start the drop at a random point at the top but leaving
  184. // a 20px margin
  185. var x = Math.random() * (sizes.card.width - 40) + 20;
  186. // Draw the line
  187. var line = this['innerRainHolder' + (3 - Math.floor(lineWidth))].path('M0,0 0,' + lineLength).attr({
  188. fill: 'none',
  189. stroke: currentWeather.type == 'thunder' ? '#777' : '#0000ff',
  190. strokeWidth: lineWidth
  191. });
  192. // add the line to an array to we can keep track of how
  193. // many there are.
  194. rain.push(line);
  195. // Start the falling animation, calls onRainEnd when the
  196. // animation finishes.
  197. TweenMax.fromTo(line.node, 1, {x: x, y: 0- lineLength}, {delay: Math.random(), y: sizes.card.height, ease: Power2.easeIn, onComplete: onRainEnd, onCompleteParams: [line, lineWidth, x, currentWeather.type]});
  198. }
  199.  
  200. function onRainEnd(line, width, x, type)
  201. {
  202. // first lets get rid of the drop of rain 💧
  203. line.remove();
  204. line = null;
  205. // We also remove it from the array
  206. for(var i in rain)
  207. {
  208. if(!rain[i].paper) rain.splice(i, 1);
  209. }
  210. // If there is less rain than the rainCount we should
  211. // make more.
  212. if(rain.length < settings.rainCount)
  213. {
  214. makeRain();
  215. // 💦 If the line width was more than 2 we also create a
  216. // splash. This way it looks like the closer (bigger)
  217. // drops hit the the edge of the card
  218. if(width > 2) makeSplash(x, type);
  219. }
  220. }
  221.  
  222. function makeSplash(x, type)
  223. {
  224. // 💦 The splash is a single line added to the outer svg.
  225.  
  226. // The splashLength is how long the animated line will be
  227. var splashLength = type == 'thunder' ? 30 : 20;
  228. // splashBounce is the max height the line will curve up
  229. // before falling
  230. var splashBounce = type == 'thunder' ? 120 : 100;
  231. // this sets how far down the line can fall
  232. var splashDistance = 80;
  233. // because the storm rain is longer we want the animation
  234. // to last slighly longer so the overall speed is roughly
  235. // the same for both
  236. var speed = type == 'thunder' ? 0.7 : 0.5;
  237. // Set a random splash up amount based on the max splash bounce
  238. var splashUp = 0 - (Math.random() * splashBounce);
  239. // Sets the end x position, and in turn defines the splash direction
  240. var randomX = ((Math.random() * splashDistance) - (splashDistance / 2));
  241. // Now we put the 3 line coordinates into an array.
  242. var points = [];
  243. points.push('M' + 0 + ',' + 0);
  244. points.push('Q' + randomX + ',' + splashUp);
  245. points.push((randomX * 2) + ',' + splashDistance);
  246. // Draw the line with Snap SVG
  247. var splash = outerSplashHolder.path(points.join(' ')).attr({
  248. fill: "none",
  249. stroke: type == 'thunder' ? '#777' : '#0000ff',
  250. strokeWidth: 1
  251. });
  252. // We animate the dasharray to have the line travel along the path
  253. var pathLength = Snap.path.getTotalLength(splash);
  254. var xOffset = sizes.card.offset.left;//(sizes.container.width - sizes.card.width) / 2
  255. var yOffset = sizes.card.offset.top + sizes.card.height;
  256. splash.node.style.strokeDasharray = splashLength + ' ' + pathLength;
  257. // Start the splash animation, calling onSplashComplete when finished
  258. TweenMax.fromTo(splash.node, speed, {strokeWidth: 2, y: yOffset, x: xOffset + 20 + x, opacity: 1, strokeDashoffset: splashLength}, {strokeWidth: 0, strokeDashoffset: - pathLength, opacity: 1, onComplete: onSplashComplete, onCompleteParams: [splash], ease: SlowMo.ease.config(0.4, 0.1, false)})
  259. }
  260.  
  261. function onSplashComplete(splash)
  262. {
  263. // 💦 The splash has finished animating, we need to get rid of it
  264. splash.remove();
  265. splash = null;
  266. }
  267.  
  268. function makeLeaf()
  269. {
  270. var scale = 0.5 + (Math.random() * 0.5);
  271. var newLeaf;
  272. var areaY = sizes.card.height/2;
  273. var y = areaY + (Math.random() * areaY);
  274. var endY = y - ((Math.random() * (areaY * 2)) - areaY)
  275. var x;
  276. var endX;
  277. var colors = ['#76993E', '#4A5E23', '#6D632F'];
  278. var color = colors[Math.floor(Math.random() * colors.length)];
  279. var xBezier;
  280. if(scale > 0.8)
  281. {
  282. newLeaf = leaf.clone().appendTo(outerLeafHolder)
  283. .attr({
  284. fill: color
  285. })
  286. y = y + sizes.card.offset.top / 2;
  287. endY = endY + sizes.card.offset.top / 2;
  288. x = sizes.card.offset.left - 100;
  289. xBezier = x + (sizes.container.width - sizes.card.offset.left) / 2;
  290. endX = sizes.container.width + 50;
  291. }
  292. else
  293. {
  294. newLeaf = leaf.clone().appendTo(innerLeafHolder)
  295. .attr({
  296. fill: color
  297. })
  298. x = -100;
  299. xBezier = sizes.card.width / 2;
  300. endX = sizes.card.width + 50;
  301. }
  302. leafs.push(newLeaf);
  303. var bezier = [{x:x, y:y}, {x: xBezier, y:(Math.random() * endY) + (endY / 3)}, {x: endX, y:endY}]
  304. TweenMax.fromTo(newLeaf.node, 2, {rotation: Math.random()* 180, x: x, y: y, scale:scale}, {rotation: Math.random()* 360, bezier: bezier, onComplete: onLeafEnd, onCompleteParams: [newLeaf], ease: Power0.easeIn})
  305. }
  306.  
  307. function onLeafEnd(leaf)
  308. {
  309. leaf.remove();
  310. leaf = null;
  311. for(var i in leafs)
  312. {
  313. if(!leafs[i].paper) leafs.splice(i, 1);
  314. }
  315. if(leafs.length < settings.leafCount)
  316. {
  317. makeLeaf();
  318. }
  319. }
  320.  
  321. function makeSnow()
  322. {
  323. var scale = 0.5 + (Math.random() * 0.5);
  324. var newSnow;
  325. var x = 20 + (Math.random() * (sizes.card.width - 40));
  326. var endX; // = x - ((Math.random() * (areaX * 2)) - areaX)
  327. var y = -10;
  328. var endY;
  329. if(scale > 0.8)
  330. {
  331. newSnow = outerSnowHolder.circle(0, 0, 5)
  332. .attr({
  333. fill: 'white'
  334. })
  335. endY = sizes.container.height + 10;
  336. y = sizes.card.offset.top + settings.cloudHeight;
  337. x = x + sizes.card.offset.left;
  338. //xBezier = x + (sizes.container.width - sizes.card.offset.left) / 2;
  339. //endX = sizes.container.width + 50;
  340. }
  341. else
  342. {
  343. newSnow = innerSnowHolder.circle(0, 0 ,5)
  344. .attr({
  345. fill: 'white'
  346. })
  347. endY = sizes.card.height + 10;
  348. //x = -100;
  349. //xBezier = sizes.card.width / 2;
  350. //endX = sizes.card.width + 50;
  351. }
  352. snow.push(newSnow);
  353. TweenMax.fromTo(newSnow.node, 3 + (Math.random() * 5), {x: x, y: y}, {y: endY, onComplete: onSnowEnd, onCompleteParams: [newSnow], ease: Power0.easeIn})
  354. TweenMax.fromTo(newSnow.node, 1,{scale: 0}, {scale: scale, ease: Power1.easeInOut})
  355. TweenMax.to(newSnow.node, 3, {x: x+((Math.random() * 150)-75), repeat: -1, yoyo: true, ease: Power1.easeInOut})
  356. }
  357.  
  358. function onSnowEnd(flake)
  359. {
  360. flake.remove();
  361. flake = null;
  362. for(var i in snow)
  363. {
  364. if(!snow[i].paper) snow.splice(i, 1);
  365. }
  366. if(snow.length < settings.snowCount)
  367. {
  368. makeSnow();
  369. }
  370. }
  371.  
  372. function tick()
  373. {
  374. tickCount++;
  375. var check = tickCount % settings.renewCheck;
  376. if(check)
  377. {
  378. if(rain.length < settings.rainCount) makeRain();
  379. if(leafs.length < settings.leafCount) makeLeaf();
  380. if(snow.length < settings.snowCount) makeSnow();
  381. }
  382. for(var i = 0; i < clouds.length; i++)
  383. {
  384. if(currentWeather.type == 'sun')
  385. {
  386. if(clouds[i].offset > -(sizes.card.width * 1.5)) clouds[i].offset += settings.windSpeed / (i + 1);
  387. if(clouds[i].offset > sizes.card.width * 2.5) clouds[i].offset = -(sizes.card.width * 1.5);
  388. clouds[i].group.transform('t' + clouds[i].offset + ',' + 0);
  389. }
  390. else
  391. {
  392. clouds[i].offset += settings.windSpeed / (i + 1);
  393. if(clouds[i].offset > sizes.card.width) clouds[i].offset = 0 + (clouds[i].offset - sizes.card.width);
  394. clouds[i].group.transform('t' + clouds[i].offset + ',' + 0);
  395. }
  396. }
  397. requestAnimationFrame(tick);
  398. }
  399.  
  400. function reset()
  401. {
  402. for(var i = 0; i < weather.length; i++)
  403. {
  404. container.removeClass(weather[i].type);
  405. weather[i].button.removeClass('active');
  406. }
  407. }
  408.  
  409. function updateSummaryText()
  410. {
  411. summary.html(currentWeather.name);
  412. TweenMax.fromTo(summary, 1.5, {x: 30}, {opacity: 1, x: 0, ease: Power4.easeOut});
  413. }
  414.  
  415. function startLightningTimer()
  416. {
  417. if(lightningTimeout) clearTimeout(lightningTimeout);
  418. if(currentWeather.type == 'thunder')
  419. {
  420. lightningTimeout = setTimeout(lightning, Math.random()*6000);
  421. }
  422. }
  423.  
  424. function lightning()
  425. {
  426. startLightningTimer();
  427. TweenMax.fromTo(card, 0.75, {y: -30}, {y:0, ease:Elastic.easeOut});
  428. var pathX = 30 + Math.random() * (sizes.card.width - 60);
  429. var yOffset = 20;
  430. var steps = 20;
  431. var points = [pathX + ',0'];
  432. for(var i = 0; i < steps; i++)
  433. {
  434. var x = pathX + (Math.random() * yOffset - (yOffset / 2));
  435. var y = (sizes.card.height / steps) * (i + 1)
  436. points.push(x + ',' + y);
  437. }
  438. var strike = weatherContainer1.path('M' + points.join(' '))
  439. .attr({
  440. fill: 'none',
  441. stroke: 'white',
  442. strokeWidth: 2 + Math.random()
  443. })
  444. TweenMax.to(strike.node, 1, {opacity: 0, ease:Power4.easeOut, onComplete: function(){ strike.remove(); strike = null}})
  445. }
  446.  
  447. function changeWeather(weather)
  448. {
  449. if(weather.data) weather = weather.data;
  450. reset();
  451. currentWeather = weather;
  452. TweenMax.killTweensOf(summary);
  453. TweenMax.to(summary, 1, {opacity: 0, x: -30, onComplete: updateSummaryText, ease: Power4.easeIn})
  454. container.addClass(weather.type);
  455. weather.button.addClass('active');
  456. // windSpeed
  457. switch(weather.type)
  458. {
  459. case 'wind':
  460. TweenMax.to(settings, 3, {windSpeed: 3, ease: Power2.easeInOut});
  461. break;
  462. case 'sun':
  463. TweenMax.to(settings, 3, {windSpeed: 20, ease: Power2.easeInOut});
  464. break;
  465. default:
  466. TweenMax.to(settings, 3, {windSpeed: 0.5, ease: Power2.easeOut});
  467. break;
  468. }
  469. // rainCount
  470. switch(weather.type)
  471. {
  472. case 'rain':
  473. TweenMax.to(settings, 3, {rainCount: 10, ease: Power2.easeInOut});
  474. break;
  475. case 'thunder':
  476. TweenMax.to(settings, 3, {rainCount: 60, ease: Power2.easeInOut});
  477. break;
  478. default:
  479. TweenMax.to(settings, 1, {rainCount: 0, ease: Power2.easeOut});
  480. break;
  481. }
  482. // leafCount
  483. switch(weather.type)
  484. {
  485. case 'wind':
  486. TweenMax.to(settings, 3, {leafCount: 5, ease: Power2.easeInOut});
  487. break;
  488. default:
  489. TweenMax.to(settings, 1, {leafCount: 0, ease: Power2.easeOut});
  490. break;
  491. }
  492. // snowCount
  493. switch(weather.type)
  494. {
  495. case 'snow':
  496. TweenMax.to(settings, 3, {snowCount: 40, ease: Power2.easeInOut});
  497. break;
  498. default:
  499. TweenMax.to(settings, 1, {snowCount: 0, ease: Power2.easeOut});
  500. break;
  501. }
  502. // sun position
  503. switch(weather.type)
  504. {
  505. case 'sun':
  506. TweenMax.to(sun.node, 4, {x: sizes.card.width / 2, y: sizes.card.height / 2, ease: Power2.easeInOut});
  507. TweenMax.to(sunburst.node, 4, {scale: 1, opacity: 0.8, y: (sizes.card.height/2) + (sizes.card.offset.top), ease: Power2.easeInOut});
  508. break;
  509. default:
  510. TweenMax.to(sun.node, 2, {x: sizes.card.width / 2, y: -100, leafCount: 0, ease: Power2.easeInOut});
  511. TweenMax.to(sunburst.node, 2, {scale: 0.4, opacity: 0, y: (sizes.container.height/2)-50, ease: Power2.easeInOut});
  512. break;
  513. }
  514. // lightning
  515. startLightningTimer();
  516. }

That’s it! You now have a weather card with animated weather icons on your website. If you have any questions or suggestions, feel free to comment below.

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