Preflight
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.
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.
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.
You will not be able to see the WebGL demos later in this slide deck.
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.
Your browser does not support displaying notifications. Currently,
only Google Chrome
will support this functionality.
Your browser does not support one or more of the following APIs:
File, FileList, FileReader.
Your browser does not support the File System API for
reading/writing files and directories.
The File System API are available in your browser, but write access is unavailable.
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.
- 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
10:45 - 11:45am
- 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
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
File
Graphics
Audio
File
Binary Data in HTML5
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();
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.
DataView ArrayBuffer Uint8Array Uint16Array Uint32Array Int8Array Int16Array Int32Array Float32Array
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 / FileList<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());
}
};
<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');
};
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
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);
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.
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
srcorhrefattributes. - Con: doesn't come for free. Use
revokeObjectURL()!
<!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>
File System API
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 );
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);
}
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
- Blob URLs (
blob:) - Data URLs (
data:) - 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) { ... });
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
<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>
<textPath method="align" spacing="auto"
xlink:href="#svgTextPath">
<tspan>Sometimes I have to put text on a path</tspan>
</textPath>
@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');
}
linear ease-in ease-out ease-in-out cubic-bezier(0.9, 0.1, 0.1, 0.9);
: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
.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
canvas.getContext('2d').drawImage(sprite_image,
sX, sY, sprite_w, sprite_h,
dX, dY, sprite_w, sprite_h);
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);
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...
Audio
New features let you:
- Play audio from the filesystem or the web.
- Generate new audio from JavaScript.
- Analyze audio as it is played.
<audio controls autoplay loop> <source src="sound.mp3" type="audio/mpeg"> <source src="sound.ogg" type="audio/ogg"> </audio>

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.
}
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);
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
That was a lot...
- Import, Create, Manipulate, Store, Publish
Graphics
- Declare, Script, Access
Audio
- Play, Generate, Analyze
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
- Photo: Spacium ray a go go, baby by Fuyoh!
- Photo: Hero Time by Fuyoh!

