2016-03-28 4 views
0

これは本当に簡単ですが、これを行う方法を理解できないようです。私は "Uncaught TypeError:this.resizeCanvasは関数ではありません"というメッセージをChromeのコンソールから取得します。このコードは、アナログ時計を描画するキャンバスのサイズを変更するためのものです。クラス内からDOMを変更できますか?

<編集> はちょうどprotionが>

私に頭痛 < /編集を与えていない、コード全体を貼り付けJAVASCRIPT

function Hands(canvas) 
{ 
    this.angle = 0; 
    this.beginX = canvas.width/2; 
    this.beginY = canvas.height/2; 
    this.endX = 0; 
    this.endY = 0; 
    this.radius = 0; 
    this.length = 0; 
    this.modLength = 0; 
    this.color = ''; 
    this.lineCap = ''; 
    this.lineWidth = 0; 
    this.rotation = (Math.PI * 2)/4; 

    this.draw = function(ctx) 
    { 
     this.length = this.radius - this.modLength; 

     this.endX = this.beginX + Math.cos(this.angle - this.rotation) * this.length; 
     this.endY = this.beginY + Math.sin(this.angle - this.rotation) * this.length; 

     ctx.beginPath(); 
     ctx.moveTo(this.beginX, this.beginY); 
     ctx.lineWidth = this.lineWidth; 
     ctx.strokeStyle = this.color; 
     ctx.lineCap = this.lineCap; 
     ctx.lineTo(this.endX, this.endY); 
     ctx.stroke(); 
    }; 
} 

function AnalogClock() 
{ 
    this.canvas = document.getElementById("clockface"); 
    this.context = this.canvas.getContext('2d'); 

    this.margin = 30; 
    this.rotation = (Math.PI * 2)/4; // Rotate 0 rad to be at top of circle 
    this.centerX = this.canvas.width/2; 
    this.centerY = this.canvas.height/2; 

    this.secondHand = new Hands(this.canvas); 
    this.secondHand.lineWidth = 3; 
    this.secondHand.modLength = 100; 
    this.secondHand.beginX = this.centerX; 
    this.secondHand.beginY = this.centerY; 
    this.secondHand.color = '#ff0000'; 
    this.secondHand.radius = this.canvas.height/2.031; 

    this.minuteHand = new Hands(this.canvas); 
    this.minuteHand.lineWidth = 10; 
    this.minuteHand.modLength = 100; 
    this.minuteHand.beginX = this.centerX; 
    this.minuteHand.beginY = this.centerY; 
    this.minuteHand.color = '#101010'; 
    this.minuteHand.radius = this.canvas.height/2.031; 

    this.hourHand = new Hands(this.canvas); 
    this.hourHand.lineWidth = 16; 
    this.hourHand.modLength = 175; 
    this.hourHand.beginX = this.centerX; 
    this.hourHand.beginY = this.centerY; 
    this.hourHand.color = '#101010'; 
    this.hourHand.radius = this.canvas.height/2.031; 

    this.drawSecondHand = function(s) 
    { 
     this.secondHand.angle = (Math.PI * 2) * (s/60); 
     this.secondHand.draw(this.context); 
    }; 

    this.drawMinuteHand = function(m) 
    { 
     this.minuteHand.angle = (Math.PI * 2) * (m/60); 
     this.minuteHand.draw(this.context); 
    }; 

    this.drawHourHand = function(h) 
    { 
     this.hourHand.angle = (Math.PI * 2) * (h/12); 
     this.hourHand.draw(this.context); 
    }; 

    this.drawDot = function(x, y, radius, radians, color) 
    { 
     this.context.beginPath(); 
     this.context.arc(x, y, radius, 0, Math.PI * 2, false); 
     this.context.fillStyle = color; 
     this.context.fill(); 
    }; 

    this.drawClockFace = function() 
    { 
     var distance = this.centerY - 80; 

     for(i = 0; i < 60; i++) 
     { 
      var targetX = this.centerX + Math.cos(((Math.PI * 2) * (i/60)) - this.rotation) * distance; 
      var targetY = this.centerY + Math.sin(((Math.PI * 2) * (i/60)) - this.rotation) * distance; 

      this.drawDot(targetX, targetY, 3, this.minuteHand.color); 
     } 

     for(i = 0; i < 12; i++) 
     { 
      var targetX = this.centerX + Math.cos(((Math.PI * 2) * (i/12)) - this.rotation) * distance; 
      var targetY = this.centerY + Math.sin(((Math.PI * 2) * (i/12)) - this.rotation) * distance; 

      this.drawDot(targetX, targetY, 8, this.hourHand.color); 
     } 
    }; 

    this.resizeCanvas = function() 
    { 
     this.canvas.width = window.innerWidth - this.margin; 
     this.canvas.height = window.innerHeight - this.margin; 
    }; 

    this.draw = function() 
    { 
     var now = new Date(); 

     this.resizeCanvas(); 
     this.drawClockFace(); 
     this.drawHourHand(now.getHours()); 
     this.drawMinuteHand(now.getMinutes()); 
     this.drawSecondHand(now.getSeconds()); 

     this.drawDot(this.centerX, this.centerY, 10, this.secondHand.color); // Center dot 
    }; 
} 


/******** 
LOAD APP 
*********/ 

// ctx.translate(0.5, 0.5); // Anti-aliasing 

var analogClock = new AnalogClock(); 

function tick() 
{ 
    setInterval(analogClock.draw, 1000); 
    analogClock.draw(); 
} 

document.addEventListener("DOMContentLoaded", function(){ tick(); }); 

HTML

<!DOCTYPE html> 
<html> 
    <head> 
     <style> 
      body { 
       background: #fefefe; 
      } 

      canvas { 
       background: #fefefe; 
      } 
     </style> 
    </head> 
    <body id="root"> 
     <canvas id="clockface"></canvas> 
     <script src="clock.js"></script> 
    </body> 
</html> 
+0

'myClock.resize();' – Igor

+0

'myClock.resize();'? –

+0

それを試しましたが、エラーは持続しました。私の側から打ち明けたタイプミス。 – fimas

答えて

2

は...

function tick() { 
    analogClock.draw(); 
    //setInterval(tick, 1000); - WRONG 
    setTimeout(tick, 1000); // Or preferably use requestAnimationFrame. 
} 

window.addEventListener("load", function() { 
    tick(); 
}); 

しかし、それはFirefoxで非常に悪い実行されます。おそらくrequestAnimationFrameはうまくいくでしょうが、私は指を置くことができないということがあります。しかし、これは現在のresizeCanvasの問題を未定義に戻します。チェックを外してresizeCanvasを呼び出すか直接描画すると、正常に動作します。また、チックが正しくループすると、正常に動作します。

私は、パフォーマンスの問題は、すべてのチックで呼び出されているキャンバスのサイズ変更が原因であると思われます。あなたはおそらくそれをしたくないでしょう。ウィンドウのサイズが変更された場合は、それを呼び出す必要があります。

そして、得られた時計は逆さまになります。あなたの手のオブジェクトでは、これはあなたの問題の

this.rotation = -Math.PI/2; 
+0

本当に、ロード時に一度呼び出すと、varsを設定し、それ以降のサイズ変更でのみ呼び出す必要があります。私はあなたのソリューションがなぜ機能するのか、静かではありませんが、そうしています。私は同様にいくつかの化粧品の修正があります。あなたは正しいと答えます。ありがとうございました:) – fimas

+2

ダニの呼び出しでスタックを埋めるため、パフォーマンスが低下します。代わりに 'setTimeout'を使う必要があります。 –

+0

@PrestonSはい。私は、OPがコードにあるものをコピーしました。もちろん、setTimeoutまたはrequestAnimationFrame経由で行う必要があります。ありがとう:) – ManoDestra

0

変更clock.resize()myClock.resize()。私はこれを行うときは、より多くのこのようなあなたのダニをコーディングする必要が

+0

コードをサイトにコピーしたときに私の側からちょうどタイプミス。あなたは 'myClock.resize()'と言うべきです。編集の有無にかかわらず、エラーはまだ存在します。 – fimas

1

ルートがsetTimeoutsetIntervalによって呼び出される関数は、常に現在のwindowthisオブジェクトを持っているということです...それを修正します。オブジェクトのメソッドに、これらの機能のいずれかを使用するときは、ラッパー関数を使用するか、代わりにあなたが書くべきapply()

//wrapper 
setTimeout(function(){analogClock.draw();}, 1000); 

または

//apply 
setTimeout(function(){analogClock.draw.apply(analogClock), 1000); 

を使用する必要があります:

function tick() 
{ 
    analogClock.draw(); 
} 

document.addEventListener("DOMContentLoaded", function(){ setInterval(tick, 1000); }) 

または

function tick() 
{ 
    analogClock.draw(); 
    setInterval(analogClock.draw.apply(analogClock), 1000); 
} 

document.addEventListener("DOMContentLoaded", function(){ tick(); }); 
関連する問題