2014-03-26 4 views
0

가 어떻게 캔버스가최적화 캔버스 애니메이션 (사인 곡선)

var canvas = document.getElementById("sinewave"); 
var points = {}; 
var counter = 0; 
var intensity = 0; 

function f(x, intensity) { 
    return intensity * Math.sin(0.25 * x) + 100; 
} 

if (canvas.getContext) { 
    var ctx = canvas.getContext("2d"); 
    ctx.strokeStyle = '#fff'; 
    ctx.lineWidth = 2; 
    var x = 0, 
     y = f(0,0); 
    var timeout = setInterval(function() { 
     if(counter < 400) { 
      ctx.beginPath(); 
      ctx.moveTo(x, y); 
      x += 1; 
      y = f(x, intensity); 
      points[x] = y; 
      ctx.lineTo(x, y); 
      ctx.stroke(); 
      if (x > 1000) { 
       clearInterval(timeout); 
      } 
     } else { 
      ctx.clearRect(0, 0, 400, 200); 
      ctx.beginPath(); 
      points[x] = y; 
      x += 1; 
      y = f(x, intensity); 
      for(var i = 0; i < 400; i++) { 
       ctx.lineTo(i, points[i + counter - 400]); 
      } 
      ctx.stroke(); 
     } 
     counter++; 

    }, 5); 
} 

답변

0

어떤 생각을 다시 drawen 때 발생하는 약간의 번짐이없는 정현파 렌더링이 코드를 최적화 할 수 있습니다

  1. 을 x == 0 & 강도 == 0이므로 처음 400 개의 그림은 직선 (?)을 형성합니다.

  2. 귀하의 setInterval 시간이 너무 짧습니다 (5ms). 화면이 약 17ms마다 새로 고침되므로 브라우저가 쓸데없이 채우려고하는 간격 호출이 누적됩니다. (당신은 막히고 있어요!).

  3. requestAnimationFrame이 디스플레이 하드웨어와 더 잘 통합되어 있기 때문에 setInterval 대신 새로운 (ish) requestAnimationFrame을 사용하십시오.

여기 예를 리팩토링 코드와 데모 : http://jsfiddle.net/m1erickson/MZ7Ap/

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 
<style> 
    body{ background-color: black; } 
    canvas{border:1px solid red;} 
</style> 
<script> 
$(function(){ 

    var canvas=document.getElementById("canvas"); 
    var ctx=canvas.getContext("2d"); 
    ctx.strokeStyle = '#fff'; 
    ctx.lineWidth = 2; 

    var points = {}; 
    var counter = 0; 
    var intensity = 2; 
    var x = 0; 
    var y = fz(0,0); 

    animate(); 

    function fz(x, intensity) { 
     return intensity * Math.sin(0.25 * x) + 100; 
    } 

    function animate(time){ 

     requestAnimationFrame(animate); 

     draw(counter); 

     counter++; 

    } 

    function draw(counter){ 
     if(counter < 400) { 
      ctx.beginPath(); 
      ctx.moveTo(x, y); 
      x += 1; 
      y = fz(x, intensity); 
      points[x] = y; 
      ctx.lineTo(x, y); 
      ctx.stroke(); 
      if (x > 1000) { 
       clearInterval(timeout); 
      } 
     } else { 
      ctx.clearRect(0, 0, 400, 200); 
      ctx.beginPath(); 
      points[x] = y; 
      x += 1; 
      y = fz(x, intensity); 
      for(var i = 0; i < 400; i++) { 
       ctx.lineTo(i, points[i + counter - 400]); 
      } 
      ctx.stroke(); 
     } 
    } 

}); // end $(function(){}); 
</script> 
</head> 
<body> 
    <canvas id="canvas" width=900 height=300></canvas> 
</body> 
</html> 
+0

AMAZING! 감사합니다. 방정식을 통해 함수의 높이를 제한하는 방법을 제안해도 친절합니까? 그래도 100000의 강도로 캔버스 높이보다 높지는 않습니다. – Leg0

+0

여러분을 환영합니다! 최대/최소 사인 값은 1.00 및 -1.00입니다. 따라서 f()에서 뒤로 작업 : minIntensity = 100 및 maxIntensity = canvas.height-100. 이 최소값/최대 값 이외의 값을 사용하려면 밝기 값을 스케일해야합니다 (x 값이 계산 당 1 픽셀 씩 증가하기 때문에 웨이브가 왜곡됩니다). – markE