triniwiz / nativescript-canvas-plugin

The source is now managed at https://github.com/NativeScript/canvas
Apache License 2.0
31 stars 5 forks source link

Canvas flickering on updating for real device #34

Closed dukewan closed 4 years ago

dukewan commented 4 years ago

Which platform(s) does your issue occur on?

Please, provide the following version numbers that your issue occurs with:

Please, tell us how to recreate the issue in as much detail as possible.

Describe the steps to reproduce it.

  1. Init a nativescript-vue project
  2. Install nativescript-canvas-plugin
  3. Create a new canvas
  4. Either setTimeout in ready method to update canvas, or handle @touch to update canvas
  5. Install the app in real ios device, try touch the canvas to see the flickering ezgif-3-4fc192f19269

Is there any code involved?

Template:

 <TNSCanvas id="canvas" iosOverflowSafeArea="true" col="0" row="0" @ready="canvasReady" @touch="onCanvasTouch2" width="400" height="400"
            />

Js:

canvasReady ({ object }) {
      const canvas = object
      const ctx = canvas.getContext('2d')
      ctx.beginPath()
      ctx.fillStyle = 'red'
      ctx.arc(150, 75, 50, 0, 2 * Math.PI)
      ctx.fill()
      ctx.closePath()
      this.ctx = ctx
    },
    onCanvasTouch2 () {
      this.ctx.beginPath()
      this.ctx.moveTo(100 * Math.random(), 100 * Math.random())
      this.ctx.lineTo(400 * Math.random(), 400 * Math.random())
      this.ctx.strokeStyle = 'blue'
      this.ctx.strokeWidth = 40
      this.ctx.stroke()
      this.ctx.closePath()
    },
triniwiz commented 4 years ago

I’ll look into this but you should use the requestAnimationFrame

dukewan commented 4 years ago

Thanks for looking! I just tried requestAnimationFrame with no luck:

onCanvasTouch2 (args) {
      requestAnimationFrame(() => {
        this.ctx.beginPath()
        this.ctx.moveTo(100 * Math.random(), 100 * Math.random())
        this.ctx.lineTo(400 * Math.random(), 400 * Math.random())
        this.ctx.strokeStyle = 'blue'
        this.ctx.strokeWidth = 40
        this.ctx.stroke()
        this.ctx.closePath()
      })
}

Btw, the background color of canvas differs between emulator and real device. Device reflect the transparent that I set while emulator has yellow background.

triniwiz commented 4 years ago

I noticed that will try fixing for next release also what device are you testing on (mine is usually a 11 Pro Max)

triniwiz commented 4 years ago

oh one thing you can do is

canvasReady ({ object }) {
      const canvas = object
      canvas.nativeView.handleInvalidationManually = true;
      const ctx = canvas.getContext('2d')
      ctx.beginPath()
      ctx.fillStyle = 'red'
      ctx.arc(150, 75, 50, 0, 2 * Math.PI)
      ctx.fill()
      canvas.flush();
      ctx.closePath()
      this.ctx = ctx
    },
    onCanvasTouch2 () {
      this.ctx.beginPath()
      this.ctx.moveTo(100 * Math.random(), 100 * Math.random())
      this.ctx.lineTo(400 * Math.random(), 400 * Math.random())
      this.ctx.strokeStyle = 'blue'
      this.ctx.strokeWidth = 40
      this.ctx.stroke()
      this.ctx.canvas.flush();
      this.ctx.closePath()
    },

it my little way of allowing the flush (draw to screen) manually instead of the CADisplayLink

dukewan commented 4 years ago

The new attempt improves a bit, we don't have the white background while flickering now. But the flickering still exists.

Looking at the gif that I attached, it seems there are two different canvas layers, the toggling between these two canvas make it look flickering.

I use iPhone Xs for testing.

triniwiz commented 4 years ago

Can you try this tap the screen or touch and drag LMK how it looks (dragging for long you may notice a slow down the final updates to start 1.x should improve that)

dukewan commented 4 years ago

It seems to have the same issue.

triniwiz commented 4 years ago

This should not be an issue with the latest release which has been moved to a new home feel free to open an issue if it's still not working as you like