Pro Yearly is on sale from $80 to $50! »

Next Mobile WebApplication

247a36b939111801f83b561060c63e7b?s=47 uupaa
December 02, 2013

Next Mobile WebApplication

このスライドは
2013-11-30 に開催された HTML5 Conference 2013 で

地下鉄・サクサク・これからのWebゲームアプリが備えるべき8つの機能

としてお話したものです

247a36b939111801f83b561060c63e7b?s=128

uupaa

December 02, 2013
Tweet

Transcript

  1. Next Mobile WebApplication uupaa 2013-­11-­30

  2. Me @uupaa - 2012 join R&D App

  3. 2013-11-30 HTML5 Conference 2013 Web 8

  4. WebApp ? WebApp WebApp, Browser Game, SinglePageApplication, ES6, Storage, Cache,

    Audio, Canvas, WebWorker
  5. NativeApp vs WebApp NativeApp WebApp ? 3D

  6. WebApp

  7. Single Page Application (SPA) SPA ? 1 WebApp

  8. SPA (BGM) WebApp 800ms -> 200ms

  9. SPA

  10. Audio/WebAudio Audio <audio> BGM BGM SE Android <audio>

  11. WebAudio WebAudio m4a(AAC) WebAudio <audio> SoundSprite

  12. WebAudio ( ) (input) ( ) ( ) (JavaScript )

  13. +-------+ +-------+ +-------+ +-------+ +-------+ | SE[0] | | SE[1]

    | | SE[n] | | BGM-A | | BGM-B | BufferSource <<AudioBuffer>> +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ | | | | | | | | +----+---+ +---+----+ | | | | FADE-A | | FADE-B | BGM CrossFade <<Gain>> | | | +----+---+ +---+----+ +---------+---------+ +----+----+ | | +----+---+ +--+---+ | EFFECT | | LOOP | Effect/Loop Volume <<Gain>> +----+---+ +--+---+ +-------------+------------+ +---+---+ | MUTE | Mute <<Gain>> +---+---+ +------+------+ | Compressor | <<DynamicsCompressor>> +------+------+ +------+------+ | Distination | AudioContext.Distination +-------------+
  14. var ctx = new global.AudioContext(); var node = { compressor:

    null, fade: [null,null], // CrossFade volume master: null, // master volume effect: null, // effect volume loop: null, // loop volume mute: null // mute }; node.compressor = ctx.createDynamicsCompressor(); node.mute = ctx.createGainNode(); node.master = ctx.createGainNode(); node.effect = ctx.createGainNode(); node.loop = ctx.createGainNode(); node.fade[0] = ctx.createGainNode(); node.fade[1] = ctx.createGainNode(); node.fade[0].connect(node.loop); node.fade[1].connect(node.loop); node.effect.connect(node.master); node.loop.connect(node.master); node.master.connect(node.mute); node.mute.connect(node.compressor); node.compressor.connect(ctx.destination);
  15. ( MIDI)

  16. WebAudio Web SE BGM OFF ON/OFF Android DualCore, 1GB RAM

    iOS iOS 7, iPhone 4S (iOS 6 ) Chrome for Android 31 http://hello.uupaa.net/issues/2/ HE-AAC
  17. ( )

  18. Canvas 65 70% 200dpi (in Google Play) $179 (Moto G)

    326dpi
  19. Canvas CanvasRenderingContext2D#toDataURL 96dpi (ImageData) High Definition toDataURLHD toBlobHD createImageDataHD getImageDataHD

    putImageDataHD
  20. 2013 ImageData Width x Height Canvas ImageData Device 480 x

    320 600 KB iPhone (2007) 960 x 640 2.3 MB iPhone Retina (2010) 2048 x 1536 12 MB iPad Retina (2012) ImageData Pixel x 4byte(RGBA)
  21. 2015 ImageData 2015 4K Width x Height Canvas ImageData Device

    960 x 640 2.3 MB iPhone Retina (2010) 2048 x 1536 12 MB iPad Retina (2012) 2560 x 1440 14 MB 2K Android (maybe 2014) 3840 x 2160 31.6 MB 4K Android (maybe 2015)
  22. ImageData ImageData MB 16ms … for

  23. ? WebWorker

  24. WebWorker Canvas ? ? Canvas canvas.transferControlToProxy canvasProxy.setContext context.commit

  25. CanvasProxy (1 ) <canvas></canvas> // index.js var canvas = document.querySelector("canvas");

    var canvasProxy = canvas.transferControlToProxy(); // CanvasProxy を取得 var canvasWorker = new Worker("BackgroundCanvasRender.js"); canvasWorker.postMessage(canvasProxy, [canvasProxy]); // Worker に渡す // BackgroundCanvasRender.js onmessage = function(event) { var context = new CanvasRenderingContext2D(); var canvasProxy = event.data; canvasProxy.setContext(context); // bind setInterval(function() { context.clearRect(0, 0, context.width, context.height); context.fillText(new Date() + "", 0, 100); context.commit(); // render }, 1000); };
  26. ? 100 150MB GC window.gc() <img> <video> <svg> Worker Canvas

    drawImage …
  27. High Definition CanvasProxy + WebWorker

  28. Command Pattern ( )

  29. Canvas API // before ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, 100,

    100); // after var canvasCommands = [ ["fillStyle", "#fff"], ["fillRect", 0, 0, 100, 100] ]; for (var i = 0, iz = canvasCommands.length; i < iz; ++i) { switch (canvasCommands[i]) { case "fillStyle": ... break; case "fillRect": ... break; } });
  30. : Android ( ) , ,

  31. ( ) Android Browser, Chrome for Android ( )

  32. DrawCall ( ) Canvas API DrawCall DrawCall // before function

    drawCall1() { ctx.fillRect(...); } function drawCall2() { ctx.fillRect(...); } drawCall1(); heavyRoutine(); drawCall2(); Chrome Canvas profiler DrawCall CanvasAPI
  33. + SnapShot, Movie

  34. + Remote Play DOM, CSS, Audio, Canvas App

  35. + WebWorker WebWorker postMessage // index.js var worker = new

    Worker("Worker.js"); var request = []; worker.onmessage = function(event) { var response = event.data.response; : }; worker.postMessage({ request: request }); // Worker.js onmessage = function(event) { var request = event.data.request; postMessage({ response: ["ok"], error: null }); };
  36. ( )

  37. WebWorker

  38. WebApp WebWorker ? , , , ,

  39. WebWorker JavaScript ?

  40. WebWorker ( )

  41. importScripts navigator.userAgent, onLine JSON, BLOB, FileReader, FileReaderSync Timer - setTimeout(),

    setInterval() encodeURIComponent/decodeURIComponent TypedArray MessageChannel WebSQL, WebSQLSync WebSocket, XMLHttpRequest
  42. navigator.webkitPersistentStorage navigator.webkitTemporaryStorage HighPerformanceTimer - performance.now() TextEncoder/TextDecoder Crypto, Base64(atob, btoa) ImageBitmap

    IndexedDB WorkerConsole - console.log() RequestFileSystem, RequestFileSystemSync ES6( Symbol, Set, Map, WeakMap, WeakSet, Promise )
  43. postMessage ? Nexus 7(2012) Chrome 0.6ms, Mac Chrome 0.02ms var

    worker = new Worker("worker.js"); var score = 0; worker.onmessage = function(event) { worker.postMessage(++score); }; setTimeout(function() { worker.postMessage("stop"); }, 10 * 1000); // worker.js var payload = []; var timerID = setInterval(function() { postMessage(payload); }, 1); onmessage = function(event) { event.data === "stop" && clearInterval(timerID); };
  44. postMessage Structured Cloning var payload = new Array(big number); postMessage(payload);

    1MB (payload) 32MB payload 25% var MB = 1024 * 1024; var payload = new Uint8ClampedArray( 1 * MB); // 無負荷時の 98% の速度で動作 var payload = new Uint8ClampedArray( 8 * MB); // 無負荷時の 90% の速度で動作 var payload = new Uint8ClampedArray(32 * MB); // 無負荷時の 25% の速度で動作 Structured Cloning
  45. Transferable Objects postMessage (zero-copy) Transferable Objects var payload = new

    Array(big number); postMessage(payload, [payload]); Transferable Objects
  46. WebWorker importScript JavaScript Prototype WebWorker

  47. + Module Node.js, Browser, WebWorker (function(global) { // --- define

    ---------------------------------------------- // --- variable -------------------------------------------- // --- interface ------------------------------------------- function Class() { } // --- implement ------------------------------------------- // --- export ---------------------------------------------- if (global.process) { module.exports = Class; } global.Class = Class; })(this.self || global); : Typical JavaScript Module Pattern
  48. WebWorker ? iframe

  49. WebWorker

  50. Storage, Cache, Offline Storage LocalStorage 5MB … WebSQL 50MB ApplicationCache

  51. LocalStorage + WebSQL Base64 DataURI <img>

  52. Asset Manifest 304 Not Modified HTTP 1 (SPDY ) 5MB

    + 5MB
  53. Asset Manifes Sample ID URL MimeType Hash (MD5, SHA1 )

    , { "HelloAssetManifest": { "url": "asset/scene/Hello.js", "hash": "fd2b04", "mime": "scene/class", "size": 1425, "prime": 1 } }
  54. Storage Indexed DB + Disk Quota Management API 10% ServiceWorker

    URL …
  55. … デモ 1 30MB (140kB jpg x 210 ) Base64

    1 40 50MB 13 (600 800MB)
  56. SinglePageApplication WebSQL LocalStorage Asset Manifest iframe Base64 Doubler 1 (Bulk

    Download)
  57. Doubler Base64 ASCII SQLite(LocalStorage WebSQL ) UTF16 Doubler NULL, BOM,

    UTF16 Base64 200 250%
  58. Doubler Code Point // Doubler.js: UTF16 Safe packer // Mobile

    Browser unavailable UTF16 words: // Safari: NULL, BOM // Chrome: NULL, BOM, SurrogatePairs // Android: NULL // // Desktop Browser unavailable UTF16 words: // Safari: NULL, BOM // Chrome: NULL, BOM, SurrogatePairs // // +- UINT16 -+- Doubler.pack() -+- unpack -+ // | 0x0000 | 0x0020, 0x8000 | -0x8000 | encode NULL // +----------+------------------+----------+ // | 0x0020 | 0x0020, 0x8020 | -0x8000 | encode 0x20 // +----------+------------------+----------+ // | 0xd800 | 0x0020, 0x5800 | +0x8000 | encode SurrogatePairs // | : | : | | // | 0xdfff | 0x0020, 0x5fff | | // +----------+------------------+----------+ // | 0xfffe | 0x0020, 0x7ffe | +0x8000 | encode BOM // | 0xffff | 0x0020, 0x7fff | | // +-- Tail --+- Doubler.pack() -+----------+ // | 0x00 | 0x0020, 0x9000 | -0x9000 | encode Tail byte // | : | : | | // | 0xff | 0x0020, 0x90ff | | // +----------+------------------+----------+
  59. Bulk Download GIF AssetSprite 1 ? (SPDY )

  60. </thank-you>