JavaScriptのCANVASでアニメーションを表示する方法とエラーの解決方法

このQ&Aのポイント
  • JavaScriptのCANVASを使用してアニメーションを表示しようとした際に、エラーが発生してしまう問題があります。
  • エラーメッセージは「ReferenceError: this.ctx is not defined」と表示され、エラーの行は下から3行目です。
  • 問題の原因は、drawAnime関数内でのthis.ctxの定義が正しく行われていないことにあります。
回答を見る
  • ベストアンサー

this.ctx is undefined

皆様のお知恵を拝借いたしたく。 JavaScriptのCANVASでアニメーションを表示したく、 setIntervalで1秒にして、絵を描こうとしたところです。 ところが、以下のプログラムを実施しても、 1秒ごとに、 "ReferenceError: this.ctx is not defined" というエラーが表示されます。エラーの行は下から3行目です。 ですが、一応「テストです」という文字は表示されます。 なぜこのエラーがでるかがわからず・・・・ アドバイスいただけないでしょうか。よろしくおねがいします。 ---------------------------- onload = function() { var layer1 = document.getElementById('layer1'); if ( ! layer1 || ! layer1.getContext ) { return false; } var lay1ctx = layer1.getContext('2d'); setInterval(drawAnime, 1000); drawAnime(layer1, lay1ctx); }; function drawAnime(layer1, lay1ctx){ var SSESocArc = new SocArc(lay1ctx); SSESocArc.drawArc(50); } var SocArc = function (ctx){ this.ctx = ctx; } SocArc.prototype.drawArc = function(){ this.ctx.font = "20px 'Ariel bold'"; ← エラーはココ this.ctx.fillText("テストです", 100, 100); }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

直接エラーが出ているのはthis.ctx.fontですが、そのメソッドを呼び出している部分が異なります。 setInterval(drawAnime, 1000); /* 1秒ごとにエラーが出る部分 */ drawAnime(layer1, lay1ctx); /* テストです という文字を表示する部分(プログラム開始時に1回だけ実行) */ -------------- >setInterval(drawAnime, 1000); この書き方でのsetIntervalから呼び出されるdrawAnime()には引数が渡りません。 そのため、 drawAnime関数のコード >function drawAnime(layer1, lay1ctx){ >var SSESocArc = new SocArc(lay1ctx); >SSESocArc.drawArc(50); >} この時のlay1ctxはundefinedですので、 >var SocArc = function (ctx){ >this.ctx = ctx; >} このコンストラクタで生成されるthis.ctxはundefinedとなります。 ------------------------------ 修正案 なお、同じ内容で描画するだけですので、1回しか描かれていないような見え方になります。 var SSESocArc; /* グローバル変数に変更 */ onload = function() { var layer1 = document.getElementById('layer1'); if ( ! layer1 || ! layer1.getContext ) { return false; } var lay1ctx = layer1.getContext('2d'); SSESocArc = new SocArc(lay1ctx); /* オブジェクトを生成して描画の準備 */ drawAnime(); /* 最初の描画 */ setInterval(drawAnime, 1000); /* 1秒ごとに描画を繰り返す */ }; /* インターバルで呼び出す関数ではオブジェクトの生成は行わずに、描画だけを行う */ function drawAnime(layer1, lay1ctx){ SSESocArc.drawArc(50); } var SocArc = function (ctx){ this.ctx = ctx; } SocArc.prototype.drawArc = function(){ this.ctx.font = "20px 'Ariel bold'"; ← エラーはココ this.ctx.fillText("テストです", 100, 100); }

nsonoda
質問者

お礼

アドバイスありがとうございます。 確かにsetIntervalは引数を渡せない・・という話をWebで見たことが有りまりた! 検索したところ、以下のサイトが見つかりました。 http://www.gravity-works.jp/gravica/web/js/003755.html これを参考に、 setInterval(function(){ drawAnime(canvas, mainctx, layer1, lay1ctx, layer2, lay2ctx); }, 40); という無名関数の形にしたら、うまくいくようになりました。 どうもありがとうございました。 以上

その他の回答 (1)

  • Kaneyan-R
  • ベストアンサー率42% (1241/2889)
回答No.1

シングルクォートの位置がおかしいと思うのだけど・・・ this.ctx.font = "bold 20px 'Ariel''"; で、どう?

nsonoda
質問者

お礼

アドバイスありがとうございます。 特にこのシングルクォーテーションの位置は これでも問題ないようです。

関連するQ&A

  • html5canvasの文字枠のずれ

    html5のcanvasで、枠付きの文字列を描画しようとしたら、表示がおかしくなったのですが、理由がわかりません。ブラウザはchromeです。 一部のフォントとサイズのときだけ起きるのですが、それ以外で作れば問題ないのでしょうか。 <canvas id="canvas" width="500" height="500"></canvas> <script type="text/javascript"> var canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); ctx.lineWidth=2; ctx.font = "bold 22px 'MS P明朝'" ctx.strokeStyle = 'rgba(255, 0, 0, 1)'; ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.strokeText("aa0.3", 10, 25); ctx.fillText("aa0.3", 10, 25); </script>

  • Canvasのメモリーリーク疑いについて

    現在、Canvasを使ってペイントソフトにあるような「レイヤー」的な ことが出来ないか実験をしています。 (レイヤー数に関しては、最大で24程度を考えています。) 環境等は、以下の通りです。 OS:Windows XP Pro(SP3) 32bit メモリ:2GB ブラウザ:各ブラウザの最新版(FireFox,Chrome,Opera,safariも実施予定です。) 実験の結果、大量のレイヤーを使用した場合に ついてメモリーリーク的な問題が発生しているような感じがしています。 もちろん、レイヤーなのである程度のメモリ消費は承知の上だったのですが タブを閉じた際や描画してから時間が経過してもメモリ使用量が減少しないのは 使用上問題がありますので質問させて頂くことになった次第です。 (なお、レイヤー数を削減すると、比例してメモリ使用量も削減されていました。 メモリ使用量に関しては、タスクマネージャのプロセスタブのメモリ使用量 で見ています。) で、この問題が特に顕著なのが、Firefoxです。 私見では、1レイヤーにつき1MB程度消費してしまう感じです。 他のブラウザ(クローム、オペラ)では一時的にメモリ使用量は 増加しますが、時間が経過するとだいたい元にもどります。 なお、実験は以下のようなサンプルを作成して行っています。 (途中省略しています。) ご教授して頂きたい点は、以下になります。 ■メモリーリークが起きている場合の対処方法 (特にFirefoxにおける対処方法) ■Canvasを使用しない場合の代替案 宜しくお願い致します。 <html> <head> <script> function draw() { canvas = document.getElementById("g0"); if(!canvas || !canvas.getContext) return false; ctx = canvas.getContext('2d'); ctx.font = "15px 'MS Pゴシック'"; ctx.fillStyle = "black"; ctx.fillText("aaa", 100, 100); canvas = document.getElementById("g1"); if(!canvas || !canvas.getContext) return false; ctx = canvas.getContext('2d'); ctx.font = "15px 'MS Pゴシック'"; ctx.fillStyle = "black"; ctx.fillText("bbb", 150, 150); canvas = document.getElementById("g23"); if(!canvas || !canvas.getContext) return false; ctx = canvas.getContext('2d'); ctx.font = "15px 'MS Pゴシック'"; ctx.fillStyle = "black"; ctx.fillText("eee", 300, 300); } function start() { draw(); } </script> </head> <body onload="start()"> <body onload="start()"> <canvas height="500" width="500" class="g" id="g0"></canvas> <canvas height="500" width="500" class="g" id="g23"></canvas> </body> </html>

  • Notice:Undefined index が。

    教えて下さい。 01: <?php 02: class Reload { 03: var $id; 04: var $val; 05: var $flag; 06: function Reload($id = 'RELOAD') { 07: $this->id = $id; 08: if ($_GET[$this->id]) 09: $this->val = $_GET[$this->id]; 10: elseif ($_POST[$this->id]) 11: $this->val = $_POST[$this->id];       以下略 こういういうコードがある本に出ているのですが、これをCentOS 5.4で include したスクリプトを実行すると、 Notice: Undefined index: ID in /xxx/abc.php on line 8 (および on line 10 にも ) と警告が出ます。 この警告をなくすために、id=""; を 3行目の下に入れてみると、 Parse error: syntax error, unexpected T_VARIABLE, expecting T_FUNCTION in /xxx/abc.php on line 4 (id=""; を挿入した行) となります。 なお、windows7 で xampp 上でテストしているときは、上記スクリプト(id=""; をする前)でも不具合は出なかったのですが、対処法が分からず途方に暮れています・・・。  どのように修正すればよいでしょうか。  よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • JavaScript/CANVASでの画像読込不可

    JavaScriptで、Canvas上で、透過GIFファイルを表示しようとしています。 (JSでは2週間ほど勉強しておる初心者です。皆様のアドバイス賜りたくよろしくおねがいします。) オリジナルのPictureクラスを以下のように宣言し、 --------------------------------------------- // pictureクラス var Picture = function(ctx, picture, locX, locY, width, height, canvas){ this.ctx = ctx; this.picture = picture; this.locX = locX; this.locY = locY; this.width = width; this.height = height; this.canvas = canvas; var img = new Image(); this.img = img; this.img.src = this.picture; } Picture.prototype.drawPicture = function(){ this.img.onload = function(){ ★ this.ctx.drawImage(this.img, this.locX, this.locY, this.width, this.height); } } ---------------------------------------------------------- 以下のように使用しても、 ------------------------------------------ var Container1 = new Picture(mainctx, "画像ファイル.gif", 42, 80, 100, 50, maincanvas); Container1.drawPicture(); ------------------------------------------ 以下のエラーがでます。(Firefox上で確認) ---------------------- TypeError: this.ctx is undefined (エラー行は★の書いている行) ---------------------- ちなみに、drawPicture関数を ---------------------- Picture.prototype.drawPicture = function(){ this.ctx.drawImage(this.img, this.locX, this.locY, this.width, this.height); } ---------------------- と変更すれば、エラーはなくなりますが、 画像は出るときと出ないときがあります。何度か再読込すれば表示されます。 きっと thisの使い方が間違っている(=理解していない)のではないかと 思うのですが、いかがでしょうか? すみませんが、うまく動く方法をご教示頂ければうれしいです。よろしくおねがいします。 以上

  • javascriptのタイプミス

    javascript初心者です。以下のコードでどこにミスがあるのか 解りません。どこにあるのでしょうか? このソースをエディタに 貼ると見やすくなると思います。 <!DOCTYPE html> <html> <head> <title>SnakeBite</title> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script type="text/javascript"> var W, H, S = 20; var snake = [ ], foods = [ ]; var keyCode = 0; var point = 0; var timer = NaN; var ctx; // pointオブジェクト function Point(x,y) { this.x = x; this.y = y; } //初期関数 function init() { var canvas = document.getElementById('field'); W = canvas.width / S; H = canvas.height / S; ctx = canvas.getContext('2d'); ctx.font = "20px sans-serif"; //蚊の初期化 snake.push(new Point(W / 2, H / 2)); //餌の初期化 for (var i = 0 ; i < 10 ; i++) { addFood(); } timer = setInterval("tick()", 200); window.onkeydown = keydown; } //餌の追加 function addFood() { while (true) { var x = Math.floor(Math.random() * W); var y = Math.floor(Math.random() * H); if (isHit(foods, x, y) || isHit(snake, x, y)) { continue; } foods.push(new Point(x, y)); break; } } //衝突判定 function isHit(data, x, y) { for (var i = 0 ; i < data.length ; i++) { if (data[i].x==x && data[i].y==Y) { return true; } } return false; } function moveFood(x, y) { foods =foods. filter(function (p){return (p.x !=x || p.y !=y);}); addFood(); } function tick() { var x = snake[0].x; var y = snake[0].y; switch (keyCode) { case 37: x--; break; //左 case 38: y--; break; //上 case 39: x++; break; //右 case 40: y++; break; //下 default: paint(); return; } //自分or壁に衝突 if(isHit(snake,x,y) || x<0 || x>=W || y<0 || y>=H ) clearInterval(timer); paint(); return; } //頭を先頭に追加 snake.unshift(new Point(x,y)); if(isHit(foods, x, y)) { point +=10; //餌を食べた moveFood(x,y); }else{ snake.pop(); //食べていない→しっぽを解除 } paint(); } function paint() { ctx.clearRect(0,0,W * S, H * S); ctx.fillStyle = "rgb(256,0,0)"; ctx.fillText(point, S, S * 2); ctx.fillStyle = "rgb(0,0,255)"; foods.forEach(function (p) { ctx.fillText("+", p.x * S, (p.y + 1) * S);}); snake.forEach(function (p) { ctx.fillText("*", p.x * S, (p.y + 1) * S); }); } function keydown(event) { keyCode = event.keyCode; } </script> </head> <body onload="init()"> <canvas id="field" width="400" height="400" style="background:#cccccc"> </canvas> </body> </html>

  • javascriptのcanvasについて

    先日こちらで質問させて頂き、頂いた回答をもとに javascriptのcanvasについて勉強を続けていて、 canvasを2つ重ねたカラーシミュレーションのようなものを作りたいと考えています。 先日教えて頂いた内容をもとに 下記のような記述で2枚目のcanvasの画像を入れ替えることや、 色を変更することは出来ました。 ただ、「進む」ボタンや「戻る」ボタンを押したときに 色がもとの色に戻ってしまうので、色は固定されたまま(この記述でいうと茶色や赤)で 画像を入れ替える方法がわからずにいます。 なにか良い方法はないでしょうか。 <style type="text/css"> .canvas001 { position: absolute; top:100px; left:0px; } .canvas002{ position: absolute; top:100px; left:0px; } </style> <script> onload = function() { image1(); image2(); image3();}; function image1() { var cnvs = document.getElementById('canvas1'); var ctx = cnvs.getContext('2d'); var img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0); }; img.src = "face.png"; }; function image2() { var cnvs = document.getElementById('canvas2'); var ctx = cnvs.getContext('2d'); var img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0); }; img.src = "hair1.png"; }; var src = [  'hair1.png',  'hair2.png',  'hair3.png' ]; var currentIndex = 0; var currentImage; function hair(){ var img = currentImage = new Image(); img.onload = function() { if(currentImage === img){ var cnvs = document.getElementById('canvas2'); var ctx = cnvs.getContext('2d'); ctx.clearRect(0, 0, cnvs.offsetWidth, cnvs.offsetHeight); ctx.drawImage(img, 0, 0); } }; img.src = src[currentIndex]; } window.back = function(){ currentIndex = (currentIndex - 1 + src.length) % src.length; hair(); } window.foward = function(){ currentIndex = (currentIndex + 1) % src.length; hair(); } function black(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 35; idata[ i*4 + 1 ] = 24; idata[ i*4 + 2 ] = 21; } ctx.putImageData(imagedata,0,0); } function brown(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 140; idata[ i*4 + 1 ] = 96; idata[ i*4 + 2 ] = 37; } ctx.putImageData(imagedata,0,0); } function red(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 182 ; idata[ i*4 + 1 ] = 0; idata[ i*4 + 2 ] = 5; } ctx.putImageData(imagedata,0,0); } </script> <body> <div> <div class="canvas001"><canvas id="canvas1" height="300"></canvas></div> <div class="canvas002"><canvas id="canvas2" height="300"></canvas></div> </div> <div> <form><div> <INPUT TYPE=button NAME="submit" VALUE="戻る" onClick="back()"> <INPUT TYPE=button NAME="submit" VALUE="進む" onClick="foward()"> </div></form> </div> <img src="btn_black.png" onclick="black()" > <img src="btn_brown.png" onclick="brown()" > <img src="btn_red.png" onclick="red()" > </body>

  • JavaScript thisとvarの違い

    以下のスクリプトをRhino 1.7 で実行しました。 var a = 1; this.a = 2; function MyFunc() { var a = 3; this.a = 4; print(a); } var func = new MyFunc(); print(a); print(this.a); print(func.a); 結果は以下の通りです。 3 2 2 4 1行目と4行目の結果が違います。 トップレベル(2と3行目)ではthisとvarの値が同じなのに1と4行目の値が違うのは、どのような理由でしょうか? JavaScriptの動作から含めて、教えていただければ幸いです。 よろしくお願いします。

  • JavaScriptでのアニメーション

    JavaScriptで書いたアニメーションをHTML5上で動かそうとしているのですが、うまくいきません。いろいろなサイトで調べましたが原因がわからなかったのでどなたか解決法を教えてください。 任意の値X,Yを入力、これを始点の座標としてそこからランダムな色の円が動くというアニメーションを作りたいです。しかし、X,Yの値を任意に入力させようとするとアニメーションそのものが動かなくなってしまいます。座標をあらかじめ指定しておくとうまく動くのですが……。 任意の値を入れてもきちんと動くように直したいのですが、方法がわかりません。どなたかご教授願います。 以下コード。これより上と下は省略してあります。 <script type="text/javascript"> var speedX = 3.0;   var speedY = 4.0; var locX = parseInt(document.getElementById("x").value); var locY = parseInt(document.getElementById("y").value);  //locX,locYを予め指定しておくとその位置からきちんとアニメーションが動くが、上のようにすると動かなくなる var ctx; function anim(){ var canvas = document.getElementById('mycanvas'); if (canvas.getContext){ ctx = canvas.getContext('2d'); setInterval(draw, 60); } } function draw(){ ctx.globalCompositeOperation = "source-over"; var r = parseInt(Math.random() * 255); var g = parseInt(Math.random() * 255); var b = parseInt(Math.random() * 255); var alpha = Math.random(); var rgba = "rgba("+r+", "+g+", "+b+", "+alpha+")"; ctx.fillStyle = rgba; ctx.fill(); ctx.globalCompositeOperation = "lighter"; locX += speedX; locY += speedY; if(locX < 0 || locX > 800){ speedX *= -1; } if(locY < 0 || locY > 600){ speedY *= -1; } ctx.beginPath(); ctx.fillStyle = rgba; ctx.arc(locX, locY, 5, 0, Math.PI*2.0, true); ctx.fill(); } </script> </head> <body> <p><label>X </label><input id="x"> <label>Y </label><input id="y"> <button type=button onclick="anim();">start</button></p>

  • 2つの図を重ねて表示したい

    HTMLもJavaScriptも初心者です。 *.png の図と canvas に書いた図を重ねて表示したいのですが、canvas に書いた図が *.png に隠れて表示されません。 コーディングは次のとおりです。 <html> <title>figures</title> <!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]--> </head> <body> <div id=lyrwall style="position:absolute; left:20px; top:20px;"> <img src=figure.png> </div> <canvas id="canvassample" width="500" height="500"> <script type="text/javascript"> onload = function() { draw(); }; function draw() { var canvas = document.getElementById('canvassample'); if ( ! canvas || ! canvas.getContext ) { return false; } /* 2Dコンテキスト */ var ctx = canvas.getContext('2d'); /* 線を引く */ ctx.beginPath(); ctx.moveTo(20, 20); ctx.lineTo(480, 480); ctx.stroke(); } </script> </canvas> </body> </html> 直線のうち、figure.png と重なる部分が表示されません。表示されるようにするにはどうすればいいのでしょうか。よろしくお願いいたします。

    • ベストアンサー
    • HTML
  • is not a functionというエラー

    jqueryのスクリプトを書いていたところ $(function () { var wrapper = $("#main"); var wrapperWidth; var blocks = []; NewBlocks(blocks, wrapper.children()); function NewBlocks(blocks, elements) { for (var i = 0; i < elements.length; i++) { var element = elements[i]; var block = new Block(element); blocks.push(block) } } function Block(element) { this.element = element; element.style.margin = "10px"; this.init(); } Block.prototype = { init: function () { this.width = this.element.offsetWidth; this.height = this.element.offsetHeight; } } }); 上記スクリプトを実行すると「this.init is not a function」というエラーが出てしまいます。 一体何をどう間違っているせいでエラーが出るのか、どうかご教授いただけますでしょうか。