Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flickering during animation #155

Open
andySigler opened this issue Oct 28, 2019 · 12 comments
Open

Flickering during animation #155

andySigler opened this issue Oct 28, 2019 · 12 comments
Labels

Comments

@andySigler
Copy link

andySigler commented Oct 28, 2019

I am testing out react-native-canvas to use for an animation. However, I am unable to draw a simple animation without a flickering. It looks as if the canvas is rendering to the display halfway through the drawing functions, but that's just a guess.

Here is a video showing my test. The left view is in the browser, and the right view is with react-native-canvas in a simulator (btw it behaves the same when ran on device). You will notice the animation works just fine when ran in a browser.

I have tried a few combinations of changes to see what would remove the flickering, but none have removed the flickering:

  • using requestAnimationFrame and also a slow setTimeout
  • removing any calls to fillRect that would erase the entire canvas
  • only erasing (drawing over) the spaces on the canvas that have updated
  • removing references to canvas.width and canvas.height inside draw functions
  • commenting and uncommenting different parts of the code/drawing functions

And my code is below:

import React, { Component } from 'react';
import { View, Dimensions } from 'react-native';

import Canvas from 'react-native-canvas';


function drawCircle(context, color, x, y) {
  context.strokeStyle = color;
  context.lineWidth = 5; // hard-coded width
  context.beginPath();
  context.arc(x, y, 30, 0, Math.PI * 2, false);  // hard-coded radius
  context.closePath();
  context.stroke();
}


function updateBouncingCircleCoords(canvas, pos, step) {
  pos.x += step.x;
  if (pos.x < 0 || pos.x > canvas.width) {
    step.x *= -1;
    pos.x += step.x;
  }
  pos.y += step.y;
  if (pos.y < 0 || pos.y > canvas.height) {
    step.y *= -1;
    pos.y += step.y;
  }
  return [pos, step]
}


function drawLoop(canvas, context, pos, step) {
  [pos, step] = updateBouncingCircleCoords(canvas, pos, step);
  context.save();
  context.fillStyle = 'gray';
  context.fillRect(0, 0, canvas.width, canvas.height);
  drawCircle(context, 'blue', pos.x, pos.y);
  drawCircle(context, 'red', canvas.width / 2, canvas.height / 2);
  context.restore();
  requestAnimationFrame(() => drawLoop(canvas, context, pos, step));
}


export default class HelloWorldApp extends Component {

  initCanvas(c) {
    const canvas = c
    const thisWindow = Dimensions.get('window');
    canvas.width = thisWindow.width;
    canvas.height = thisWindow.height;
    const pos = {x: 0, y: 0};
    const step = {x: 5, y: 5};
    pos.x = canvas.width / 2;
    pos.y = canvas.height / 2;
    context = canvas.getContext('2d');
    requestAnimationFrame(() => drawLoop(canvas, context, pos, step));
  }

  render() {
    return (
      <View>
        <Canvas ref={this.initCanvas}/>
      </View>
    );
  }
}
@andySigler andySigler changed the title Simple animation flickering Flickering during animation Oct 28, 2019
@iddan iddan added the bug label Oct 29, 2019
@iddan
Copy link
Owner

iddan commented Oct 29, 2019

Hey, thank you for trying React Native Canvas and reporting this issue so well. I am not quite sure what is causing the flickering but it will require some debugging effort I can not fit into my schedule at the moment. Leads for solution and PRs are welcome though!

@zhiqiangx
Copy link

Hi, @iddan ,I think the problem is caused by React Native Canvas takes too much time in WebView message, and I want to create a function which will allows any Canvas updates in an event loop to be batched together in CanvasRenderingContext2D.js .Can I submit a PR?

@iddan
Copy link
Owner

iddan commented Dec 10, 2019

Hey @zhiqiangx, sure you can! I'd be happy to review it.

@ajouve
Copy link

ajouve commented Jan 7, 2020

Same issue calling drawImage

Any news ?

@Shudog
Copy link

Shudog commented Feb 19, 2020

Came across the same flickering problem, any updates or helpful tips?

@iddan
Copy link
Owner

iddan commented Feb 19, 2020

Currently, I don't have a solution for this except not awaiting when drawing the frame. If someone figures it out let me know!

@briangmitie
Copy link

briangmitie commented May 8, 2020

I've found a dirty solution for this on Anderoid. This was an App killer until I discovered a solution.

I added a second canvas (with fixed props so it shouldn't redraw) to get 2 canvases side by side at the same height. I noticed that only the left canvas flickers!

So the fix is to add a dummy canvas with minimal width. Flicker is now completely gone, at least at the low frame rates I'm using. Code below. LtyLabel, and LtyLabelAxes contain a react-native-canvas.

          <View style={{flex: 80, flexDirection: 'row'}}>
            <View style={{flexDirection: 'row', backgroundColor: '#020202', flex: 1, margin: 0}}>
              <LtyLabelAxes style={{flex: 1}} graphSeparation = {8/(48+48)}
                minPres = {0} maxPres = {1} minFlow = {0} maxFlow = {1}
              />
            </View>
            <View style={{flexDirection: 'row', backgroundColor: '#020202', flex: 10, margin: 0}}>
              <LtyLabelAxes style={{flex: 1}} graphSeparation = {8/(48+48)}
                minPres = {this.minPres} maxPres = {this.maxPres} minFlow = {this.minFlow} maxFlow = {this.maxFlow}
              />
            </View>
            <View style={{flexDirection: 'row', backgroundColor: '#020202', flex: 390, margin: 0}}>
              <LtyLabel style={{flex: 1}} newData={this.state.newData} graphSeparation = {8/(48+48)}
                force={this.state.forceUpdate} arraySize={this.arraySize}
                minPres = {this.minPres} maxPres = {this.maxPres} minFlow = {this.minFlow} maxFlow = {this.maxFlow}
              />
            </View>
          </View>

@matthiasferch
Copy link

matthiasferch commented Feb 20, 2021

@iddan First of all, thank you very much for this library, my app wouldn't be possible without it! However, I have now run into the same problem discussed here: clearing the canvas and redrawing causes extreme flickering, at least on Android (I cannot test this on iOS, unfortunately.) Have you made any progress on this?

@zhiqiangx Did you ever get this working witht he solution you described above?

@Nesh108
Copy link

Nesh108 commented Jun 22, 2021

Same problem! It flickers quite heavily on iOS too.

@joonas-yoon
Copy link

+1 still on android 11

@hangju21a
Copy link

It's blinking a lot on Android too. T_T

@dblas-softserve
Copy link

Still flickering, but only on Android :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests