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

Canvas onTouch Android #2250

Open
chiefchief opened this issue Feb 23, 2024 · 3 comments
Open

Canvas onTouch Android #2250

chiefchief opened this issue Feb 23, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@chiefchief
Copy link

Description

When user tap and hold, triggers - "onStart" but no "onActive" on move, immediately after start moving triggers "onEnd"

Version

0.1.240

Steps to reproduce

Code provided below

Snack, code example, screenshot, or link to a repository

import { Canvas, Path, Skia, useCanvasRef, useTouchHandler } from '@shopify/react-native-skia';
import React, { forwardRef, useEffect, useImperativeHandle } from 'react';

const activePath = Skia.Path.Make();

export const SignaturePad = forwardRef<SignaturePad, SignaturePadProps>(({ height, width, onUpdate }, ref) => {
  const canvasRef = useCanvasRef();

  useEffect(() => {
    return () => {
      activePath.reset();
    };
  }, []);

  useImperativeHandle(ref, () => ({
    clear: () => {
      activePath.reset();
      onUpdate?.('');
    },
  }));

  const onTouch = useTouchHandler({
    onStart: ({ x, y }) => {
      activePath.moveTo(x, y);
    },
    onActive: ({ x, y }) => {
      activePath.lineTo(x, y);
    },
    onEnd: () => {
      console.log('END', Date.now());
    },
  });

  return (
    <Canvas ref={canvasRef} style={{ height, width, backgroundColor: 'white' }} onTouch={onTouch}>
      <Path path={activePath} />
    </Canvas>
  );
});

type SignaturePadProps = {
  width: number;
  height: number;
  onUpdate?: (img: string) => void;
};

export type SignaturePad = {
  clear: () => void;
};
@chiefchief chiefchief added the bug Something isn't working label Feb 23, 2024
@wcandillon
Copy link
Collaborator

wcandillon commented Feb 23, 2024 via email

@chiefchief
Copy link
Author

chiefchief commented Feb 23, 2024

I strongly recommend to use gesture-handler for such scenario. We are not really supporting this API anymore: https://shopify.github.io/react-native-skia/docs/animations/gestures Based on the code you provided you will reanimated if want to update the path on the UI thread and have it shown directly onto the canvas. I hope this helps. William

On Fri, Feb 23, 2024 at 3:12 PM Silver O @.> wrote: Description When user tap and hold, triggers - "onStart" but no "onActive" on move, immediately after start moving triggers "onEnd" Version 0.1.240 Steps to reproduce Code provided below Snack, code example, screenshot, or link to a repository import { Canvas, Path, Skia, useCanvasRef, useTouchHandler } from @./react-native-skia'; import React, { forwardRef, useEffect, useImperativeHandle } from 'react'; const activePath = Skia.Path.Make(); export const SignaturePad = forwardRef<SignaturePad, SignaturePadProps>(({ height, width, onUpdate }, ref) => { const canvasRef = useCanvasRef(); useEffect(() => { return () => { activePath.reset(); }; }, []); useImperativeHandle(ref, () => ({ clear: () => { activePath.reset(); onUpdate?.(''); }, })); const onTouch = useTouchHandler({ onStart: ({ x, y }) => { activePath.moveTo(x, y); }, onActive: ({ x, y }) => { activePath.lineTo(x, y); }, onEnd: () => { console.log('END', Date.now()); }, }); return ( <Canvas ref={canvasRef} style={{ height, width, backgroundColor: 'white' }} onTouch={onTouch}> ); }); type SignaturePadProps = { width: number; height: number; onUpdate?: (img: string) => void; }; export type SignaturePad = { clear: () => void; }; — Reply to this email directly, view it on GitHub or unsubscribe. You are receiving this email because you are subscribed to this thread. Triage notifications on the go with GitHub Mobile for iOS or Android.

  1. on ios throw error
import { Canvas, Path, Skia, useCanvasRef } from '@shopify/react-native-skia';
import React, { forwardRef, useEffect, useImperativeHandle } from 'react';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';

const activePath = Skia.Path.Make();

const onBeginWorklet = (e) => {
  'worklet';
  activePath.moveTo(e.x, e.y);
};
const onChangeWorklet = (e) => {
  'worklet';
  activePath.lineTo(e.x, e.y);
};

export const SignaturePad = forwardRef<SignaturePad, SignaturePadProps>(({ height, width, onUpdate }, ref) => {
  const canvasRef = useCanvasRef();

  useEffect(() => {
    return () => {
      activePath.reset();
    };
  }, []);

  useImperativeHandle(ref, () => ({
    clear: () => {
      activePath.reset();
      onUpdate?.('');
    },
  }));

  const gesture = Gesture.Pan().onBegin(onBeginWorklet).onChange(onChangeWorklet);

  return (
    <GestureDetector gesture={gesture}>
      <Canvas ref={canvasRef} style={{ height, width, backgroundColor: 'white' }}>
        <Path path={activePath} style={'stroke'} strokeWidth={2} />
      </Canvas>
    </GestureDetector>
  );
});

type SignaturePadProps = {
  width: number;
  height: number;
  onUpdate?: (img: string) => void;
};

export type SignaturePad = {
  clear: () => void;
};
Screenshot 2024-02-23 at 18 30 33
  1. if run on JS the app just crash and no error
const onBeginWorklet = (e) => {
  runOnJS(activePath.moveTo)(e.x, e.y);
};
const onChangeWorklet = (e) => {
  runOnJS(activePath.lineTo)(e.x, e.y);
};
  1. on Android these actions don't trigger at all

The only way on Android that works almost correctly is this one.

import { Canvas, Path, Skia, useCanvasRef } from '@shopify/react-native-skia';
import React, { forwardRef, useEffect, useImperativeHandle } from 'react';

const activePath = Skia.Path.Make();

export const SignaturePad = forwardRef<SignaturePad, SignaturePadProps>(({ height, width, onUpdate }, ref) => {
  const canvasRef = useCanvasRef();

  useEffect(() => {
    return () => {
      activePath.reset();
    };
  }, []);

  useImperativeHandle(ref, () => ({
    clear: () => {
      activePath.reset();
      onUpdate?.('');
    },
  }));

  return (
    <Canvas
      ref={canvasRef}
      style={{ height, width, backgroundColor: 'white' }}
      onTouchStart={(e) => {
        activePath.moveTo(e.nativeEvent.locationX, e.nativeEvent.locationY);
      }}
      onTouchMove={(e) => {
        activePath.lineTo(e.nativeEvent.locationX, e.nativeEvent.locationY);
      }}
    >
      <Path path={activePath} style={'stroke'} strokeWidth={2} />
    </Canvas>
  );
});

type SignaturePadProps = {
  width: number;
  height: number;
  onUpdate?: (img: string) => void;
};

export type SignaturePad = {
  clear: () => void;
};

However, the line appears on the next tap (for example, when the user taps and moves, nothing appears, but on the next tap, the previous line will appear).

@chiefchief
Copy link
Author

useTouchHandler works properly without modal on android

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants