2010-08-11 52 views
1

我想在瀏覽器中使用canvas元素創建基本頻閃燈。我期待setInterval繼續調用changeBG函數來改變爲隨機背景顏色。這個函數可以獨立工作,但不能在setInterval調用時使用。我試圖在firebug中拉起這個頁面,它告訴我顏色是未定義的。這是有問題的代碼。setInterval和未定義參數的問題

<html> 
<head> 
    <title>Strobe!</title> 
    <link rel="stylesheet" type="text/css" href="reset.css" /> 
    <script type="text/javascript"> 
     function changeBG(colors,ctx,canvas) {     
      ctx.fillStyle = colors[Math.floor(Math.random()*colors.length)] 
      ctx.fillRect(0,0,canvas.width,canvas.height) 
     } 

     function eventLoop() { 
      var colors = ['#000000','#ff0000','#00ff00','#0000ff','#ffff00','#ff00ff','#00ffff'] 
      var canvas = document.getElementById('mainCanvas') 
      var ctx = canvas.getContext('2d') 
      canvas.width = window.innerWidth 
      canvas.height = window.innerHeight 
      //changeBG(colors,ctx,canvas) 
      setInterval("changeBG(colors,ctx,canvas)", 1000);    
     } 
    </script> 
</head> 
<body onload="eventLoop()"> 
    <canvas id="mainCanvas" width="800" height="600"> 
    </canvas> 
</body> 

我是新來的JavaScript,因此任何見解什麼那麼將高度讚賞。

回答

6

你的代碼會工作。因爲它在一個字符串中,所以它不能在你試圖使用的變量上創建一個閉包。

試試這個:

setInterval(function() { 
    changeBG(colors,ctx,canvas); 
}, 1000)​;​ 

使用這種方法,你傳遞一個匿名函數給setInterval。它將在每個間隔內調用一次該函數,在本例中爲1000毫秒。

該函數可以使用顏色,ctx和canvas變量,因爲它們存在於函數聲明的範圍中。這將創建一個閉包,以便這些變量在我們反覆調用時仍然存在(就我們的匿名函數而言)。

現在,您可能只需使用此代碼即可。爲了進一步理解,我建議研究匿名函數和閉包。

+1

只是爲了OP的完整性:如果您將'colors','ctx'和'canvas'變量聲明爲全局變量,而不使用'var',則代碼有效。爲什麼?因爲變數現在是全球性的。每當有人這樣做時,上帝會殺死一隻小貓(幾乎)。 – Chubas 2010-08-11 21:29:58

+1

非常感謝。我曾經與死貓一起試過這個版本,但我的良知無法接受。 – 2010-08-11 21:52:10

+1

@Chubas:正確。我會提到的,但忘了! – EndangeredMassa 2010-08-11 22:32:26

-1

試試這個 修訂 setInterval(function(){changeBG(colors,ctx,canvas)}, 1000);

+0

+1對我來說很不錯 – 2010-08-11 21:11:46

+1

我不認爲你需要在這個例子中的匿名函數聲明的參數。這將阻止使用現有變量,因爲該函數將期望它們作爲輸入並將它們視爲未定義(如果未提供)。 – 2010-08-11 21:26:48

+0

是的,我們不需要重新聲明它... – shox 2010-08-11 22:18:42

0

您可以直接傳遞一個函數,而不是字符串來評估,如

setInterval(function(){changeBG(colors,ctx,canvas)}, 1000); 

好運挑起癲癇的人

0

問題的根源當間隔代碼執行時,變量作用域,顏色和其他變量不在作用域中。

試試這個:如果你不是傳遞字符串給setInterval

<html> 
<head> 
<title>Strobe!</title> 
<link rel="stylesheet" type="text/css" href="reset.css" /> 
<script type="text/javascript">   
    function eventLoop() { 
     var colors = ['#000000','#ff0000','#00ff00','#0000ff','#ffff00','#ff00ff','#00ffff'] 
     var canvas = document.getElementById('mainCanvas') 
     var ctx = canvas.getContext('2d') 
     canvas.width = window.innerWidth 
     canvas.height = window.innerHeight    
     setInterval(function() {     
      ctx.fillStyle = colors[Math.floor(Math.random()*colors.length)] 
      ctx.fillRect(0,0,canvas.width,canvas.height) 
     }, 1000);    
    }  
</script> 
</head> 
<body onload="eventLoop()"> 
    <canvas id="mainCanvas" width="800" height="600"> 
    </canvas> 
</body>