Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Next Mobile WebApplication
Search
uupaa
December 02, 2013
Programming
13
6.5k
Next Mobile WebApplication
このスライドは
2013-11-30 に開催された HTML5 Conference 2013 で
地下鉄・サクサク・これからのWebゲームアプリが備えるべき8つの機能
としてお話したものです
uupaa
December 02, 2013
Tweet
Share
Other Decks in Programming
See All in Programming
Realtime API 入門
riofujimon
0
150
カンファレンスの「アレ」Webでなんとかしませんか? / Conference “thing” Why don't you do something about it on the Web?
dero1to
1
100
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
1
100
CSC509 Lecture 13
javiergs
PRO
0
110
最新TCAキャッチアップ
0si43
0
190
Outline View in SwiftUI
1024jp
1
330
RubyLSPのマルチバイト文字対応
notfounds
0
120
Compose 1.7のTextFieldはPOBox Plusで日本語変換できない
tomoya0x00
0
190
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
260
リアーキテクチャxDDD 1年間の取り組みと進化
hsawaji
1
220
どうして僕の作ったクラスが手続き型と言われなきゃいけないんですか
akikogoto
1
120
GitHub Actionsのキャッシュと手を挙げることの大切さとそれに必要なこと
satoshi256kbyte
5
430
Featured
See All Featured
5 minutes of I Can Smell Your CMS
philhawksworth
202
19k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Building Adaptive Systems
keathley
38
2.3k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Designing for humans not robots
tammielis
250
25k
Designing on Purpose - Digital PM Summit 2013
jponch
115
7k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
YesSQL, Process and Tooling at Scale
rocio
169
14k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
Producing Creativity
orderedlist
PRO
341
39k
Transcript
Next Mobile WebApplication uupaa 2013-11-30
Me @uupaa - 2012 join R&D App
2013-11-30 HTML5 Conference 2013 Web 8
WebApp ? WebApp WebApp, Browser Game, SinglePageApplication, ES6, Storage, Cache,
Audio, Canvas, WebWorker
NativeApp vs WebApp NativeApp WebApp ? 3D
WebApp
Single Page Application (SPA) SPA ? 1 WebApp
SPA (BGM) WebApp 800ms -> 200ms
SPA
Audio/WebAudio Audio <audio> BGM BGM SE Android <audio>
WebAudio WebAudio m4a(AAC) WebAudio <audio> SoundSprite
WebAudio ( ) (input) ( ) ( ) (JavaScript )
+-------+ +-------+ +-------+ +-------+ +-------+ | 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 +-------------+
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);
( MIDI)
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
( )
Canvas 65 70% 200dpi (in Google Play) $179 (Moto G)
326dpi
Canvas CanvasRenderingContext2D#toDataURL 96dpi (ImageData) High Definition toDataURLHD toBlobHD createImageDataHD getImageDataHD
putImageDataHD
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)
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)
ImageData ImageData MB 16ms … for
? WebWorker
WebWorker Canvas ? ? Canvas canvas.transferControlToProxy canvasProxy.setContext context.commit
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); };
? 100 150MB GC window.gc() <img> <video> <svg> Worker Canvas
drawImage …
High Definition CanvasProxy + WebWorker
Command Pattern ( )
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; } });
: Android ( ) , ,
( ) Android Browser, Chrome for Android ( )
DrawCall ( ) Canvas API DrawCall DrawCall // before function
drawCall1() { ctx.fillRect(...); } function drawCall2() { ctx.fillRect(...); } drawCall1(); heavyRoutine(); drawCall2(); Chrome Canvas profiler DrawCall CanvasAPI
+ SnapShot, Movie
+ Remote Play DOM, CSS, Audio, Canvas App
+ 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 }); };
( )
WebWorker
WebApp WebWorker ? , , , ,
WebWorker JavaScript ?
WebWorker ( )
importScripts navigator.userAgent, onLine JSON, BLOB, FileReader, FileReaderSync Timer - setTimeout(),
setInterval() encodeURIComponent/decodeURIComponent TypedArray MessageChannel WebSQL, WebSQLSync WebSocket, XMLHttpRequest
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 )
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); };
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
Transferable Objects postMessage (zero-copy) Transferable Objects var payload = new
Array(big number); postMessage(payload, [payload]); Transferable Objects
WebWorker importScript JavaScript Prototype WebWorker
+ 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
WebWorker ? iframe
WebWorker
Storage, Cache, Offline Storage LocalStorage 5MB … WebSQL 50MB ApplicationCache
LocalStorage + WebSQL Base64 DataURI <img>
Asset Manifest 304 Not Modified HTTP 1 (SPDY ) 5MB
+ 5MB
Asset Manifes Sample ID URL MimeType Hash (MD5, SHA1 )
, { "HelloAssetManifest": { "url": "asset/scene/Hello.js", "hash": "fd2b04", "mime": "scene/class", "size": 1425, "prime": 1 } }
Storage Indexed DB + Disk Quota Management API 10% ServiceWorker
URL …
… デモ 1 30MB (140kB jpg x 210 ) Base64
1 40 50MB 13 (600 800MB)
SinglePageApplication WebSQL LocalStorage Asset Manifest iframe Base64 Doubler 1 (Bulk
Download)
Doubler Base64 ASCII SQLite(LocalStorage WebSQL ) UTF16 Doubler NULL, BOM,
UTF16 Base64 200 250%
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 | | // +----------+------------------+----------+
Bulk Download GIF AssetSprite 1 ? (SPDY )
</thank-you>