Skip to content

Commit

Permalink
fix: simplification touch down action
Browse files Browse the repository at this point in the history
  • Loading branch information
lanfr0 committed Apr 12, 2024
1 parent 51334e7 commit 995ce6a
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 160 deletions.
2 changes: 1 addition & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function App() {
<GestureHandlerRootView style={styles.container}>
<View style={styles.canvas}>
<Rheostat
double={false}
double={true}
values={[12, 22]}
data={mockValues}
min={0}
Expand Down
44 changes: 0 additions & 44 deletions src/components/hooks/usePanGesture.ts

This file was deleted.

73 changes: 39 additions & 34 deletions src/components/rheostat/double.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React, { useMemo } from 'react';
import React, { useCallback, useMemo } from 'react';

import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import {
Gesture,
GestureDetector,
type GestureTouchEvent,
} from 'react-native-gesture-handler';
import { useDerivedValue, useSharedValue } from 'react-native-reanimated';
import { Canvas, Path, Skia } from '@shopify/react-native-skia';

Expand All @@ -10,19 +14,15 @@ import {
DOT_MAGNETIC_AREA,
} from './constant';
import type { BaseRheostatProps } from './types';
import { getPosition, getValue } from './utils';
import { getPosition, getValue, whichIsActive } from './utils';
import { SkiaDot } from '../skiaDot/skiaDot';

function DoubleRheostat({
enabled = true,
width,
height,
values: inputValues,
data,
onValuesUpdated,
horizontalPadding = DOT_DEFAULT_RADIUS,
...props
}: BaseRheostatProps) {
const { width, values: inputValues, height, data, onValuesUpdated } = props;
const startX = useMemo(() => horizontalPadding, [horizontalPadding]);
const endX = useMemo(
() => width - horizontalPadding,
Expand All @@ -35,6 +35,7 @@ function DoubleRheostat({

return p;
}, [endX, height, startX]);

/**
* DOT 1
*/
Expand Down Expand Up @@ -69,36 +70,35 @@ function DoubleRheostat({
return p;
}, [dot1ValuePosition.value, dot2ValuePosition.value, height]);

const isGestureActive = useSharedValue<number | undefined>(undefined);
const gesture = Gesture.Pan()
.runOnJS(true)
.enabled(enabled)
.onTouchesDown((event) => {
/**
* -1 = nessuna gesture riconosciuta e gestita
*/
const isGestureActive = useSharedValue<number>(-1);
const trackTouchDown = useCallback(
(event: GestureTouchEvent) => {
const touch = event.changedTouches[0]?.x;

if (touch) {
const distance1 = Math.abs(touch - dot1ValuePosition.value);
const distance2 = Math.abs(touch - dot2ValuePosition.value);

if (distance1 < DOT_MAGNETIC_AREA && distance2 < DOT_MAGNETIC_AREA) {
if (distance1 < distance2) {
isGestureActive.value = 0;
} else {
isGestureActive.value = 1;
}

return;
} else {
if (distance1 < DOT_MAGNETIC_AREA) {
isGestureActive.value = 0;
} else if (distance2 < DOT_MAGNETIC_AREA) {
isGestureActive.value = 1;
}
}
isGestureActive.value = whichIsActive(
touch,
dot1ValuePosition,
dot2ValuePosition
);
}
})
.onTouchesUp(() => (isGestureActive.value = undefined))
},
[dot1ValuePosition, dot2ValuePosition, isGestureActive]
);
const trackTouchUp = useCallback(
() => (isGestureActive.value = -1),
[isGestureActive]
);
const gesture = Gesture.Pan()
.runOnJS(true)
.enabled(enabled)
.onTouchesDown(trackTouchDown)
.onTouchesUp(trackTouchUp)
.onChange((event) => {
if (isGestureActive.value === undefined) return;
if (isGestureActive.value === -1) return;

if (onValuesUpdated) {
onValuesUpdated({
Expand All @@ -125,6 +125,11 @@ function DoubleRheostat({
dot2ValuePosition.value = event.x;
}
}
})
.onEnd(() => {
if (props.onSliderDragEnd) {
props.onSliderDragEnd();
}
});

return (
Expand Down
33 changes: 15 additions & 18 deletions src/components/rheostat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,23 @@ function RheostatImpl({
);

const checkedValues = useMemo(() => {
try {
if (double) {
if (values.length < 2) {
throw new Error('È necessario definire due valori');
} else if (values.length > 2) {
return values.slice(0, 2);
}
} else {
if (values.length === 0) {
throw new Error('È necessario definire un valore');
} else if (values.length > 1) {
return values.slice(0, 1);
}
if (double) {
if (values.length < 2) {
console.warn('È necessario definire due valori');
return [];
} else if (values.length > 2) {
return values.slice(0, 2);
}
} else {
if (values.length === 0) {
console.warn('È necessario definire un valore');
return [];
} else if (values.length > 1) {
return values.slice(0, 1);
}

return values;
} catch (error) {
console.warn(error);
return [];
}

return values;
}, [double, values]);

const snapPoints = useMemo(() => {
Expand Down
121 changes: 59 additions & 62 deletions src/components/rheostat/single.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import React, { useMemo } from 'react';
import { View } from 'react-native';
import React, { useCallback, useMemo } from 'react';

import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import {
Gesture,
GestureDetector,
type GestureTouchEvent,
} from 'react-native-gesture-handler';
import { useDerivedValue, useSharedValue } from 'react-native-reanimated';

import type { BaseRheostatProps } from './types';
import { getPosition, getValue } from './utils';
import {
DOT_DEFAULT_COLOR,
DOT_DEFAULT_RADIUS,
DOT_MAGNETIC_AREA,
} from './constant';
import { getPosition, getValue, whichIsActive } from './utils';
import { DOT_DEFAULT_COLOR, DOT_DEFAULT_RADIUS } from './constant';
import { Canvas, Group, Path, Skia } from '@shopify/react-native-skia';
import { SkiaDot } from '../skiaDot/skiaDot';

function SingleRheostat({
enabled = true,
width,
values: inputValues,
height,
data,
onValuesUpdated,
horizontalPadding = DOT_DEFAULT_RADIUS,
...props
}: BaseRheostatProps) {
const { width, values: inputValues, height, data, onValuesUpdated } = props;
const startX = useMemo(() => horizontalPadding, [horizontalPadding]);
const endX = useMemo(
() => width - horizontalPadding,
Expand Down Expand Up @@ -56,22 +51,26 @@ function SingleRheostat({
return p;
}, [startX, horizontalPadding, dotValuePosition, height]);

const isGestureActive = useSharedValue<number | undefined>(undefined);
const gesture = Gesture.Pan()
.runOnJS(true)
.enabled(enabled)
.onTouchesDown((event) => {
const isGestureActive = useSharedValue<number>(-1);
const trackTouchDown = useCallback(
(event: GestureTouchEvent) => {
const touch = event.changedTouches[0]?.x;

if (touch) {
const distance = Math.abs(touch - dotValuePosition.value);

if (distance < DOT_MAGNETIC_AREA) {
isGestureActive.value = 0;
}
isGestureActive.value = whichIsActive(touch, dotValuePosition);
}
})
.onTouchesUp(() => (isGestureActive.value = undefined))
},
[dotValuePosition, isGestureActive]
);
const trackTouchUp = useCallback(
() => (isGestureActive.value = -1),
[isGestureActive]
);
const gesture = Gesture.Pan()
.runOnJS(true)
.enabled(enabled)
.onTouchesDown(trackTouchDown)
.onTouchesUp(trackTouchUp)
.onChange((event) => {
if (isGestureActive.value === undefined) return;

Expand All @@ -91,42 +90,40 @@ function SingleRheostat({
});

return (
<View style={{ flex: 1 }}>
<GestureDetector gesture={gesture}>
<Canvas
style={{
flex: 1,
}}
>
<Group>
<Path
path={path}
strokeWidth={3}
color={props.theme?.slider?.inactive}
style="stroke"
strokeJoin="round"
strokeCap="round"
></Path>
<Path
path={activePath}
strokeWidth={3}
color={props.theme?.slider?.active}
style="stroke"
strokeJoin="round"
strokeCap="round"
></Path>
</Group>
<SkiaDot
color={props.theme?.dot ?? DOT_DEFAULT_COLOR}
size={DOT_DEFAULT_RADIUS}
circleX={dotValuePosition}
active={isGestureActive}
circleY={height / 2}
index={0}
/>
</Canvas>
</GestureDetector>
</View>
<GestureDetector gesture={gesture}>
<Canvas
style={{
flex: 1,
}}
>
<Group>
<Path
path={path}
strokeWidth={3}
color={props.theme?.slider?.inactive}
style="stroke"
strokeJoin="round"
strokeCap="round"
></Path>
<Path
path={activePath}
strokeWidth={3}
color={props.theme?.slider?.active}
style="stroke"
strokeJoin="round"
strokeCap="round"
></Path>
</Group>
<SkiaDot
color={props.theme?.dot ?? DOT_DEFAULT_COLOR}
size={DOT_DEFAULT_RADIUS}
circleX={dotValuePosition}
active={isGestureActive}
circleY={height / 2}
index={0}
/>
</Canvas>
</GestureDetector>
);
}

Expand Down
1 change: 1 addition & 0 deletions src/components/rheostat/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,5 @@ export interface RheostatProps {
*/
verticalPadding?: number;
onValuesUpdated?: (state: HandlersState) => void;
onSliderDragEnd?: () => void;
}
Loading

0 comments on commit 995ce6a

Please sign in to comment.