Вопрос

То, что я хотел бы сделать, это нарисовать свою графику на буфере, а затем иметь возможность скопировать его как в холсте, чтобы я мог сделать анимацию и избежать мерцаний. Но я не мог найти этот вариант. Кто-нибудь знает, как я могу пойти об этом?

Это было полезно?

Решение

Следующая полезная связь, в дополнение к отображению примеров и преимуществ использования двойной буферизации, показывает несколько других советов по производительности для использования элемента HTML5 Canvas. Он включает в себя ссылки на тесты 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;

В этом коде «буферы массива» включают в себя оба холста-объекты. Поэтому, когда вы хотите начать рисовать, вам все еще нужно получить контекст:

var context = Buffers[DrawingBuffer].getContext('2d');

Браузеры, которые я проверил, все обрабатывает эту буферизацию для вас, не перекрасив холст до тех пор, пока код не вытягивает ваш кадр. Смотрите также список рассылки Whatwg: http://www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html.

Вы всегда могли бы сделатьvar canvas2 = document.createElement("canvas");И не добавлять его в домос вообще.

Просто говорят, как вы, ребята, кажутся так одержимы display:none;Мне кажется чистым для меня и имитирует идею двойного буферизации более точно, чем просто неловко невидимый холст.

Более двух лет спустя:

Нет необходимости в «вручную» внедрять двойную буферизу. Мистер Geary писал об этом в его книге "HTML5 Canvas".

Чтобы эффективно уменьшить использование мерцания requestAnimationFrame()!

Джош спросил (некоторое время назад) о том, как браузер знает «Когда процесс рисования заканчивается», чтобы избежать мерцания. Я бы прокомментировал прямо на свой пост, но мой реп не достаточно высок. Также это только мое мнение. У меня нет фактов, чтобы поддержать его, но я чувствую себя довольно уверенно, и это может быть полезно другим, читающим это в будущем.

Я предполагаю, что браузер не «знает», когда вы закончите рисунок. Но так же, как и большинство JavaScript, если ваш код работает без отказа от контроля в браузере, браузер по существу заблокирован и не будет / не может обновлять / отвечать на его интерфейс. Я предполагаю, что если вы очистите холст и нарисуйте весь кадр без отказа от контроля в браузере, он на самом деле не нарисует ваш холст, пока вы не закончите.

Если вы настроили ситуацию, когда ваш рендеринг охватывает несколько вызовов SettimeOut / Setinterval / RequestanimationFrame, где вы очищаете холст в одном вызове и рисуете элементы на холсте в следующих нескольких вызовах, повторяя цикл (например) каждые 5 звонков, я «Будут готовы поспорить, что вы увидите мерцание, так как холст будет обновлен после каждого вызова.

Тем не менее, я не уверен, что я это доверю. Мы уже в точке, что JavaScript скомпилирован вниз на собственный код машины перед выполнением (по крайней мере, это то, что делает двигатель V8 Chrome V8 из того, что я понимаю). Я бы не был удивлен, если бы не слишком долго, прежде чем браузеры запустили свой JavaScript в отдельной резьбе из пользовательского интерфейса и синхронизируя любой доступ к элементам пользовательских интерфейсов, позволяя пользовательским интерфейсам обновлять / отвечать во время выполнения JavaScript, который не доступа к пользователю 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 Engine сделает все ваши рендеринга перед показывать его. Кроме того, контекст сохранения и восстановления только стека трансформационных матричных данных и такие, а не сам содержание холста. Итак, вам не нужно или хочу буферизацию DBL!

Вместо того, чтобы катиться своим собственным, вы, вероятно, собираетесь получить лучший пробег, используя существующую библиотеку для создания чистой и Flicker-Freick JavaScript Animation:

Вот популярный: http://processingjs.org.

Вам нужно 2 холста: (обратите внимание на CSS Z-индекс и положение: абсолютно)

<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, даже когда рисунок медленно, поэтому кажется, что это то, что они делают, но как это достигается, это загадка для меня. Как знал браузер, что он обновляет дисплей незадолго до того, как будет выполняться дополнительные инструкции по рисованию? Как вы думаете, они просто когда это так, если промежуток в течение более 5 мс или около того, не выполняя инструкцию чертежа холста, она предполагает, что он может безопасно поменять буферы?

В большинстве ситуаций вам не нужно делать это, браузер реализует это для вас. Но не всегда полезно!

Вы все еще должны реализовать это, когда ваш рисунок очень сложен. Большая часть скорости обновления экрана составляет около 60 Гц, это означает обновления экрана на 16 мс. Скорость обновления браузера может возле этого номера. Если ваша форма нуждается в завершении 100 мс, вы увидите незавершенную форму. Таким образом, вы можете реализовать двойную буферизацию в этой ситуации.

Я сделал тест: Clear a rect, wait for some time, then fill with some color. Если я установлю время до 10 мс, я не увижу мерцание. Но если я установлю его до 20 мс, случается мерцание.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top