5 H ere's T hat M agical L anguage 5

More Magic Moments

HTML5

Taking web development to the next level.

  • Fast. Secure. Responsive. Interactive.

  • Stunningly beautiful. Lot of support for animation and graphics.

  • Provides ways to create as complex apps as desktop allows.

  • Bridges the gap between offline and online, 2D and 3D, server and client.

  • Much easier development.

  • Browsers more secure than ever.

Magic Moment 1


The Rainbow Spiral

Number of figures:    
Angle of rotation:       

The Rainbow Spiral - explained.

CSS3 gradients, CSS3 transforms.

<style>
    div { 
        background-image: linear-gradient(left top, red 0%, orange 16%, yellow 33%, 
            green 50%, blue 67%, indigo 84%, violet 100%); 
        transform: rotate(20deg);
    }
</style>

Magic Moment 2


Me, Me, Me.

grayscale: 0   

sepia: 0   

saturate: 1   

hue-rotate: 0deg   

invert: 0   

opacity: 1   

brightness: 0   

contrast: 1   

blur: 0px   

Me, Me, Me - realized.

getUserMedia

<video autoplay width="600" height="480" src=""></video>
<canvas width="600" height="480" style="display:none;" ></canvas>
<img src="" width="100" height="80" ></img>
navigator.getUserMedia = navigator.webkitGetUserMedia;
window.URL = window.webkitURL;

function switchOnCamera() {
    navigator.getUserMedia({video: true;}, successFn, failureFn);
}

function successFn(localMediaStream) {
	var video = document.querySelector("video");
	video.src = window.URL.createObjectURL(localMediaStream);
}

Me, Me, Me - realized.

CSS3 filters

 video {
   -webkit-filter: 
        grayscale(0.4)
        sepia(0.6)
        saturate(2.3)
        hue-rotate(90deg)
        invert(0.1)
        opacity(1) 
        brightness(0)
        contrast(1) 
        blur(0)
        drop-shadow(10px 10px 10px #008888);
}
 Apply filters 

Me, Me, Me - realized.

canvas

function takePhoto() {
    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, 600, 450);
    ctx.drawImage(document.querySelector("video"), 0, 0);
    document.querySelector('img').src = canvas.toDataURL('image/png');
}

Magic Moment 3


The Rotating Cube

HTML5 Rocks!
 opaque
Use keys 1 to 6 to rotate the cube.

The Rotating Cube - unfolded.

step 1: Get the HTML and basic CSS right.

<div id="cubeOuter" class="cubeOuter">
    <div class="cubeFace cubeFaceA"> 1 </div>
    <!-- other five faces go here -->
</div>
.cubeFace {
    border: 2px solid black; border-radius: 5px; height: 100%; width: 100%;
    position: absolute; left: 0px; top: 0px;
}
.cubeFaceA {
    background: rgba(255, 0, 0, 0.5);
}
/* Other five styles go here. */
1
2
3
4
5
6

The Rotating Cube - unfolded.

step 2: Get the rotations right.

.cubeFaceA { -webkit-transform: rotateY(0deg); }
.cubeFaceB { -webkit-transform: rotateY(-90deg); }
.cubeFaceC { -webkit-transform: rotateY(180deg); }
.cubeFaceD { -webkit-transform: rotateY(90deg); }
.cubeFaceE { -webkit-transform: rotateX(90deg); }
.cubeFaceF { -webkit-transform: rotateX(-90deg); }
1
2
3
4
5
6
1
2
3
4
5
6
try mouseover on each figure.

The Rotating Cube - unfolded.

step 3: Get the perspective right.

.cubeOuter {
    -webkit-perspective: 1200;
    -webkit-perspective-origin: 300px 200px;
    -webkit-transition: -webkit-transform 2s;
}
.cubeFaceA { -webkit-transform: rotateY(0deg) translateZ(150px); }
.cubeFaceB { -webkit-transform: rotateY(-90deg) translateZ(150px); }
.cubeFaceC { -webkit-transform: rotateY(180deg) translateZ(150px); }
.cubeFaceD { -webkit-transform: rotateY(90deg) translateZ(150px); }
.cubeFaceE { -webkit-transform: rotateX(90deg) translateZ(150px); }
.cubeFaceF { -webkit-transform: rotateY(-90deg) translateZ(150px); }
1
2
3
4
5
6
try mouseover.
non-commutative transformations
use perspective.
transform origin.

The Rotating Cube - unfolded.

step 4: Get the JavaScript right.

var rotateX = 0, rotateY = 0, rotateZ = 0, diff = 90;
function rotateCube(e) { 
    switch(e.keyCode) {
        case 49: rotateY -= diff; break;
        case 50: rotateY += diff; break;
        case 51: rotateX += diff; break;
        case 52: rotateX -= diff; break;
        case 53: rotateZ += diff; break;
        case 54: rotateZ -= diff; break;
    }
    var rX = "rotateX(" + rotateX + "deg) "; 
    var rY = "rotateY(" + rotateY + "deg) ";
    var rZ = "rotateZ(" + rotateZ + "deg) ";
    $("cubeOuter").style.webkitTransform = rX + rY + rZ;
}
document.addEventListener('keypress', rotateCube, false);

Magic Moment 4


You Are Here!

You Are Here - grounded.

navigator.geoLocation, google Maps APIs

navigator.geolocation.getCurrentPosition(
    function(position) { // Success handler.
        var acc = position.coords.accuracy;
        var lat = position.coords.latitude;
        var log = position.coords.longitude;
        var geoMap = document.getElementById("mapDiv");
        var map = new google.maps.Map(geoMap, { });
        var latLng = new google.maps.LatLng(lat, log);
        new google.maps.Marker({position: latLng, map: map});
        map.setCenter(latLng);
        map.setZoom(15);
    },
    function(evt) {  // Error handler.
    }
);

Magic Moment 5


Bend It Like Beckham

Works only if your laptop has accelerometer. Try bending the laptop.

Bend It Like Beckham - straightened.

device orientation, CSS3 transforms.


window.addEventListener('deviceorientation', function(event) {
    var alpha = event.alpha; // direction.
    var beta = event.beta, // front-to-back tit.
    var gamma = event.gamma; // left-to-right tilt.
    var layers = document.querySelectorAll('.layer');
    for (var i = 0, zindex = 1, elem; elem = layers[i]; ++i, ++zindex) {
        var x = Math.round(1.5 * gamma * zindex);
        var y = Math.round(1.5 * beta * zindex);
        elem.style.left = x.toString() + 'px';
        elem.style.top = y.toString() + 'px';
        elem.style.webkitTransform = 
            'rotateY(' + (-2.0 * gamma) + 'deg) rotateX(' + (-2.0 * beta) + 'deg)';
    }
}, false);

Magic Moment 6


The Photo Wheel

The Photo Wheel- pinned.

Transformation and Animation

@-webkit-keyframes rotate {
    from { -webkit-transform: rotateY(0deg); }
    to { -webkit-transform: rotateY(-360deg); }
}
.picture {
    -webkit-animation: rotate 6s linear 0s infinite normal;
    -webkit-transform-origin: 0px 0px;
    padding-left: 50px;
    border: 1px solid #ccc;
    background: rgba(255,255,255,0.2);
    box-shadow: inset 0 0 20px rgba(0,0,0,0.3);
}

The Photo Wheel- pinned.

Drag and Drop

<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event);" />
<img src="images/sky.jpg" draggable="true" ondragstart="drag(event);" />
function allowDrop(ev) { 
    ev.preventDefault(); 
}
function drag(ev) { 
    ev.dataTransfer.setData("Text",ev.target.id); 
}
function drop(ev) {
    ev.preventDefault();
    var data=ev.dataTransfer.getData("Text");
    ev.target.appendChild(document.getElementById(data));
}

The Photo Wheel - pinned.

Network Detection

var photoGroup = document.querySelector(".photoGroup");
setInterval(function () {
    if (navigator.onLine) {
        wheelElem.style.webkitAnimationPlayState = "running";
    } else { 
        wheelElem.style.webkitAnimationPlayState = "paused";
    }
}, 250);	

The Photo Wheel - pinned.

History API

function saveState(ev) {
    var imageNodes = document.querySelectorAll(".photoGroup img");
    var imageIds = getCurrentImageIds();
    var url = window.location.pathname + "#d=" + imageIds;
    history.pushState(null, null, url);
}

window.addEventListener('popstate', function(e) {
    var d = window.location.hash.split("=")[1];
    setImages(d);
});

Magic Moment 7


The Bouncing Ball

Source:  http://billmill.org/static/canvastutorial/

The Bouncing Ball - caught.

Step 1: Draw the individual components.

<canvas id="canvas" width="800" height="500"></canvas>
function initCanvasDemo() {
    ctx = $('canvas').getContext("2d");
}
function circle(x, y, r, color) {
    ctx.beginPath();
    ctx.arc(x, y, r, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fillStyle = color; ctx.fill();
} 
function rect(x, y, w, h, color) {
    ctx.beginPath(); ctx.rect(x,y,w,h); ctx.closePath(); 
    ctx.fillStyle = color; ctx.fill(); 
}

The Bouncing Ball - caught.

Step 2: Add motion to the ball.

function draw() {
    clear("#000000");
    circle(x, y, 10);
    if (x + dx > canvasWidth || x + dx < 0)  dx = -dx;
    if (y + dy > canvasHeight || y + dy < 0) dy = -dy;
    x += dx;
    y += dy;
}
function clear(backColor) {
    ctx.fillStyle = backColor;
    ctx.clearRect(0, 0, canvasWidth, canvasHeight);
    ctx.beginPath(); ctx.rect(0,0,canvasWidth,canvasHeight); 
    ctx.closePath(); ctx.fill();
}
setInterval(draw, 10);

The Bouncing Ball - caught.

Step 3: Restrict bouncing from the handle.

function draw() {
    clear("#000000"); circle(x, y, 10);
    if (x + dx > canvasWidth || x + dx < 0)  dx = -dx;
    if (y + dy > canvasHeight || y + dy < 0)  dy = -dy;
    // Bounce off the ball only on colliding with the handle.
    if (x > handleX && x < handleX + handleW)  dy = -dy;
    else clearInterval(intervalId);
    x += dx; y += dy;
}
function onMouseMove(evt) {
  if (evt.pageX > canvasMinX && evt.pageX < canvasMaxX) {
    handleX = evt.pageX - canvasMinX;
  }
}
document.addEventListener("mousemove", onMouseMove, false);

Magic Moment 8


HTM5 Piano

HTML5 Piano - cracked.

The audio header

var header = new Uint8Array([
    0x52,0x49,0x46,0x46, // "RIFF"
    0, 0, 0, 0,          // put total size here
    0x57,0x41,0x56,0x45, // "WAVE"
    0x66,0x6d,0x74,0x20, // "fmt "
    16,0,0,0,            // size of the following
    1, 0,                // PCM format
    1, 0,                // Mono: 1 channel
    0x44,0xAC,0,0,       // 44,100 samples per second
    0x88,0x58,0x01,0,    // byte rate: two bytes per sample
    2, 0,                // aligned on every two bytes
    16, 0,               // 16 bits per sample
    0x64,0x61,0x74,0x61, // "data"
    0, 0, 0, 0           // put number of samples here
]).buffer;  // Note: we just want the ArrayBuffer.

HTML5 Piano - cracked.

Audio synthesis

function makeWave(samples) {
    var bb = new WebKitBlobBuilder();
    var dv = new DataView(header);
    dv.setInt32(4, 36 + samples.length, true);
    dv.setInt32(40, samples.length, true);
    bb.append(header);
    bb.append(samples.buffer);
    return bb.getBlob('audio/wav');
}

HTML5 Piano - cracked.

Playing the audio

function playNote(frequency, duration) {
    var samplespercycle = 44100 / frequency;
    var samples = new Uint16Array(44100 * duration);
    var da = 2 * Math.PI / samplespercycle;
    for (var i = 0, a = 0; i < samples.length; i++, a += da) {
        samples[i] = Math.floor(Math.sin(a) * 32768);
    }
    var blob = makeWave(samples);
    var url = window.webkitURL.createObjectURL(blob);
    var player = new Audio(url);
    player.play();
    player.addEventListener('ended', 
        function(e) {window.webkitURL.revokeObjectURL(url);}, false);
}
Frequency:     URL:  

Magic Moment 9


HTML5 Terminal

source:  http://www.htmlfivewow.com/demos/terminal/terminal.html

HTML5 Terminal - demystified.

requestFileSystem, getFile, fileReader, fileWriter


// Getting handle to the file system.
window.requestFileSystem(window.TEMPORARY, 5*1024*1024 /*5MB*/, 
    function (fs) { ... }, errorHandler);
// Creating a file.
fs.root.getFile('log.txt', {create: true, exclusive: true}, 
    function(fileEntry) { .. }, errorHandler);
// Reading a file.
fileEntry.file(function(file) { ...}, errorHandler};
// Writing or appending to a file.
fileEntry.createWriter(function(fileWriter) { ....}, errorHandler);
// Removing a file.
fileEntry.remove(function() { ..}, errorHandler);

Magic Moment 10


The WebGL BookCase

Wrapping it all

It's only the beginning...

Some more demos

..that will make you say 'wow'!

Dive Deeper

...if you are searching for pearls.