├── .gitignore ├── LICENSE ├── README.md ├── ch01 ├── ca.js └── index.html ├── ch05 ├── ex1 │ ├── index.html │ └── module.js ├── ex2 │ ├── index.html │ └── sideeffect.js ├── ex3 │ ├── index.html │ └── module.js ├── ex4 │ ├── index.html │ ├── module.js │ └── module2.js ├── ex5 │ ├── index.html │ └── module.js ├── ex6 │ ├── index.html │ └── module.js ├── ex7 │ ├── index.html │ └── module.js └── ex8 │ ├── index.html │ ├── module.js │ ├── submodule.js │ └── submodule2.js ├── ch12 ├── ex1 │ └── index.html ├── ex2 │ └── index.html └── ex3 │ └── index.html ├── ch15 ├── cssanimation.html ├── csstransform.html ├── csstransition.html ├── ex1 │ ├── JavaScript-logo.png │ ├── Network-12716.mp4 │ ├── brook1.mp3 │ ├── bulbul.mp3 │ ├── fall_morning_river.mp3 │ ├── index.html │ ├── refs.txt │ └── takedown.mp4 ├── ex2 │ └── index.html └── webgl.html ├── ch17 ├── ex1 │ ├── index.html │ └── sw.js ├── ex2 │ ├── index.html │ ├── sw1.js │ ├── v1 │ │ ├── page1.html │ │ └── page2.html │ └── v2 │ │ ├── page3.html │ │ └── page4.html ├── ex3 │ ├── index.html │ └── sw.js ├── ex4 │ ├── icon.png │ ├── index.html │ ├── manifest.webmanifest │ └── sw.js └── ex5 │ └── index.html ├── ch19 ├── index.html ├── js │ ├── worker1.js │ ├── worker2.js │ ├── worker3.js │ ├── worker4.js │ ├── worker5.js │ ├── worker6.js │ └── worker7.js └── wasm │ ├── add.wasm │ └── add.wat ├── hands-on-javascript.png ├── repl.txt └── toc.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *~ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 ANDO Yasushi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ハンズオンJavaScript 2 | 3 | --- 4 | 5 | ![表紙](hands-on-javascript.png) 6 | 7 | --- 8 | 9 | 本リポジトリはオライリー・ジャパン発行書籍『[ハンズオンJavaScript](https://www.oreilly.co.jp/books/9784873119229/)』のサポートサイトです。 10 | 11 | ## ソースコード 12 | 13 | ### ファイル構成 14 | 15 | |ファイル名 |説明 | 16 | |:-- |:-- | 17 | |ch01/ |1章で使用するベースサイト | 18 | |ch05/ |5章で使用するベースサイト | 19 | |ch12/ |12章で使用するベースサイト| 20 | |ch15/ |15章で使用するベースサイト| 21 | |ch17/ |17章で使用するベースサイト| 22 | |ch19/ |19章で使用するベースサイト| 23 | |repl.txt |書籍から抽出したコード | 24 | 25 | 起動方法や利用方法は本書籍をご覧ください。 26 | 27 | ## ライセンス 28 | 本リポジトリのソースコードは[MITライセンス](http://www.opensource.org/licenses/MIT)です。 29 | 商用・非商用問わず、自由にご利用ください。 30 | 31 | ## 正誤表 32 | 33 | 本書の正誤情報は以下のページで公開しています。 34 | 35 | https://github.com/oreilly-japan/hands-on-javascript/wiki/errata 36 | 37 | 本ページに掲載されていない誤植など間違いを見つけた方は、[japan@oreilly.co.jp]()までお知らせください。 38 | -------------------------------------------------------------------------------- /ch01/ca.js: -------------------------------------------------------------------------------- 1 | class CA1Rule90 { 2 | constructor(initialStates) { 3 | this.rule = { 4 | "000": "0", 5 | "001": "1", 6 | "010": "0", 7 | "011": "1", 8 | "100": "1", 9 | "101": "0", 10 | "110": "1", 11 | "111": "0", 12 | } 13 | this.initialStates = initialStates 14 | this.reset() 15 | } 16 | 17 | next() { 18 | const currentStates = `0${this.states}0` 19 | const nextStates = [] 20 | for (let c = 0; c < currentStates.length - 2; c++) { 21 | const state = currentStates.substring(c, c+3) 22 | nextStates[c] = this.nextCell(state) 23 | } 24 | this.states = nextStates.join("") 25 | } 26 | 27 | nextCell(state) { 28 | return this.rule[state] 29 | } 30 | 31 | reset() { 32 | this.states = `${this.initialStates}` 33 | } 34 | 35 | toString() { 36 | return this.states.replace(/./g, s => s === "0" ? " " : "*") 37 | } 38 | } 39 | 40 | export { CA1Rule90 } 41 | 42 | // How to instantiate 43 | // new CA1({ 44 | // rule:90, 45 | // states:[ 46 | // 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 47 | // 1, 48 | // 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 49 | // ] 50 | // }) 51 | export class CA1 { 52 | constructor(opts={}) { 53 | this.rule = opts.rule 54 | this.initialStates = opts.states 55 | this.reset() 56 | } 57 | 58 | next() { 59 | let curr = [0].concat(this.states, [0]) 60 | for (let c = 1; c < curr.length - 1; c++) { 61 | const state = 0b100 * curr[c+1] + 0b010 * curr[c] + 0b001 * curr[c-1] 62 | this.states[c-1] = this.nextCell(state) 63 | } 64 | } 65 | 66 | nextCell(state) { 67 | return (this.rule & (0x1 << state)) >> state 68 | } 69 | 70 | reset() { 71 | this.states = [].concat(this.initialStates) 72 | } 73 | 74 | toString() { 75 | return this.states.map(c => c === 0 ? " " : "*").join("") 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /ch01/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ch. 1. Cellular Automaton 5 | 56 | 57 | 58 |
59 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ch05/ex1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ch05/ex1/module.js: -------------------------------------------------------------------------------- 1 | console.log("module.js") 2 | -------------------------------------------------------------------------------- /ch05/ex2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ch05/ex2/sideeffect.js: -------------------------------------------------------------------------------- 1 | console.log("モジュールの副作用") 2 | -------------------------------------------------------------------------------- /ch05/ex3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ch05/ex3/module.js: -------------------------------------------------------------------------------- 1 | class Klass {} 2 | function func() { return "module func" } 3 | let variable = "var" 4 | const constant = "constant" 5 | export {Klass, func, variable, constant} 6 | -------------------------------------------------------------------------------- /ch05/ex4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch05/ex4/module.js: -------------------------------------------------------------------------------- 1 | class Klass {} 2 | function func() { return "module func" } 3 | let variable = "var" 4 | const constant = "constant" 5 | export {Klass, func, variable, constant} 6 | -------------------------------------------------------------------------------- /ch05/ex4/module2.js: -------------------------------------------------------------------------------- 1 | class Klass {} 2 | function func() { return "module func2" } 3 | let variable = "var2" 4 | const constant = "constant2" 5 | export {Klass, func, variable, constant} 6 | -------------------------------------------------------------------------------- /ch05/ex5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ch05/ex5/module.js: -------------------------------------------------------------------------------- 1 | class Klass {} 2 | function func() { return "module func" } 3 | let variable = "var" 4 | const constant = "constant" 5 | export {Klass, func, variable, constant} 6 | -------------------------------------------------------------------------------- /ch05/ex6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ch05/ex6/module.js: -------------------------------------------------------------------------------- 1 | class Klass {} 2 | function func() { return "module func" } 3 | let variable = "var" 4 | const constant = "constant" 5 | export {Klass, func, variable, constant} 6 | export default {Klass, func, variable, constant} 7 | -------------------------------------------------------------------------------- /ch05/ex7/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /ch05/ex7/module.js: -------------------------------------------------------------------------------- 1 | class Klass {} 2 | function func() { return "module func" } 3 | let variable = "var" 4 | const constant = "constant" 5 | export {Klass, func, variable, constant} 6 | export default {Klass, func, variable, constant} 7 | -------------------------------------------------------------------------------- /ch05/ex8/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ch05/ex8/module.js: -------------------------------------------------------------------------------- 1 | export { Klass as K, func as f } from "./submodule.js" 2 | export * from "./submodule.js" 3 | export * from "./submodule2.js" 4 | export { default } from "./submodule.js" 5 | -------------------------------------------------------------------------------- /ch05/ex8/submodule.js: -------------------------------------------------------------------------------- 1 | class Klass {} 2 | function func() { return "func1" } 3 | let variable = "variable1" 4 | const constant = "constant1" 5 | 6 | export { variable as default, Klass, func, constant } 7 | -------------------------------------------------------------------------------- /ch05/ex8/submodule2.js: -------------------------------------------------------------------------------- 1 | function func() { return "func2" } 2 | const constant = "constant2" 3 | -------------------------------------------------------------------------------- /ch12/ex1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ウェブ 6 | 7 | 8 |
9 |

HTML

10 |

HTMLは文書のコンテンツと構造を表現します。

11 |
12 |
13 |

CSS

14 |

CSSはHTMLのスタイルを指定します。

15 |
16 |
17 |

JavaScript

18 |

JavaScriptはHTMLとCSSの両方を制御できます。

19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /ch12/ex2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ウェブ 6 | 23 | 24 | 25 |
26 |

HTML

27 |

HTMLは文書のコンテンツと構造を表現します。

28 |
29 |
30 |

CSS

31 |

CSSはHTMLのスタイルを指定します。

32 |
33 |
34 |

JavaScript

35 |

JavaScriptはHTMLとCSSの両方を制御できます。

36 |
37 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ch12/ex3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Web Components 6 | 7 | 8 | 9 | 10 | 31 | 32 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ch15/cssanimation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 45 | 46 | 47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /ch15/csstransform.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 20 |
21 | hello
world
!! 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /ch15/csstransition.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /ch15/ex1/JavaScript-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/ch15/ex1/JavaScript-logo.png -------------------------------------------------------------------------------- /ch15/ex1/Network-12716.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/ch15/ex1/Network-12716.mp4 -------------------------------------------------------------------------------- /ch15/ex1/brook1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/ch15/ex1/brook1.mp3 -------------------------------------------------------------------------------- /ch15/ex1/bulbul.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/ch15/ex1/bulbul.mp3 -------------------------------------------------------------------------------- /ch15/ex1/fall_morning_river.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/ch15/ex1/fall_morning_river.mp3 -------------------------------------------------------------------------------- /ch15/ex1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 |
25 |

Ref.

26 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /ch15/ex1/refs.txt: -------------------------------------------------------------------------------- 1 | - https://taira-komori.jpn.org/nature01.html 2 | - brook1 3 | -------------------------------------------------------------------------------- /ch15/ex1/takedown.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/ch15/ex1/takedown.mp4 -------------------------------------------------------------------------------- /ch15/ex2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /ch15/webgl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /ch17/ex1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | /proxy/以下で拡張子を".html"にすると生成(プロキシ)された内容が返ります。 7 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ch17/ex1/sw.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('install', event => { 2 | console.log(`install:${event}`) 3 | }); 4 | 5 | self.addEventListener('activate', event => { 6 | console.log(`activate:${event}`) 7 | }); 8 | 9 | self.addEventListener('fetch', event => { 10 | event.respondWith(new Promise((resolve, reject) => { 11 | const pathname = new URL(event.request.url).pathname 12 | console.log(pathname) 13 | if (pathname.startsWith("/ch17/ex1/proxy/")) { 14 | if (pathname.endsWith(".html")) { 15 | resolve(new Response("Proxy World!")) 16 | } else { 17 | resolve(Response.error()) 18 | } 19 | } else { 20 | resolve(fetch(event.request)) 21 | } 22 | })) 23 | }); 24 | -------------------------------------------------------------------------------- /ch17/ex2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /ch17/ex2/sw1.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('install', event => { 2 | event.waitUntil( 3 | caches.open('v1').then(cache => { 4 | return cache.addAll([ 5 | '/ch17/ex2/v1/page1.html' 6 | ]); 7 | }) 8 | ); 9 | }); 10 | 11 | self.addEventListener('fetch', event => { 12 | event.respondWith(caches.match(event.request).then(response => { 13 | return response || fetch(event.request).then(response => { 14 | return caches.open('v1').then(cache => { 15 | cache.put(event.request, response.clone()) 16 | return response 17 | }) 18 | }) 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /ch17/ex2/v1/page1.html: -------------------------------------------------------------------------------- 1 | page1 2 | -------------------------------------------------------------------------------- /ch17/ex2/v1/page2.html: -------------------------------------------------------------------------------- 1 | page2 2 | -------------------------------------------------------------------------------- /ch17/ex2/v2/page3.html: -------------------------------------------------------------------------------- 1 | page3 2 | -------------------------------------------------------------------------------- /ch17/ex2/v2/page4.html: -------------------------------------------------------------------------------- 1 | page4 2 | -------------------------------------------------------------------------------- /ch17/ex3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ch17/ex3/sw.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('push', event => { 2 | //console.log(`プッシュ通知: ${event.data.text()}`) 3 | const data = event.data.json() 4 | event.waitUntil(self.registration.showNotification(data.title, {body:data.body})) 5 | }) 6 | -------------------------------------------------------------------------------- /ch17/ex4/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/ch17/ex4/icon.png -------------------------------------------------------------------------------- /ch17/ex4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Installable app 9 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ch17/ex4/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "サンプルアプリ名", 3 | "description": "どのようなアプリであるかの説明", 4 | "display": "fullscreen", 5 | "icons": [{ 6 | "src": "/ch17/ex4/icon.png", 7 | "sizes": "256x256" 8 | }], 9 | "start_url": "/ch17/ex4/" 10 | } 11 | -------------------------------------------------------------------------------- /ch17/ex4/sw.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('install', event => { 2 | console.log(`install:${event}`) 3 | }); 4 | 5 | self.addEventListener('activate', event => { 6 | console.log(`activate:${event}`) 7 | }); 8 | 9 | self.addEventListener('fetch', event => { 10 | event.respondWith(new Promise((resolve, reject) => { 11 | resolve(new Response("Installable app")) 12 | })) 13 | }); 14 | -------------------------------------------------------------------------------- /ch17/ex5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ch19/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ch19/js/worker1.js: -------------------------------------------------------------------------------- 1 | console.log("worker1実行中") 2 | while (true) {} 3 | -------------------------------------------------------------------------------- /ch19/js/worker2.js: -------------------------------------------------------------------------------- 1 | self.addEventListener("message", event => { 2 | const name = event.data 3 | if (typeof name !== "string") throw "名前が文字列ではありません" 4 | self.postMessage(`Hello, ${name}`) 5 | }) 6 | -------------------------------------------------------------------------------- /ch19/js/worker3.js: -------------------------------------------------------------------------------- 1 | let messageData 2 | self.addEventListener("message", event => messageData = event.data) 3 | -------------------------------------------------------------------------------- /ch19/js/worker4.js: -------------------------------------------------------------------------------- 1 | importScripts("https://cdnjs.cloudflare.com/ajax/libs/mathjs/6.6.2/math.js") 2 | self.addEventListener("message", event => { 3 | postMessage(math.evaluate(event.data)) 4 | }) 5 | -------------------------------------------------------------------------------- /ch19/js/worker5.js: -------------------------------------------------------------------------------- 1 | let canvas 2 | self.addEventListener("message", event => { 3 | if ("canvas" in event.data) canvas = event.data.canvas 4 | 5 | const ctx = canvas.getContext("2d") 6 | ctx.fillStyle = event.data.color 7 | ctx.beginPath() 8 | ctx.moveTo(50, 50) 9 | ctx.lineTo(50, 80) 10 | ctx.lineTo(10, 80) 11 | ctx.closePath() 12 | ctx.fill() 13 | ctx.beginPath() 14 | ctx.moveTo(55, 80) 15 | ctx.arc(125, 80, 70, Math.PI, 0, true) 16 | ctx.bezierCurveTo(170, 100, 120, -50, 55, 50) 17 | ctx.closePath() 18 | ctx.moveTo(105, 50) 19 | ctx.ellipse(85, 50, 20, 15, 0, 0, 2 * Math.PI) 20 | ctx.moveTo(90, 50) 21 | ctx.arc(80, 50, 10, 0, 2 * Math.PI) 22 | ctx.rect(10, 85, 40, 5) 23 | ctx.fill() 24 | }) 25 | -------------------------------------------------------------------------------- /ch19/js/worker6.js: -------------------------------------------------------------------------------- 1 | let messageData = "初期値" 2 | 3 | self.addEventListener("connect", event => { 4 | let port = event.ports[0] 5 | port.addEventListener("message", event => { 6 | let prevData = messageData 7 | messageData = event.data 8 | port.postMessage(prevData) 9 | }) 10 | port.start() 11 | }) 12 | -------------------------------------------------------------------------------- /ch19/js/worker7.js: -------------------------------------------------------------------------------- 1 | const drawBird = (scale, dx, dy) => { 2 | ctx.clearRect(0, 0, 200, 200) 3 | ctx.beginPath() 4 | ctx.moveTo(50*scale+dx, 50*scale+dy) 5 | ctx.lineTo(50*scale+dx, 80*scale+dy) 6 | ctx.lineTo(10*scale+dx, 80*scale+dy) 7 | ctx.closePath() 8 | ctx.fill() 9 | ctx.beginPath() 10 | ctx.moveTo(55*scale+dx, 80*scale+dy) 11 | ctx.arc(125*scale+dx, 80*scale+dy, 70*scale, Math.PI, 0, true) 12 | ctx.bezierCurveTo(170*scale+dx, 100*scale+dy, 120*scale+dx, -50*scale+dy, 55*scale+dx, 50*scale+dy) 13 | ctx.closePath() 14 | ctx.moveTo(105*scale+dx, 50*scale+dy) 15 | ctx.ellipse(85*scale+dx, 50*scale+dy, 20*scale, 15*scale, 0, 0, 2 * Math.PI) 16 | ctx.moveTo(90*scale+dx, 50*scale+dy) 17 | ctx.arc(80*scale+dx, 50*scale+dy, 10*scale, 0, 2 * Math.PI) 18 | ctx.rect(10*scale+dx, 85*scale+dy, 40*scale, 5*scale) 19 | ctx.fill() 20 | } 21 | 22 | const moveBird = timestamp => { 23 | if (stopping) return 24 | 25 | const angle = (timestamp / 20 % 360) / 180 * Math.PI 26 | const scale = 0.3 27 | const dx = 70 + 70 * Math.cos(angle*2) 28 | const dy = 70 + 70 * Math.sin(angle*5) 29 | drawBird(scale, dx, dy) 30 | 31 | requestAnimationFrame(moveBird) 32 | } 33 | 34 | let ctx 35 | let stopping = true 36 | self.addEventListener("message", event => { 37 | if ("stop" in event.data) { 38 | stopping = true 39 | } else if (("canvas" in event.data || "start" in event.data) && stopping) { 40 | stopping = false 41 | if (!ctx) ctx = event.data.canvas.getContext("2d") 42 | requestAnimationFrame(moveBird) 43 | } 44 | }) 45 | -------------------------------------------------------------------------------- /ch19/wasm/add.wasm: -------------------------------------------------------------------------------- 1 | asm 2 | ``consolelogjsmemadd 3 |  j!A 6  -------------------------------------------------------------------------------- /ch19/wasm/add.wat: -------------------------------------------------------------------------------- 1 | (module 2 | ;; JSから受け取る関数 3 | (import "console" "log" (func $log (param i32))) 4 | 5 | ;; JSと共有する記憶領域 6 | (import "js" "mem" (memory 1)) 7 | 8 | ;; JSから利用できるadd関数定義 9 | (func (export "add") (param $v1 i32) (param $v2 i32) 10 | 11 | ;; 変数宣言 12 | (local $result i32) 13 | 14 | ;; 引数を合計した結果を$resultに保存 15 | (set_local $result (i32.add (get_local $v1) (get_local $v2))) 16 | 17 | ;; 結果を共有領域に保存 18 | (i32.store (i32.const 0) (get_local $result)) 19 | 20 | ;; 結果を$log関数で表示 21 | (call $log (get_local $result)) 22 | ) 23 | ) 24 | -------------------------------------------------------------------------------- /hands-on-javascript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oreilly-japan/hands-on-javascript/79eb96f36be51098a4bb41806d3123229d2d0913/hands-on-javascript.png -------------------------------------------------------------------------------- /toc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | --------------------------------------------------------------------------------