Preflight

Webkit
If using Google Chrome, you will likely need the Dev channel to see all of the functionality in this presentation. If you are using Safari, you will likely need a nightly build of WebKit in order to see all of the functionality in this presentation.
Mozilla
You are running a Mozilla browser. While such browsers generally have excellent support for HTML5 features, this presentation has only been tested using WebKit browsers such as Google Chrome or Safari. You should still be able to navigate the slides by using left/right arrow keys, but will currently see display errors with regard to the 3d rendering of the slides and some demo content.
Other browser
You are running a browser that has not been tested with this presentation. You may not be able to run some or all of the samples listed here. While we want to add support for as many browsers as possible, currently we only support WebKit-based browsers such as Google Chrome or Safari.
WebGL: available
WebGL: not supported
You will not be able to see the WebGL demos later in this slide deck.
Notification permission incorrect
You have granted permission for this page to show notifications. If you intended to demo the request permission functionality, you may want to clear this permission by clicking here and removing the permission.
Notification permission correct
No notification
Your browser does not support displaying notifications. Currently, only Google Chrome will support this functionality.
File APIs: available
File APIs are not supported
Your browser does not support one or more of the following APIs: File, FileList, FileReader.
File System API: available
File System API: not supported
Your browser does not support the File System API for reading/writing files and directories.
File System API: partial support
The File System API are available in your browser, but write access is unavailable.
Web Audio API: available
Web Audio API: not supported
Your browser does not support the Web Audio API. If using Google Chrome, you need Mac OSX and to enable the API in about:flags.
If things look good, press → to move on.
Welcome! (This field is for presenter notes and commentary.)
Press:
  • Space or ← / → to move around
  • Ctrl/Command / – or + to zoom in and out if slides don’t fit
  • N to show/hide speaker notes
  • H to highlight important elements in code snippets

HTML5 Showcase for Web Developers:
The Wow and the How

Eric Bidelman && Arne Roomann-Kurrik
Google I/O - May 11, 2011
10:45 - 11:45am

Watch the session

Who are these guys?

Eric Bidelman @ebidel

Arne Roomann-Kurrik @kurrik
One year ago...
Training for a better career in HTML...
  • Canvas Element
  • Audio Element
  • Video Element
  • Local Storage
  • Web SQL Database
  • Worker Threads
  • Drag and drop Events
  • Desktop Notifications
  • New CSS Styles
  • CSS Transforms
  • CSS Transitions
  • CSS Animations
  • Hotel / Restaurant Mgmt.
  • Web Fonts
  • Flexible Box Model

Or a specialized associate degree

  • Developing an HTML5 Paint Application
  • Accounting
http://bit.ly/html5io2010
Today we will...

Show you demos that will make you say wow

Demonstrate how you can use these features working together

All code is open sourced at http://html5wow.googlecode.com

Please give us feedback! http://goo.gl/ac8n7

Ask questions in Google Moderator: http://goo.gl/mod/XKDL

Today's agenda
File
Graphics
Audio

File

Binary Data in HTML5

http://www.flickr.com/photos/mcclanahoochie/5068845349
Binary data on the web is was painful!
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);

// Trick to pass bytes through unprocessed.
xhr.overrideMimeType('text/plain; charset=x-user-defined');

xhr.onreadystatechange = function(e) {
  if (this.readyState == 4 && this.status == 200) {
    var binStr = this.responseText;
    for (var i = 0, len = binStr.length; i < len; ++i) {
      var c = binStr.charCodeAt(i);
      //String.fromCharCode(c & 0xff)
      var byte = c & 0xff;  // byte at offset i
    }
  }
};

xhr.send();
HTML5 ♥ binary data

New features let you:

  • Import from the filesystem or the web.
  • Create new files from scratch.
  • Manipulate existing file data.
  • Store file data on the client.
  • Publish files back to the web.
Manipulate New data types
DataView
ArrayBuffer
Uint8Array
Uint16Array
Uint32Array
Int8Array
Int16Array
Int32Array
Float32Array
Import Publish Fetch binary file: new hotness
BlobBuilder is prefixed in Chrome 12+ as window.WebKitBlobBuilder().
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);

xhr.responseType = 'arraybuffer';

xhr.onload = function(e) {
  if (this.status == 200) {

    var uInt8Array = new Uint8Array(this.response); // Note: not xhr.responseText

    var byte3 = uInt8Array[4]; // byte at offset 4
  }
};

xhr.send();

File APIs

http://www.flickr.com/photos/daddo83/3406962115/
Import Getting file handles: File / FileList
Getting access to the native file system is easier. New capabilities yield more ways to get files in/out of your app. Easy import. Easy export.
<input type="file" id="files" accept="image/*" multiple>
document.querySelector('#files').onchange = function(e) {
  var files = e.target.files; // FileList of File objects.

  for (var i = 0, f; f = files[i]; ++i) {
    console.log(f.name, f.type, f.size,
                f.lastModifiedDate.toLocaleDateString());
  }
};

Import Directory upload
<input type="file" id="dir-select" webkitdirectory />
document.querySelector('#dir-select').onchange = function(e) {
  var out = [];
  for (var i = 0, f; f = e.target.files[i]; ++i) {
    out.push(f.webkitRelativePath);
  }
  document.querySelector('output'),textContent = out.join('/n');
};
Import Drag & drop
var reader = new FileReader();
reader.onload = function(e) {
  document.querySelector('img').src = e.target.result;
};

function onDrop(e) {
  reader.readAsDataURL(e.dataTransfer.files[0]);
};
Drag in image files from your desktop

DEMO: Photo Gallery

LAUNCH

Blueprint: Photo Gallery

Using files

http://www.flickr.com/photos/meddygarnet/4012204741/
Manipulate Reading file content ( FileReader )

Asynchronously read file content into memory:

var reader = new FileReader();

reader.readAsBinaryString(File | Blob);

reader.readAsText(File | Blob, opt_encoding /* default UTF-8 */);

reader.readAsDataURL(Blob | File);

reader.readAsArrayBuffer(Blob | File);

Reading byte ranges:

var blob = file.slice(startByte, stopByte, contentType);
reader.readAsBinaryString(blob);
Create Data URLs
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'data:text/css;base64,' +
            window.btoa('body { background: red; }');

document.head.appendChild(link);

Open text area

  • Pro: persistent URL. It is the content.
  • Pro: 1 less network request.
  • Con: 30% overhead.
Create Blob URLs
  • Chrome is prefixed with window.webkitURL.createObjectURL()
  • In Google Chrome, chrome://blob-internals/ will give you an overview of the Blob URLs that have been allocated for a given app.
window.URL.createObjectURL(File | Blob);
if (imgFile.type.match(/image.*/)) {
  var blobURL = window.URL.createObjectURL(imgFile);

  var img = document.createElement('img');
  img.src = blobURL; // blob:http://example.com/d8c2c85e-ab1b
  document.body.appendChild(img);

  window.URL.revokeObjectURL(img.src); // clean up.
}
  • Pro: temporary (and unique) URL handle to the content.
  • Pro: Use as src or href attributes.
  • Con: doesn't come for free. Use revokeObjectURL()!
Create Blob URL Example: Inline Web Workers
BlobBuilder is prefixed in Chrome 12+ as window.WebKitBlobBuilder().
<!DOCTYPE html>
<html>
  <body>
  <script type="javascript/worker">
    onmessage = function(e) {
      ...
    };
  </script>
  <script>
    var bb = new BlobBuilder();
    bb.append(
        document.querySelector('[type="javascript/worker"]').textContent);

    var worker = new Worker(window.URL.createObjectURL(bb.getBlob()));
    worker.onmessage = function(e) {
      ...
    };
    worker.postMessage({cmd: 'init'}); // Start the worker.
  </script>
</body>
</html>
Browser Support: File APIs
  • Opera announced partial support for the File APIs, FileReader, and Blobs.
  • IE 9 File API Lab

File System API

http://www.flickr.com/photos/christosnyc/87637818/
Store Opening the file system
  • If Chrome Web Store App: need to use unlimitedStorage manifest permission.
  • You also need the --allow-file-access-from-files flag to run this presentation from file://.
  • Prefixed in Chrome 12+: window.webkitRequestFileSystem
window.requestFileSystem(
  TEMPORARY,        // persistent vs. temporary storage
  1024 * 1024,      // size (bytes) of needed space
  initFs,           // success callback
  opt_errorHandler  // opt. error callback, denial of access
);
Store Fetching a file by name
function errorHandler(e) {
  switch (e.code) {
    case FileError.QUOTA_EXCEEDED_ERR:
      ...
    case FileError.NOT_FOUND_ERR:
      ...
  }
}
function initFs(fs) {

  fs.root.getFile('logFile.txt', {create: true}, function(fileEntry) {

    // fileEntry.isFile == true
    // fileEntry.name == 'logFile.txt'
    // fileEntry.fullPath == '/logFile.txt'

    // Get a File obj
    fileEntry.file(function(file) { ... }, errorHandler);

    // fileEntry.remove(function() {}, errorHandler);
    // fileEntry.moveTo(...);
    // fileEntry.copyTo(...);
    // fileEntry.getParent(function(dirEntry) {}, errorHandler);

  }, errorHandler);

}
Create Manipulate Terminal: Duplicating user-selected files
document.querySelector('#terminal').ondrop = function(e) {
  var files = e.dataTransfer.files;

  window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {

    Array.prototype.slice.call(files || [], 0).forEach(function(file, i) {
      fs.root.getFile(file.name, {create: true, exclusive: true}, function(fileEntry) {

        fileEntry.createWriter(function(fileWriter) {
          fileWriter.write(f); // Note: write() can take a File | Blob.
        }, errorHandler);

      }, errorHandler);
    });

  }, errorHandler);

};

DEMO: HTML5 Terminal

LAUNCH

Blueprint: HTML5 Terminal
(CRX-less web app docs)
Store 1, 2, 3, Ways to generate URLs to files
window.resolveLocalFileSystemURL is prefixed as window.webkitResolveLocalFileSystemURL in Chrome 12+.
  1. Blob URLs ( blob: )
  2. Data URLs ( data: )
  3. File System URLs ( filesystem: ) New
var img = document.createElement('img');

// filesystem:http://example.com/temporary/myfile.png
img.src = fileEntry.toURL();
document.body.appendChild(img);

Retrieve a file by its filesystem URL:

window.resolveLocalFileSystemURL(img.src, function(fileEntry) { ... });
Browser Support: File System API

Graphics

HTML5 ♥ graphics

New features let you:

  • Declare styles and animations to be rendered by the browser.
  • Script graphics for finer control.
  • Access low-level APIs for performance.

Declarative Options

http://www.flickr.com/photos/twicepix/681510321/
Declare Inline SVG
<svg viewBox="-10 -10 120 120" preserveAspectRatio="none">
  <defs><path id="svgPath"
          d="M 0,100
             C 0,0  40,0  50,0
             C 60,0 100,0 100,100 Z" /></defs>
  <use xlink:href="#svgPath" stroke="green" stroke-width="8"
       fill="yellow" />
</svg>
Declare The SVG DOM
<textPath method="align" spacing="auto"
          xlink:href="#svgTextPath">
  <tspan>Sometimes I have to put text on a path</tspan>
</textPath>
Sometimes I have to put text on a path
Declare CSS: Too much awesome to cover
text-shadow text-outline box-shadow border-radius gradient transform transition border-image font-face text-overflow
Declare Movement with CSS
@keyframes chromelogo-spin {
  from { transform: rotate(0); }
  to { transform: rotate(-2160deg); }
}
.chromelogo {
  animation: chromelogo-spin 12s infinite cubic-bezier(0.9, 0.1, 0.1, 0.9);
  background: url('chromelogo.png');
}
 
Declare Tweens
linear
ease-in
ease-out
ease-in-out
cubic-bezier(0.9, 0.1, 0.1, 0.9);
 
Declare 3D transforms in CSS
:any(.two, .three, .four) > span {
    transform-origin: 50% 0;    /* Rotate from top */
    transform: rotateX(45deg);
}

.three, .four {  transform: rotateY(60deg);     }
.four         {  transform-style: preserve-3d;  }
1
2
3
4
Declare The power of 3D CSS
.container { transform-style: preserve-3d;
             perspective: 800; }

.one   { transform: rotateY(0)      translateZ(110px); }
.two   { transform: rotateY(90deg)  translateZ(110px); }
.three { transform: rotateY(180deg) translateZ(110px); }
.four  { transform: rotateY(270deg) translateZ(110px); }
1
2
3
4
 

Scripted APIs

http://www.flickr.com/photos/maxbraun/4577640054/
Script <canvas>
Script requestAnimationFrame
function draw() {
  var now = new Date().getTime();
  updateModels(now - last);
  last = now;
  paintScene(canvas);
  window.setTimeout(draw, 10);
});
draw();
function draw(future) {

  updateModels(future - last);
  last = future;
  paintScene(canvas);
  requestAnimationFrame(draw, canvas);
};
draw();
Script 2D <canvas>
canvas.getContext('2d').drawImage(sprite_image,
                                  sX, sY, sprite_w, sprite_h,
                                  dX, dY, sprite_w, sprite_h);
Script 3D support!
A
B
C

Using device orientation for input:

window.addEventListener('deviceorientation', function(event) {
  var a = event.alpha; //
  var b = event.beta;  //
  var g = event.gamma; //
}, false);
Access WebGL 3D support
  varying vec2 vTextureCoord;
  uniform sampler2D uSampler;
  void main(void) {
      vec2 coords = vec2(vTextureCoord.s, vTextureCoord.t);
      gl_FragColor = texture2D(uSampler, coords);
  }

DEMO: Back to the command line...

LAUNCH

Blueprint: 3D FileSystem Browser

Audio

HTML5 ♥ audio

New features let you:

  • Play audio from the filesystem or the web.
  • Generate new audio from JavaScript.
  • Analyze audio as it is played.
Play <audio>
HTML5 gave us the ability play audio, natively, sans-plugin.
<audio controls autoplay loop>
  <source src="sound.mp3" type="audio/mpeg">
  <source src="sound.ogg" type="audio/ogg">
</audio>

Web Audio API

http://www.flickr.com/photos/timsnell/3105266077/sizes/z/in/photostream/
Play Playing a sound file
  • Prefixed in WebKit as window.webkitAudioContext()
  • Enable in about:flags
var ctx = new window.AudioContext();

function playSound(arrBuff) { // Obtain arrBuffer from XHR
  var src = ctx.createBufferSource();
  src.buffer = ctx.createBuffer(arrBuff, false /*mix2Mono*/);
  src.looping = true;

  src.connect(ctx.destination);
  src.noteOn(0); // Play immediately.
}
Generate Generating sound
var sine = new Oscillator(DSP.SINE, 440, 1.0, 2048, 44100).generate(); // dsp.js

var src = ctx.createBufferSource();
src.buffer = ctx.createBuffer(1 /*channels*/, 2048, 44100);
src.buffer.getChannelData(0).set(sine);
src.looping = true;

src.connect(ctx.destination);

src.noteOn(0);
Analyze Audio processing in 10 lines of code!
var ctx = new AudioContext();
var analyser = ctx.createAnalyser();
var jsProcessor = ctx.createJavaScriptNode(2048 /*samples*/,
                                             1 /*inputs*/, 1 /*outputs*/);
jsProcessor.onaudioprocess = function(e) {
  var freqByteData = new Uint8Array(analyser.frequencyBinCount);
  analyser.getByteFrequencyData(freqByteData);
  // render freqByteData to <canvas>.
};

function initAudio(arrBuff) {
  // src -> analyser -> jsprocessor -> destination.
  var src = ctx.createBufferSource();
  src.buffer = ctx.createBuffer(arrBuff, false);

  src.connect(analyser);
  analyser.connect(jsProcessor);
  jsProcessor.connect(ctx.destination);
};

DEMO: GAL 9000

LAUNCH

Blueprint: GAL 9000
Analyze Real-time audio analysis
Browser Support: Web Audio API

That was a lot...

What you saw
File
  • Import, Create, Manipulate, Store, Publish

Graphics
  • Declare, Script, Access

Audio
  • Play, Generate, Analyze
Go deeper

View: htmlfivewow.com   Source: code.google.com/p/html5wow

  • Learn: www.html5rocks.com
  • Compatibility: chromestatus.com, caniuse.com
  • Google Chrome Frame: code.google.com/chrome/chromeframe
  • Ask: groups.google.com/a/chromium.org/group/chromium-html5/
  • File Bugs! crbug.com
  • Follow Chrome Developer Relations: @ChromiumDev
  • Follow these guys: @ebidel, @kurrik

Thanks!

Feedback: http://goo.gl/ac8n7

Questions? http://goo.gl/mod/XKDL

References
  • Photo: Spacium ray a go go, baby by Fuyoh!
  • Photo: Hero Time by Fuyoh!