Comments:"HTML5 Showcase for Web Developers: The Wow and the How"
URL:http://www.htmlfivewow.com/slide1
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 will not be able to see the WebGL demos later in this slide deck.
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.
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
Eric Bidelman && Arne
Roomann-KurrikGoogle I/O - May 11, 2011
10:45 - 11:45am
Watch the session
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
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 dataNew 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();
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 & dropvar 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
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 URLsChrome 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>
Store Opening the file systemIf 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
Store 1, 2, 3, Ways to generate URLs to fileswindow.resolveLocalFileSystemURL is prefixed as window.webkitResolveLocalFileSystemURL in Chrome 12+.
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) { ... });
HTML5 ♥ graphicsNew features let you:
Declare styles and animations to be rendered by the browser.
Script graphics for finer control.
Access low-level APIs for performance.
Declare CSS: Too much awesome to covertext-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 Tweenslinear
ease-in
ease-out
ease-in-out
cubic-bezier(0.9, 0.1, 0.1, 0.9);
cubic-bezierlinearease-inease-outease-in-out
Animate
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; }
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
Script <canvas>Stop
Script requestAnimationFrame
Script 3D support!
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);
}
LAUNCH
HTML5 ♥ audioNew 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>
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);
};
Analyze Real-time audio analysis
Go deeper
View: htmlfivewow.com
Source: code.google.com/p/html5wow
Thanks!
Feedback: http://goo.gl/ac8n7
Questions? http://goo.gl/mod/XKDL