2012-06-22 2 views
5

방금 ​​HTML5 캔버스로 게임을 시작 했으므로 몇 가지 게임을 만들려고했습니다. 그러나 최대한 빨리 마우스가 좌표를 렌더링 시작, 그것은 거의 중단 연마 : 38 개 라인과 텍스트, 아니, 그것을 처리 할 수 ​​있어야 렌더링 내가 한 모든HTML5 캔버스를 매우 느리게 다시 그려야합니다.

http://jsfiddle.net/mnpenner/zHpgV/

입니까?

내가 잘못 했나요? 나는 30 FPS에서 렌더링 할 수 있기를 원합니다. 그러나 이와 같은 것을 위해 나는 1000 초를 그릴 수 있다고 기대합니다.

아니면 그냥 잘못된 도구를 사용하고 있습니까? 작업을 위해 WebGL을 사용하고 있습니까? 왜 다른 하나보다 훨씬 느린가?

String.prototype.format = function() { 
 
    var args = arguments; 
 
    return this.replace(/\{(\d+)\}/g, function(m, n) { 
 
     return args[n]; 
 
    }); 
 
}; 
 
var $canvas = $('#canvas'); 
 
var c = $canvas[0].getContext('2d'); 
 
var scale = 20; 
 
var xMult = $canvas.width()/scale; 
 
var yMult = $canvas.height()/scale; 
 
var mouseX = 0; 
 
var mouseY = 0; 
 
c.scale(xMult, yMult); 
 
c.lineWidth = 1/scale; 
 
c.font = '1pt Calibri'; 
 

 
function render() { 
 
    c.fillStyle = '#dcb25c'; 
 
    c.fillRect(0, 0, scale, scale); 
 
    c.fillStyle = '#544423'; 
 
    c.lineCap = 'square'; 
 
    for (var i = 0; i <= 19; ++i) { 
 
     var j = 0.5 + i; 
 
     c.moveTo(j, 0.5); 
 
     c.lineTo(j, 19.5); 
 
     c.stroke(); 
 
     c.moveTo(0.5, j); 
 
     c.lineTo(19.5, j); 
 
     c.stroke(); 
 
    } 
 
    c.fillStyle = '#ffffff'; 
 
    c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5); 
 
} 
 
render(); 
 
$canvas.mousemove(function(e) { 
 
    mouseX = e.clientX; 
 
    mouseY = e.clientY; 
 
    render(); 
 
});
<canvas id="canvas" width="570" height="570"></canvas>

답변

7

여기 코드가 훨씬 개선되었습니다.

  • 연속 대신 중지 beginPath와 함께 새로운 길을 만드는 경로에 추가 :

    http://jsfiddle.net/zHpgV/3/

    은 여기가 변경 당신이 고려해야 할 것들의 고장입니다. 이것은 지금까지 가장 큰 성과 킬러입니다. 수천 가지의 라인 세그먼트가 절대로 나오지 않는 길로 끝나고 있습니다.

  • 동일한 경로를 초기화 할 때 한 번만 만들어야 할 때 계속해서 반복해서 만듭니다. 즉, render으로 전화해야하는 유일한 전화 번호는 stroke입니다. lineTo/moveTo에 다시 전화 할 필요는 없으며 확실히 계속해서 전화 할 필요가 없습니다. 이상과 주 1

을 통해 라인 캡을 설정 CSS 배경

  • 을 배경을 다시 그리기 루프
  • 에 대한 내부의 stroke 대신 설정 한 경로에
  • 두 번 쓰다듬어 1.
  • 주의 참조 : 응용 프로그램에 둘 이상의 경로가있을 계획이라면 변경되지 않으므로이 경로를 캐시해야합니다. 나는 그것을하는 방법에 대한 지침서가있다 here.

    물론 배경을 만들기 위해이 모든 작업을 수행하는 경우 PNG로 저장해야하며 CSS 배경 이미지를 사용해야합니다. 그래서 같이

    :

    http://jsfiddle.net/zHpgV/4/ 그런 다음 갑자기 루틴을 렌더링 오히려 작은 :

    function render() { 
        c.clearRect(0, 0, scale, scale); 
        c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5); 
    } 
    
  • +0

    나는 경로가 그 일을 몰랐어요! 나는'path' 객체를 갖는 것이 더 직관적이었을 것이라고 생각한다. 왜 그렇게 느린 지 지금 생각합니다. 고마워요! – mpen

    +3

    HTML5 Canvas 스펙에 경로 객체가 있습니다. 앞으로 경로를 만들고'drawPath'를 호출 할 수 있습니다. 그러나 아직 어떤 브라우저도 구현되지 않았으므로 몇 달이 지나야 사용할 수 있습니다. 언젠가 구입하십시오! –

    7

    당신은 모든 애니메이션 프레임에서 전체 그리드를 그릴 필요가 없습니다. 그것을 다른 기본 캔버스에 놓으십시오 ("레이어"라고하는 것이 일반적이지만 별도의 캔버스 요소 임). 따라서 좌표 만 다시 그릴 수 있습니다. 여기

    <div id="canv"> 
    <canvas id="bgLayer" width="500" height="500" style="z-index: 0"></canvas> 
    <canvas id="fgLayer" width="500" height="500" style="z-index: 1"></canvas> 
    </div> 
    

    내가 계층 캔버스와 함께 놀았 던 the example입니다. 아래쪽 캔버스에 그려진 표가 공이 위쪽 캔버스에 그려져 있습니다. 이것은 단지 놀이터이기 때문에, 예를 들어 모든 공을 다른 숨겨진 캔버스에 한 번만 그리고 성능을 향상 시키려면 getImageData/putImageData을 사용하는 등 수정하고 최적화하는 것이 많습니다.

    또한 캔버스를 업데이트하려면 requestAnimationFrame을 사용하는 것이 좋습니다. 귀하의 예는 모든 마우스 움직임에 대신 그려지는데, 이것은 훨씬 더 자주 필요합니다 (물론 마우스가 움직일 때).

    캔버스 성능 향상에 좋은 article가 있습니다. 또한,이 주제에 큰 SO post가 있습니다.

    +0

    는 말 그대로 캔버스 요소를 레이어 의미 알아 내기 위해 잠시 나를했다. "레이어"는 캔버스 컨텍스트 내의 개념이라고 생각했습니다. 좋은 생각이야. 팁 주셔서 감사! – mpen

    +0

    죄송합니다. 다른 사람을 혼동하지 않도록 변경했습니다. –

    +1

    이것들은 좋은 코멘트입니다 만,이 경우에는 발견 할 수없는 또 다른 문제가 있습니다. 매우 빠른 애니메이션으로 훨씬 더 복잡한 작업을 수행 할 수 있습니다. 이중 버퍼링에 신경 쓰지 않아도됩니다. –

    9

    나는 더블 버퍼링에 대해 걱정하지 않고도 매우 빠른 애니메이션으로 훨씬 더 복잡한 것들을 그릴 때이 코드의 속도가 느리다는 것에 놀랐다.

    그래서 좀 더 보니 예상대로 버그가 발견되었습니다.

    주된 문제는 드로잉 경로의 누적입니다.

    하나의 경로를 그릴 때마다 c.beginPath();을 추가하십시오.

    이제는 비행 거리가되었음을 증명하기 위해 fast rendering of the same thing입니다.

    캔버스 드로잉 이며 애니메이션에 사용할 수 있습니다.

    관련 문제