From 6ef1fa4618e08426b874529619a66adbd3d1fcf0 Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 12:07:59 +0100 Subject: unslug ja: move --- .../tutorial/basic_animations/index.html | 711 +++++++++++++++++++++ 1 file changed, 711 insertions(+) create mode 100644 files/ja/web/api/canvas_api/tutorial/basic_animations/index.html (limited to 'files/ja/web/api/canvas_api/tutorial/basic_animations') diff --git a/files/ja/web/api/canvas_api/tutorial/basic_animations/index.html b/files/ja/web/api/canvas_api/tutorial/basic_animations/index.html new file mode 100644 index 0000000000..1690518a7d --- /dev/null +++ b/files/ja/web/api/canvas_api/tutorial/basic_animations/index.html @@ -0,0 +1,711 @@ +--- +title: Basic animations +slug: Web/Guide/HTML/Canvas_tutorial/Basic_animations +tags: + - Canvas + - Graphics + - HTML + - HTML5 + - Intermediate + - Tutorial +translation_of: Web/API/Canvas_API/Tutorial/Basic_animations +--- +
{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}
+ +
+

私たちが {{HTMLElement("canvas")}} 要素の操作に JavaScript を使うのは、とても簡単にインタラクティブなアニメーションを作成できるからです!本章では、いくつかの基本的なアニメーションで、その概要をつかんでいきます。

+
+ +

おそらく最大の制約は、キャンバスに図形を一度描画すると、その状態が維持されることです。アニメーションさせる場合にも、移動する部分と以前に描いた部分をすべて再描画する必要があります。複雑なフレームの再描画には時間がかかり、パフォーマンスは、実行しているコンピューターの速度に大きく依存します。

+ +

基本的なアニメーションの手順

+ +

フレームを描画させる手順は、このようになります。

+ +
    +
  1. キャンバスをクリアする
    + 描画する図形がキャンバス全体 (たとえば、背景画像) に収まらない限り、以前に描画した図形をすべてクリアする必要があります。それを行う最も簡単な方法は、{{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}} メソッドを使うことです。
  2. +
  3. キャンバスの状態を保存する
    + キャンバスの状態に影響を与える設定(スタイル、変形など)を変更していて、フレームを描画するたびに元の状態を使用したい場合は、その状態を保存する必要があります。
  4. +
  5. アニメ―ションさせる図形を描画する
    + 実際に、フレームの描画を行います。
  6. +
  7. キャンバスの状態を復元する
    + 状態を保存した場合は、新しいフレームを描画する前に状態を復元します。
  8. +
+ +

アニメーションの制御

+ +

図形は、canvas のメソッドを直接使用するか、カスタム関数を呼び出すことによって描画されます。通常は、スクリプトの実行が終了したときにのみ、これらの結果がキャンバスに表示されます。たとえば、for ループ内からアニメーションを実行することはできません。

+ +

つまり、一定の期間ごとに描画関数を実行する方法が必要です。このようなアニメーションを制御するには、2 つの方法があります。

+ +

スケジュールの更新

+ +

まず、{{domxref("window.setInterval()")}}、{{domxref("window.setTimeout()")}} があります。それから、{{domxref("window.requestAnimationFrame()")}} 関数があります。これらは、特定の関数を一定時間で呼び出すために使用できます。

+ +
+
{{domxref("WindowTimers.setInterval", "setInterval(function, delay)")}}
+
function で指定した関数を delay ミリ秒ごとに繰り返し実行します。
+
{{domxref("WindowTimers.setTimeout", "setTimeout(function, delay)")}}
+
function で指定した関数を delay ミリ秒後に実行します。
+
{{domxref("Window.requestAnimationFrame()", "requestAnimationFrame(callback)")}}
+
アニメーションを実行することをブラウザーに通知し、次の再描画の前にアニメーションを更新するため、ブラウザーが指定の関数を呼び出すように要求します。
+
+ +

ユーザーの操作が必要ない場合は、提供されたコードを繰り返し実行する setInterval() 関数を使用できます。ゲームを作成したい場合、キーボードまたはマウスのイベントを使用してアニメーションを制御するため setTimeout() を使用できます。{{domxref( "EventListener")}}を設定することで、ユーザーの操作を取得し、アニメーション関数を実行します。

+ +
+

以下の例では、{{domxref("window.requestAnimationFrame()")}} メソッドを使用してアニメーションを制御します。requestAnimationFrame メソッドは、フレームを描画する準備ができた時にシステムがアニメーションフレームを呼び出すことで、よりスムーズで効率的な方法でアニメーションを提供します。通常、コールバック回数は 1 秒あたり 60 回となり、バックグラウンドタブで実行している場合は、レートが低くなることがあります。特にゲームのアニメーションループの詳細については、ゲーム開発ビデオゲームの解剖学を参照してください。

+
+ +

アニメーションする太陽系

+ +

この例は、太陽系の小さなモデルをアニメーションさせます。

+ +
var sun = new Image();
+var moon = new Image();
+var earth = new Image();
+function init(){
+  sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png';
+  moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png';
+  earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png';
+  window.requestAnimationFrame(draw);
+}
+
+function draw() {
+  var ctx = document.getElementById('canvas').getContext('2d');
+
+  ctx.globalCompositeOperation = 'destination-over';
+  ctx.clearRect(0,0,300,300); // clear canvas
+
+  ctx.fillStyle = 'rgba(0,0,0,0.4)';
+  ctx.strokeStyle = 'rgba(0,153,255,0.4)';
+  ctx.save();
+  ctx.translate(150,150);
+
+  // Earth
+  var time = new Date();
+  ctx.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
+  ctx.translate(105,0);
+  ctx.fillRect(0,-12,50,24); // Shadow
+  ctx.drawImage(earth,-12,-12);
+
+  // Moon
+  ctx.save();
+  ctx.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
+  ctx.translate(0,28.5);
+  ctx.drawImage(moon,-3.5,-3.5);
+  ctx.restore();
+
+  ctx.restore();
+
+  ctx.beginPath();
+  ctx.arc(150,150,105,0,Math.PI*2,false); // Earth orbit
+  ctx.stroke();
+
+  ctx.drawImage(sun,0,0,300,300);
+
+  window.requestAnimationFrame(draw);
+}
+
+init();
+
+ + + +

{{EmbedLiveSample("An_animated_solar_system", "310", "310", "https://mdn.mozillademos.org/files/202/Canvas_animation1.png")}}

+ +

アニメ―ションする時計

+ +

この例は、アニメーションする時計で現在時間を表示します。

+ +
function clock(){
+  var now = new Date();
+  var ctx = document.getElementById('canvas').getContext('2d');
+  ctx.save();
+  ctx.clearRect(0,0,150,150);
+  ctx.translate(75,75);
+  ctx.scale(0.4,0.4);
+  ctx.rotate(-Math.PI/2);
+  ctx.strokeStyle = "black";
+  ctx.fillStyle = "white";
+  ctx.lineWidth = 8;
+  ctx.lineCap = "round";
+
+  // Hour marks
+  ctx.save();
+  for (var i=0;i<12;i++){
+    ctx.beginPath();
+    ctx.rotate(Math.PI/6);
+    ctx.moveTo(100,0);
+    ctx.lineTo(120,0);
+    ctx.stroke();
+  }
+  ctx.restore();
+
+  // Minute marks
+  ctx.save();
+  ctx.lineWidth = 5;
+  for (i=0;i<60;i++){
+    if (i%5!=0) {
+      ctx.beginPath();
+      ctx.moveTo(117,0);
+      ctx.lineTo(120,0);
+      ctx.stroke();
+    }
+    ctx.rotate(Math.PI/30);
+  }
+  ctx.restore();
+
+  var sec = now.getSeconds();
+  var min = now.getMinutes();
+  var hr  = now.getHours();
+  hr = hr>=12 ? hr-12 : hr;
+
+  ctx.fillStyle = "black";
+
+  // write Hours
+  ctx.save();
+  ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )
+  ctx.lineWidth = 14;
+  ctx.beginPath();
+  ctx.moveTo(-20,0);
+  ctx.lineTo(80,0);
+  ctx.stroke();
+  ctx.restore();
+
+  // write Minutes
+  ctx.save();
+  ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )
+  ctx.lineWidth = 10;
+  ctx.beginPath();
+  ctx.moveTo(-28,0);
+  ctx.lineTo(112,0);
+  ctx.stroke();
+  ctx.restore();
+
+  // Write seconds
+  ctx.save();
+  ctx.rotate(sec * Math.PI/30);
+  ctx.strokeStyle = "#D40000";
+  ctx.fillStyle = "#D40000";
+  ctx.lineWidth = 6;
+  ctx.beginPath();
+  ctx.moveTo(-30,0);
+  ctx.lineTo(83,0);
+  ctx.stroke();
+  ctx.beginPath();
+  ctx.arc(0,0,10,0,Math.PI*2,true);
+  ctx.fill();
+  ctx.beginPath();
+  ctx.arc(95,0,10,0,Math.PI*2,true);
+  ctx.stroke();
+  ctx.fillStyle = "rgba(0,0,0,0)";
+  ctx.arc(0,0,3,0,Math.PI*2,true);
+  ctx.fill();
+  ctx.restore();
+
+  ctx.beginPath();
+  ctx.lineWidth = 14;
+  ctx.strokeStyle = '#325FA2';
+  ctx.arc(0,0,142,0,Math.PI*2,true);
+  ctx.stroke();
+
+  ctx.restore();
+
+  window.requestAnimationFrame(clock);
+}
+
+window.requestAnimationFrame(clock);
+ + + +

{{EmbedLiveSample("An_animated_clock", "180", "180", "https://mdn.mozillademos.org/files/203/Canvas_animation2.png")}}

+ +

ループする風景

+ +

この例は、左から右へ風景写真をスクロールさせます。Wikipedia からヨセミテ国立公園の画像を使いましたが、キャンバスよりも大きな任意の画像を使用できます。

+ +
var img = new Image();
+
+// User Variables - customize these to change the image being scrolled, its
+// direction, and the speed.
+
+img.src = 'https://mdn.mozillademos.org/files/4553/Capitan_Meadows,_Yosemite_National_Park.jpg';
+var CanvasXSize = 800;
+var CanvasYSize = 200;
+var speed = 30; // lower is faster
+var scale = 1.05;
+var y = -4.5; // vertical offset
+
+// Main program
+
+var dx = 0.75;
+var imgW;
+var imgH;
+var x = 0;
+var clearX;
+var clearY;
+var ctx;
+
+img.onload = function() {
+    imgW = img.width * scale;
+    imgH = img.height * scale;
+
+    if (imgW > CanvasXSize) {
+        // image larger than canvas
+        x = CanvasXSize - imgW;
+    }
+    if (imgW > CanvasXSize) {
+        // image width larger than canvas
+        clearX = imgW;
+    } else {
+        clearX = CanvasXSize;
+    }
+    if (imgH > CanvasYSize) {
+        // image height larger than canvas
+        clearY = imgH;
+    } else {
+        clearY = CanvasYSize;
+    }
+
+    // get canvas context
+    ctx = document.getElementById('canvas').getContext('2d');
+
+    // set refresh rate
+    return setInterval(draw, speed);
+}
+
+function draw() {
+    ctx.clearRect(0, 0, clearX, clearY); // clear the canvas
+
+    // if image is <= Canvas Size
+    if (imgW <= CanvasXSize) {
+        // reset, start from beginning
+        if (x > CanvasXSize) {
+            x = -imgW + x;
+        }
+        // draw additional image1
+        if (x > 0) {
+            ctx.drawImage(img, -imgW + x, y, imgW, imgH);
+        }
+        // draw additional image2
+        if (x - imgW > 0) {
+            ctx.drawImage(img, -imgW * 2 + x, y, imgW, imgH);
+        }
+    }
+
+    // image is > Canvas Size
+    else {
+        // reset, start from beginning
+        if (x > (CanvasXSize)) {
+            x = CanvasXSize - imgW;
+        }
+        // draw aditional image
+        if (x > (CanvasXSize-imgW)) {
+            ctx.drawImage(img, x - imgW + 1, y, imgW, imgH);
+        }
+    }
+    // draw image
+    ctx.drawImage(img, x, y,imgW, imgH);
+    // amount to move
+    x += dx;
+}
+
+ +

以下は、画像をスクロールする {{HTMLElement("canvas")}} です。ここで指定する幅と高さは、JavaScript コードの CanvasXZSize および CanvasYSize 変数の値と一致する必要があることに注意してください。

+ +
<canvas id="canvas" width="800" height="200"></canvas>
+ +

{{EmbedLiveSample("A_looping_panorama", "830", "230")}}

+ +

マウス追跡アニメーション

+ +
<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        <meta http-equiv="X-UA-Compatible" content="ie=edge">
+        <title>Document</title>
+        <script>
+            var cn;
+            //= document.getElementById('cw');
+            var c;
+            var u = 10;
+            const m = {
+                x: innerWidth / 2,
+                y: innerHeight / 2
+            };
+            window.onmousemove = function(e) {
+                m.x = e.clientX;
+                m.y = e.clientY;
+
+            }
+            function gc() {
+                var s = "0123456789ABCDEF";
+                var c = "#";
+                for (var i = 0; i < 6; i++) {
+                    c += s[Math.ceil(Math.random() * 15)]
+                }
+                return c
+            }
+            var a = [];
+            window.onload = function myfunction() {
+                cn = document.getElementById('cw');
+                c = cn.getContext('2d');
+
+                for (var i = 0; i < 10; i++) {
+                    var r = 30;
+                    var x = Math.random() * (innerWidth - 2 * r) + r;
+                    var y = Math.random() * (innerHeight - 2 * r) + r;
+                    var t = new ob(innerWidth / 2,innerHeight / 2,5,"red",Math.random() * 200 + 20,2);
+                    a.push(t);
+                }
+                //cn.style.backgroundColor = "#700bc8";
+
+                c.lineWidth = "2";
+                c.globalAlpha = 0.5;
+                resize();
+                anim()
+            }
+            window.onresize = function() {
+
+                resize();
+
+            }
+            function resize() {
+                cn.height = innerHeight;
+                cn.width = innerWidth;
+                for (var i = 0; i < 101; i++) {
+                    var r = 30;
+                    var x = Math.random() * (innerWidth - 2 * r) + r;
+                    var y = Math.random() * (innerHeight - 2 * r) + r;
+                    a[i] = new ob(innerWidth / 2,innerHeight / 2,4,gc(),Math.random() * 200 + 20,0.02);
+
+                }
+                //  a[0] = new ob(innerWidth / 2, innerHeight / 2, 40, "red", 0.05, 0.05);
+                //a[0].dr();
+            }
+            function ob(x, y, r, cc, o, s) {
+                this.x = x;
+                this.y = y;
+                this.r = r;
+                this.cc = cc;
+                this.theta = Math.random() * Math.PI * 2;
+                this.s = s;
+                this.o = o;
+                this.t = Math.random() * 150;
+
+                this.o = o;
+                this.dr = function() {
+                    const ls = {
+                        x: this.x,
+                        y: this.y
+                    };
+                    this.theta += this.s;
+                    this.x = m.x + Math.cos(this.theta) * this.t;
+                    this.y = m.y + Math.sin(this.theta) * this.t;
+                    c.beginPath();
+                    c.lineWidth = this.r;
+                    c.strokeStyle = this.cc;
+                    c.moveTo(ls.x, ls.y);
+                    c.lineTo(this.x, this.y);
+                    c.stroke();
+                    c.closePath();
+
+                }
+            }
+            function anim() {
+                requestAnimationFrame(anim);
+                c.fillStyle = "rgba(0,0,0,0.05)";
+                c.fillRect(0, 0, cn.width, cn.height);
+                a.forEach(function(e, i) {
+                    e.dr();
+                });
+
+            }
+        </script>
+        <style>
+            #cw {
+                position: fixed;
+                z-index: -1;
+            }
+
+            body {
+                margin: 0;
+                padding: 0;
+                background-color: rgba(0,0,0,0.05);
+            }
+        </style>
+    </head>
+    <body>
+        <canvas id="cw"></canvas>
+    </body>
+</html>
+
+ +
表示例
+ + + + + + + +
+

beyblade

+
+ +

スネークゲーム

+ +
<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width,initial-scale=1">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>Nokia 1100:snake..Member berries</title>
+</head>
+
+<body>
+    <div class="keypress hide">
+        <div class="up" onclick="emit(38)">&#8593;</div>
+        <div class="right" onclick="emit(39)">&#8594;</div>
+        <div class="left" onclick="emit(37)">&#8592;</div>
+        <div class="down" onclick="emit(40)">&#8595;</div>
+    </div>
+    <div class="banner" id="selector">
+        <div>
+            Time :<span id="time">0</span>
+        </div>
+        <div>LousyGames ©</div>
+        <div>
+            Score :<span id="score">0</span>
+        </div>
+        <div class="touch off" onclick="touch(this)">touch</div>
+    </div>
+    <canvas id="main"></canvas>
+</body>
+<style>
+    body {
+        margin: 0;
+        overflow: hidden;
+        background: #000
+    }
+
+    .banner {
+        text-align: center;
+        color: #fff;
+        background: #3f51b5;
+        line-height: 29px;
+        position: fixed;
+        left: 0;
+        top: 0;
+        right: 0;
+        font-family: monospace;
+        height: 30px;
+        opacity: .4;
+        display: flex;
+        transition: .5s
+    }
+
+    .banner:hover {
+        opacity: 1
+    }
+
+    div#selector>div {
+        flex-basis: 30%
+    }
+
+    @keyframes diss {
+        from {
+            opacity: 1
+        }
+
+        to {
+            opacity: 0
+        }
+    }
+
+    .keypress>div {
+        border: dashed 3px #fff;
+        height: 48%;
+        width: 48%;
+        display: flex;
+        align-content: center;
+        justify-content: center;
+        align-self: center;
+        align-items: center;
+        font-size: -webkit-xxx-large;
+        font-weight: 900;
+        color: #fff;
+        transition: .5s;
+        opacity: .1;
+        border-radius: 7px
+    }
+
+    .keypress {
+        position: fixed;
+        width: 100vw;
+        height: 100vh;
+        top: 0;
+        left: 0;
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: space-around;
+        opacity: 1;
+        user-select: none
+    }
+
+    .keypress>div:hover {
+        opacity: 1
+    }
+
+    .touch {
+        background: #8bc34a
+    }
+
+    .off {
+        background: #f44336
+    }
+
+    .hide {
+        opacity: 0
+    }
+</style>
+</html>
+ +

Javascript

+ +
function tmz() {
+        var e = new Date(t),
+            i = new Date,
+            n = Math.abs(i.getMinutes() - e.getMinutes()),
+            o = Math.abs(i.getSeconds() - e.getSeconds());
+        return n + " : " + o
+    }
+
+    function coll(t, e) {
+        return t.x < e.x + e.w && t.x + t.w > e.x && t.y < e.y + e.h && t.h + t.y > e.y
+    }
+
+    function snake() {
+        this.w = 15, this.h = 15, this.dx = 1, this.dy = 1, this.xf = 1, this.yf = 1, this.sn = [];
+        for (var t = {
+            x: w / 2,
+            y: h / 2
+        }, e = 0; e < 5; e++) this.sn.push(Object.assign({}, t)), t.x += this.w;
+        this.draw = function () {
+            var t = d && d.search("Arrow") > -1,
+                e = -1;
+            if (t) {
+                var i = {
+                    ...this.sn[0]
+                };
+                if ("ArrowUp" == d && (i.y -= this.h), "ArrowDown" == d && (i.y += this.h), "ArrowLeft" == d && (i.x -= this.w), "ArrowRight" == d && (i.x += this.w), i.x >= w ? i.x = 0 : i.x < 0 && (i.x = w - this.w), i.y > h ? i.y = 0 : i.y < 0 && (i.y = h), e = fa.findIndex(t => coll({
+                    ...this.sn[0],
+                    h: this.h,
+                    w: this.w
+                }, t)), this.sn.unshift(i), -1 != e) return console.log(e), fa[e].renew(), void (document.getElementById("score").innerText = Number(document.getElementById("score").innerText) + 1);
+                this.sn.pop(), console.log(6)
+            }
+            this.sn.forEach((t, e, i) => {
+                if (0 == e || i.length - 1 == e) {
+                    var n = c.createLinearGradient(t.x, t.y, t.x + this.w, t.y + this.h);
+                    i.length - 1 == e ? (n.addColorStop(0, "black"), n.addColorStop(1, "#8BC34A")) : (n.addColorStop(0, "#8BC34A"), n.addColorStop(1, "white")), c.fillStyle = n
+                } else c.fillStyle = "#8BC34A";
+                c.fillRect(t.x, t.y, this.w, this.h), c.strokeStyle = "#E91E63", c.font = "30px serif", c.strokeStyle = "#9E9E9E", i.length - 1 != e && 0 != e && c.strokeRect(t.x, t.y, this.w, this.h), 0 == e && (c.beginPath(), c.fillStyle = "#F44336", c.arc(t.x + 10, t.y + 2, 5, 360, 0), c.fill()), c.arc(t.x + 10, t.y + 2, 5, 360, 0), c.fill(), c.beginPath()
+            })
+        }
+    }
+
+    function gc() {
+        for (var t = "0123456789ABCDEF", e = "#", i = 0; i < 6; i++) e += t[Math.ceil(15 * Math.random())];
+        return e
+    }
+
+    function food() {
+        this.x = 0, this.y = 0, this.b = 10, this.w = this.b, this.h = this.b, this.color = gc(), this.renew = function () {
+            this.x = Math.floor(Math.random() * (w - 200) + 10), this.y = Math.floor(Math.random() * (h - 200) + 30), this.color = gc()
+        }, this.renew(), this.put = (() => {
+            c.fillStyle = this.color, c.arc(this.x, this.y, this.b - 5, 0, 2 * Math.PI), c.fill(), c.beginPath(), c.arc(this.x, this.y, this.b - 5, 0, Math.PI), c.strokeStyle = "green", c.lineWidth = 10, c.stroke(), c.beginPath(), c.lineWidth = 1
+        })
+    }
+
+    function init() {
+        cc.height = h, cc.width = w, c.fillRect(0, 0, w, innerHeight);
+        for (var t = 0; t < 10; t++) fa.push(new food);
+        s = new snake(w / 2, h / 2, 400, 4, 4), anima()
+    }
+
+    function anima() {
+        c.fillStyle = "rgba(0,0,0,0.11)", c.fillRect(0, 0, cc.width, cc.height), fa.forEach(t => t.put()), s.draw(), document.getElementById("time").innerText = tmz(), setTimeout(() => {
+            requestAnimationFrame(anima)
+        }, fw)
+    }
+
+    function emit(t) {
+        key.keydown(t)
+    }
+
+    function touch(t) {
+        t.classList.toggle("off"), document.getElementsByClassName("keypress")[0].classList.toggle("hide")
+    }
+    var t = new Date + "",
+        d = void 0,
+        cc = document.getElementsByTagName("canvas")[0],
+        c = cc.getContext("2d");
+    key = {}, key.keydown = function (t) {
+        var e = document.createEvent("KeyboardEvent");
+        Object.defineProperty(e, "keyCode", {
+            get: function () {
+                return this.keyCodeVal
+            }
+        }), Object.defineProperty(e, "key", {
+            get: function () {
+                return 37 == this.keyCodeVal ? "ArrowLeft" : 38 == this.keyCodeVal ? "ArrowUp" : 39 == this.keyCodeVal ? "ArrowRight" : "ArrowDown"
+            }
+        }), Object.defineProperty(e, "which", {
+            get: function () {
+                return this.keyCodeVal
+            }
+        }), e.initKeyboardEvent ? e.initKeyboardEvent("keydown", !0, !0, document.defaultView, !1, !1, !1, !1, t, t) : e.initKeyEvent("keydown", !0, !0, document.defaultView, !1, !1, !1, !1, t, 0), e.keyCodeVal = t, e.keyCode !== t && alert("keyCode mismatch " + e.keyCode + "(" + e.which + ")"), document.dispatchEvent(e)
+    };
+    var o, s, h = innerHeight,
+        w = innerWidth,
+        fw = 60,
+        fa = [];
+    window.onkeydown = function (t) {
+        var e = t.key;
+        (e.search("Arrow") > -1 || "1" == e) && (d = t.key), "i" != e && "I" != e || (console.log("inc"), fw -= 10), "d" != e && "D" != e || (console.log("dec"), fw += 10)
+    }, init();
+
+ +
表示例
+ + + + + + + +
+

Snake game

+
+ +

その他のサンプル

+ +
+
A basic ray-caster
+
キーボードを使ってアニメーションをどのように制御するか説明した良いサンプルです。
+
Advanced animations
+
高度なアニメーション技術と物の動きについて見ていきます。
+
+ +

{{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}

-- cgit v1.2.3-54-g00ecf