Вам не нужно preserveDrawingBuffer: true
, чтобы звонить readPixels
. Вам нужно позвонить readPixels
перед выходом из текущего события.
В спецификации сказано, что если вы вызываете какую-либо функцию, которая влияет на холст (gl.clear, gl.drawXXX), то браузер очистит холст после следующей составной операции. Когда эта сложная операция происходит, зависит от браузера. Это может произойти после того, как он обработает несколько событий мыши, клавиатуры или события щелчка. Порядок не определен. Что определено, так это то, что он не сделает этого, пока не завершится текущее событие
render
read
const gl = document.querySelector("canvas").getContext("webgl");
render();
read(); // read in same event
function render() {
gl.clearColor(.25, .5, .75, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
}
function read() {
const pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
log(pixel);
}
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
* * 1010
работает где
render
setTimeout(read, 1000); // some other event
не работает
const gl = document.querySelector("canvas").getContext("webgl");
render();
setTimeout(read, 1000); // read in other event
function render() {
gl.clearColor(.25, .5, .75, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
}
function read() {
const pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
log(pixel);
}
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
<canvas></canvas>
Обратите внимание, что поскольку это составная операция (браузер на самом деле рисует холст на странице с остальным HTML), она запускает очистку, если холст не находится на странице, он не компонуется и не будет очищен. .
Другими словами, случай, который не работал выше, работает здесь
// create an offscreen canvas. Because it's offscreen it won't be composited
// and therefore will not be cleared.
const gl = document.createElement("canvas").getContext("webgl");
render();
setTimeout(read, 1000); // read in other event
function render() {
gl.clearColor(.25, .5, .75, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
}
function read() {
const pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
log(pixel);
}
function log(...args) {
const elem = document.createElement("pre");
elem.textContent = [...args].join(' ');
document.body.appendChild(elem);
}
Теперь, если вы хотите вызвать readPixels
в каком-то другом событии, например, когда пользователь щелкает элемент, у вас есть как минимум 2 варианта
Набор preserveDrawingBuffer: true
Рендеринг снова в вашем событии
screenshotElement.addEventListener('click', event => {
render();
gl.readPixels(...);
});