Creating Animated Moving Clouds using HTML5

Today I have prepared you something really entertaining. Of course, we implement it with our favorite html5. This work will show you how to create a beautiful flying clouds across the sky. In the implementation, I decided to use an additional library: https://github.com/mrdoob/three.js

Here are our demo and downloadable package:

Live Demo
download in package

Ok, download the source files and lets start coding !


Step 1. HTML

Here are html code of our clouds page

index.html

01 <!DOCTYPE html>
02 <html lang="en" >
03     <head>
04         <meta charset="utf-8" />
05         <title>HTML5 clouds | Script Tutorials</title>
06         <link href="css/main.css" rel="stylesheet" type="text/css" />
07         <script src="js/ThreeWebGL.js"></script>
08         <script src="js/ThreeExtras.js"></script>
09     </head>
10     <body>
11         <script id="vs" type="x-shader/x-vertex">
12             varying vec2 vUv;
13             void main() {
14                 vUv = uv;
15                 gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
16             }
17         </script>
18         <script id="fs" type="x-shader/x-fragment">
19             uniform sampler2D map;
20             uniform vec3 fogColor;
21             uniform float fogNear;
22             uniform float fogFar;
23             varying vec2 vUv;
24             void main() {
25                 float depth = gl_FragCoord.z / gl_FragCoord.w;
26                 float fogFactor = smoothstep( fogNear, fogFar, depth );
27                 gl_FragColor = texture2D( map, vUv );
28                 gl_FragColor.w *= pow( gl_FragCoord.z, 20.0 );
29                 gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );
30             }
31         </script>
32
33         <div class="container">
34             <canvas id="panel" width="10" height="1"></canvas>
35         </div>
36         <script type="text/javascript" src="js/script.js"></script>
37         <footer>
38             <h2>HTML5 clouds</h2>
39             <a href="http://www.script-tutorials.com/html5-clouds/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
40         </footer>
41     </body>
42 </html>

Step 2. CSS

Here are used CSS styles

css/main.css

01 *{
02     margin:0;
03     padding:0;
04 }
05 body {
06     color:#fff;
07     font:14px/1.3 Arial,sans-serif;
08     background-imageurl(../images/sky.jpg);
09 }
10 footer {
11     background-color:#212121;
12     bottom:0;
13     box-shadow: 0 -1px 2px #111111;
14     display:block;
15     height:70px;
16     left:0;
17     position:fixed;
18     width:100%;
19     z-index:100;
20 }
21 footer h2{
22     font-size:22px;
23     font-weight:normal;
24     left:50%;
25     margin-left:-400px;
26     padding:22px 0;
27     position:absolute;
28     width:540px;
29 }
30 footer a.stuts,a.stuts:visited{
31     border:none;
32     text-decoration:none;
33     color:#fcfcfc;
34     font-size:14px;
35     left:50%;
36     line-height:31px;
37     margin:23px 0 0 110px;
38     position:absolute;
39     top:0;
40 }
41 footer .stuts span {
42     font-size:22px;
43     font-weight:bold;
44     margin-left:5px;
45 }

Step 3. JS

js/ThreeWebGL.js and js/ThreeExtras.js

This is our new service libraries (available in package)

js/script.js

001 // inner variables
002 var canvas, ctx;
003 var camera, scene, renderer, meshMaterial, mesh, geometry, i;
004 var mouseX = 0, mouseY = 0;
005 var startTime = new Date().getTime();
006 var windowHalfX = window.innerWidth / 2;
007 var windowHalfY = window.innerHeight / 2;
008
009 if (window.attachEvent) {
010     window.attachEvent('onload', main_init);
011 else {
012     if(window.onload) {
013         var curronload = window.onload;
014         var newonload = function() {
015             curronload();
016             main_init();
017         };
018         window.onload = newonload;
019     else {
020         window.onload = main_init;
021     }
022 }
023
024 function main_init() {
025
026     // creating canvas and context objects
027     canvas = document.getElementById('panel');
028     var ctx = canvas.getContext('2d');
029
030     // preparing camera
031     camera = new THREE.Camera(30, window.innerWidth / window.innerHeight, 1, 5000);
032     camera.position.z = 6000;
033
034     // preparing scene
035     scene = new THREE.Scene();
036
037     // preparing geometry
038     geometry = new THREE.Geometry();
039
040     // loading texture
041     var texture = THREE.ImageUtils.loadTexture('images/clouds.png');
042     texture.magFilter = THREE.LinearMipMapLinearFilter;
043     texture.minFilter = THREE.LinearMipMapLinearFilter;
044
045     // preparing fog
046     var fog = new THREE.Fog(0x251d32, - 100, 5000);
047
048     // preparing material
049     meshMaterial = new THREE.MeshShaderMaterial({
050         uniforms: {
051             'map': {type: 't', value:2, texture: texture},
052             'fogColor' : {type: 'c', value: fog.color},
053             'fogNear' : {type: 'f', value: fog.near},
054             'fogFar' : {type: 'f', value: fog.far},
055
056         },
057         vertexShader: document.getElementById('vs').textContent,
058         fragmentShader: document.getElementById('fs').textContent,
059         depthTest: false
060     });
061
062     // preparing planeMesh
063     var planeMesh = new THREE.Mesh(new THREE.PlaneGeometry(64, 64));
064     for (i = 0; i < 10000; i++) {
065         planeMesh.position.x = Math.random() * 1000 - 500;
066         planeMesh.position.y = - Math.random() * Math.random() * 200 - 15;
067         planeMesh.position.z = i;
068         planeMesh.rotation.z = Math.random() * Math.PI;
069         planeMesh.scale.x = planeMesh.scale.y = Math.random() * Math.random() * 1.5 + 0.5;
070
071         THREE.GeometryUtils.merge(geometry, planeMesh);
072     }
073
074     mesh = new THREE.Mesh(geometry, meshMaterial);
075     scene.addObject(mesh);
076
077     mesh = new THREE.Mesh(geometry, meshMaterial);
078     mesh.position.z = - 10000;
079     scene.addObject(mesh);
080
081     // preparing new renderer and drawing it
082     renderer = new THREE.WebGLRenderer({ antialias: false });
083     renderer.setSize(window.innerWidth, window.innerHeight);
084     document.body.appendChild(renderer.domElement);
085
086     // change positions by mouse
087     document.addEventListener('mousemove', onMousemove, false);
088
089     // change canvas size on resize
090     window.addEventListener('resize', onResize, false);
091
092     setInterval(drawScene, 30); // loop drawScene
093 }
094
095 function onMousemove(event) {
096     mouseX = (event.clientX - windowHalfX) * 0.3;
097     mouseY = (event.clientY - windowHalfY) * 0.2;
098 }
099
100 function onResize(event) {
101     camera.aspect = window.innerWidth / window.innerHeight;
102     camera.updateProjectionMatrix();
103     renderer.setSize(window.innerWidth, window.innerHeight);
104 }
105
106 function drawScene() {
107     position = ((new Date().getTime() - startTime) * 0.1) % 10000;
108
109     camera.position.x += mouseX * 0.01;
110     camera.position.y += - mouseY * 0.01;
111     camera.position.z = - position + 10000;
112
113     renderer.render(scene, camera);
114 }

Most of code will pretty easy for understanding – I have tried to comment this code as possible.