HTML-холст на мобильном устройстве (react-native-canvas) мерцает
Я пытаюсь сделать несколько простую анимацию на react-native. я использую
react-native-canvas
и, кажется, он достаточно хорошо реализует нормальный холст html, но на реальном устройстве у меня ужасно мерцает. У меня почти не мерцает эмулятор iOS, а вот Android плохой.
В моем текущем коде уже реализованы следующие предложения, которые я нашел:
- Использовать
requestAnimationFrame
- Двойная буферизация
- Обработка частоты кадров
- Избегайте использования состояний для переменных (поскольку они повторно запускают рендеринг)
Моя цель - получить анимацию, которая не мерцает. Я не возражаю, если на более медленном устройстве он будет играть немного медленнее, но мерцание не вызывает у пользователя приятных ощущений.
Что я делаю не так?
Вот код:
initTempCanvas = (canvas) => {
if (canvas !== null) {
canvas.width = this.window_size.height;
canvas.height = this.window_size.width + 50;
this.tempCanvas = canvas;
this.tempCtx = canvas.getContext('2d');
canvas.hidden = true;
}
}
initCanvas = (canvas) => {
if (canvas !== null) {
var fps = 25;
this.interval = 1000 / fps;
this.speed = 30;
// These are switched because of landscape mode
canvas.width = this.window_size.height;
canvas.height = this.window_size.width + 50;
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
requestAnimationFrame(this.drawLoop);
}
}
drawLoop = (now) => {
if (this.tempCtx !== undefined) {
if (!this.then) {
this.then = now;
}
this.delta = now - this.then;
if (this.delta > this.interval) {
this.ctx.save();
this.tempCtx.clearRect(0, 0, this.tempCanvas.width, this.tempCanvas.height)
this.drawCircle(this.tempCtx, (this.canvasTimer * 100), this.tempCanvas.height / 2 + (-125 * Math.sin(this.canvasTimer * (Math.PI / 2) - Math.PI * 0.5)), 30, 'purple', 'purple', 2);
this.ctx.drawImage(this.tempCanvas, 0, 0);
this.ctx.restore();
this.deltaTime = this.delta / 100000 * this.speed;
this.canvasTimer += this.deltaTime;
}
this.then = now - (this.delta % this.interval);
}
requestAnimationFrame(this.drawLoop);
}
drawCircle = (ctx, x, y, radius, fill, stroke, strokeWidth) => {
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
if (fill) {
ctx.fillStyle = fill;
ctx.fill();
}
if (stroke) {
ctx.lineWidth = strokeWidth;
ctx.strokeStyle = stroke;
ctx.stroke();
}
}
render() {
return (
<View>
{this.tempCanvas == undefined && <Canvas ref={this.initCanvas} />}
<Canvas style={"display: none"} ref={this.initTempCanvas} />
</View>
)
}