내가하고 싶은 것은 버퍼에 그래픽을 그린 다음 캔버스에 그대로 복사하여 애니메이션을 수행하고 깜박임을 피할 수 있도록하는 것입니다. 하지만이 옵션을 찾을 수 없습니다. 내가 어떻게 할 수 있는지 아는 사람 있나요?
답변
다음의 유용한 링크는 이중 버퍼링 사용의 예와 장점을 보여주는 것 외에도 html5 canvas 요소 사용에 대한 몇 가지 다른 성능 팁을 보여줍니다. 여기에는 브라우저 전반의 테스트 결과를 Browserscope 데이터베이스로 집계하는 jsPerf 테스트에 대한 링크가 포함되어 있습니다. 이렇게하면 성능 팁이 확인됩니다.
http://www.html5rocks.com/en/tutorials/canvas/performance/
귀하의 편의를 위해 기사에서 설명한대로 효과적인 이중 버퍼링의 최소한의 예를 포함했습니다.
// canvas element in DOM
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');
// buffer canvas
var canvas2 = document.createElement('canvas');
canvas2.width = 150;
canvas2.height = 150;
var context2 = canvas2.getContext('2d');
// create something on the canvas
context2.beginPath();
context2.moveTo(10,10);
context2.lineTo(10,30);
context2.stroke();
//render the buffered canvas onto the original canvas element
context1.drawImage(canvas2, 0, 0);
답변
매우 간단한 방법은 동일한 화면 위치에 두 개의 캔버스 요소를두고 표시해야하는 버퍼의 가시성을 설정하는 것입니다. 숨겨진 그림을 그리고 완료되면 뒤집습니다.
일부 코드 :
CSS :
canvas { border: 2px solid #000; position:absolute; top:0;left:0;
visibility: hidden; }
JS에서 뒤집기 :
Buffers[1-DrawingBuffer].style.visibility='hidden';
Buffers[DrawingBuffer].style.visibility='visible';
DrawingBuffer=1-DrawingBuffer;
이 코드에서 ‘Buffers []’배열은 두 캔버스 객체를 모두 보유합니다. 따라서 그리기를 시작하려면 여전히 컨텍스트를 가져와야합니다.
var context = Buffers[DrawingBuffer].getContext('2d');
답변
내가 테스트 한 브라우저는 모두 프레임을 그리는 코드가 완료 될 때까지 캔버스를 다시 그리지 않음으로써이 버퍼링을 처리합니다. WHATWG 메일 링리스트를 참조하십시오 : http://www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html
답변
당신은 항상 할 수 var canvas2 = document.createElement("canvas");
있고 DOM에 전혀 추가 하지 않을 수
있습니다.
너희들이 display:none;
그것에 집착하는 것처럼 보이기 때문에 그냥 나에게 더 깨끗해 보이고 어색하게 보이지 않는 캔버스를 갖는 것보다 더 정확하게 이중 버퍼링 방식의 아이디어를 모방합니다.
답변
2 년 이상 후 :
이중 버퍼링을 ‘수동’으로 구현할 필요가 없습니다. Geary는 그의 책 “HTML5 Canvas” 에서 이에 대해 썼습니다 .
플리커 사용을 효과적으로 줄이려면 requestAnimationFrame()
!
답변
Josh는 깜박임을 방지하기 위해 브라우저가 “그리기 프로세스가 끝날 때”를 어떻게 인식하는지 물었습니다. 나는 그의 게시물에 직접 댓글을 달았지만 내 담당자는 충분히 높지 않습니다. 또한 이것은 내 의견입니다. 나는 그것을 뒷받침 할 사실이 없지만 그것에 대해 상당히 확신을 가지고 있으며 이것은 미래에 이것을 읽는 다른 사람들에게 도움이 될 수 있습니다.
나는 당신이 그리기를 마쳤을 때 브라우저가 “알지”못하는 것 같다. 그러나 대부분의 자바 스크립트와 마찬가지로 코드가 브라우저에 대한 제어권을 포기하지 않고 실행되는 한 브라우저는 기본적으로 잠겨 있으며 UI를 업데이트하거나 응답 할 수 없습니다. 캔버스를 지우고 브라우저에 대한 제어권을 포기하지 않고 전체 프레임을 그리면 완료 될 때까지 실제로 캔버스를 그리지 않을 것이라고 생각합니다.
렌더링이 여러 setTimeout / setInterval / requestAnimationFrame 호출에 걸쳐있는 상황을 설정하는 경우, 한 번의 호출로 캔버스를 지우고 다음 여러 번의 호출에서 캔버스에 요소를 그려서 5 번 호출 할 때마다주기를 반복합니다. 캔버스가 각 호출 후에 업데이트되기 때문에 깜박임을 볼 수있을 것입니다.
그렇긴하지만 믿을 수 있을지 모르겠습니다. 우리는 이미 자바 스크립트가 실행되기 전에 네이티브 기계 코드로 컴파일되는 시점에 있습니다 (적어도 크롬의 V8 엔진이 내가 이해하는 것입니다). 브라우저가 UI와 별도의 스레드에서 자바 스크립트를 실행하고 UI에 액세스하지 않은 자바 스크립트 실행 중에 UI가 업데이트 / 응답 할 수 있도록 UI 요소에 대한 액세스를 동기화하기까지 그리 오래 걸리지 않았다면 놀라지 않을 것입니다. 그럴 때 (그리고 다른 코드를 실행하는 동안 시작되는 이벤트 핸들러와 같이 극복해야 할 많은 장애물이 있음을 이해합니다), 사용하지 않는 캔버스 애니메이션에서 깜박임이 나타날 수 있습니다. 어떤 종류의 이중 버퍼링.
개인적으로 저는 두 개의 캔버스 요소가 서로 위에 배치되고 각 프레임에 표시 / 그리는 번갈아 표시된다는 아이디어를 좋아합니다. 상당히 방해가되지 않으며 몇 줄의 코드로 기존 애플리케이션에 쉽게 추가 할 수 있습니다.
답변
믿지 않는 사람들을 위해 몇 가지 깜박 거리는 코드가 있습니다. 이전 원을 지우려면 명시 적으로 지워야합니다.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw_ball(ball) {
ctx.clearRect(0, 0, 400, 400);
ctx.fillStyle = "#FF0000";
ctx.beginPath();
ctx.arc(ball.x, ball.y, 30, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
var deltat = 1;
var ball = {};
ball.y = 0;
ball.x = 200;
ball.vy = 0;
ball.vx = 10;
ball.ay = 9.8;
ball.ax = 0.1;
function compute_position() {
if (ball.y > 370 && ball.vy > 0) {
ball.vy = -ball.vy * 84 / 86;
}
if (ball.x < 30) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
} else if (ball.x > 370) {
ball.vx = -ball.vx;
ball.ax = -ball.ax;
}
ball.ax = ball.ax / 2;
ball.vx = ball.vx * 185 / 186;
ball.y = ball.y + ball.vy * deltat + ball.ay * deltat * deltat / 2
ball.x = ball.x + ball.vx * deltat + ball.ax * deltat * deltat / 2
ball.vy = ball.vy + ball.ay * deltat
ball.vx = ball.vx + ball.ax * deltat
draw_ball(ball);
}
setInterval(compute_position, 40);
<!DOCTYPE html>
<html>
<head><title>Basketball</title></head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
</body></html>