내가하고 싶은 것은 버퍼에 그래픽을 그린 다음 캔버스에 그대로 복사하여 애니메이션을 수행하고 깜박임을 피할 수 있도록하는 것입니다. 하지만이 옵션을 찾을 수 없습니다. 내가 어떻게 할 수 있는지 아는 사람 있나요?
explorercanvas
있지만 물론 HTML5가 canvas
아니며 단순히 VML에 의해 에뮬레이트 된 요소입니다. 그래도 다른 브라우저에서는 본 적이 없습니다.
내가하고 싶은 것은 버퍼에 그래픽을 그린 다음 캔버스에 그대로 복사하여 애니메이션을 수행하고 깜박임을 피할 수 있도록하는 것입니다. 하지만이 옵션을 찾을 수 없습니다. 내가 어떻게 할 수 있는지 아는 사람 있나요?
explorercanvas
있지만 물론 HTML5가 canvas
아니며 단순히 VML에 의해 에뮬레이트 된 요소입니다. 그래도 다른 브라우저에서는 본 적이 없습니다.
답변:
다음의 유용한 링크는 이중 버퍼링 사용의 예와 장점을 보여주는 것 외에도 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');
<noscript>
하고 Javascript로 캔버스 요소를 만들고 싶습니다. 일반적으로 Javascript에서 캔버스 지원을 확인하고 싶은데 HTML에 캔버스 폴백 메시지를 넣는 이유는 무엇입니까?
내가 테스트 한 브라우저는 모두 프레임을 그리는 코드가 완료 될 때까지 캔버스를 다시 그리지 않음으로써이 버퍼링을 처리합니다. 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>
웹 브라우저에서 깜박임이 없습니다! 그들은 이미 렌더링을 위해 dbl 버퍼링을 사용합니다. Js 엔진은 그것을 보여주기 전에 모든 렌더링을 만듭니다. 또한 컨텍스트는 캔버스 콘텐츠 자체가 아닌 스택 변환 매트릭스 데이터 만 저장하고 복원합니다. 따라서 dbl 버퍼링이 필요하거나 필요하지 않습니다!
직접 롤링하는 대신 깨끗하고 깜박임없는 JavaScript 애니메이션을 만들기 위해 기존 라이브러리를 사용하여 최고의 마일리지를 얻을 수 있습니다.
다음은 인기있는 것입니다 : http://processingjs.org
캔버스 2 개가 필요합니다 : (css z-index 및 position : absolute에 유의하세요)
<canvas id="layer1" width="760" height="600" style=" position:absolute; top:0;left:0;
visibility: visible; z-index: 0; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="layer2" width="760" height="600" style="position:absolute; top:0;left:0;
visibility: visible; z-index: 1; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
첫 번째 캔버스가 표시되고 두 번째는 숨겨진 캔버스에 그릴 아이디어가 숨겨져 있다는 것을 알 수 있습니다. 그 후 보이는 것을 숨기고 숨겨진 캔버스를 표시합니다. 숨길 때 '숨겨진 캔버스 지우기
<script type="text/javascript">
var buff=new Array(2);
buff[0]=document.getElementById("layer1");
buff[1]=document.getElementById("layer2");
ctx[0]=buff[0].getContext("2d");
ctx[1]=buff[1].getContext("2d");
var current=0;
// draw the canvas (ctx[ current ]);
buff[1- current ].style.visibility='hidden';
buff[ current ].style.visibility='visible';
ctx[1-current].clearRect(0,0,760,600);
current =1-current;
Opera 9.10은 매우 느리고 그리기 과정을 보여줍니다. 이중 버퍼링을 사용하지 않는 브라우저를 보려면 Opera 9.10을 사용해보십시오.
어떤 사람들은 브라우저가 그리기 프로세스가 끝나는시기를 결정한다고 제안했지만 어떻게 작동하는지 설명해 주시겠습니까? 그림이 느려도 Firefox, Chrome 또는 IE9에서 뚜렷한 깜박임이 눈에 띄지 않아서 그들이하는 일인 것처럼 보이지만 어떻게 수행되는지는 나에게 미스터리입니다. 더 많은 그리기 명령이 실행되기 직전에 브라우저가 디스플레이를 새로 고치고 있다는 것을 어떻게 알 수 있습니까? 캔버스 그리기 명령을 실행하지 않고 5ms 이상의 간격이 지나면 버퍼를 안전하게 스왑 할 수 있다고 가정합니다.
대부분의 경우이 작업을 수행 할 필요가 없으며 브라우저가이를 구현합니다. 그러나 항상 유용하지는 않습니다!
드로잉이 매우 복잡한 경우에도이를 구현해야합니다. 대부분의 화면 업데이트 속도는 약 60Hz로 16ms마다 화면이 업데이트됩니다. 브라우저의 업데이트 속도는이 수치에 가까울 수 있습니다. 모양을 완성하는 데 100ms가 필요한 경우 완성되지 않은 모양이 표시됩니다. 따라서이 상황에서 이중 버퍼링을 구현할 수 있습니다.
테스트를했습니다. Clear a rect, wait for some time, then fill with some color.
시간을 10ms로 설정하면 깜박임이 표시되지 않습니다. 하지만 20ms로 설정하면 깜박임이 발생합니다.