Open ShaMan123 opened 5 years ago
Here is code that I use in my projects. It will draw the path by params you set.
import React from "react";
import Animated, { Easing } from "react-native-reanimated";
import { timing, parsePath, delay } from "react-native-redash";
import { Path } from "react-native-svg";
import { useMemoOne } from "use-memo-one";
const { Value, Clock, clockRunning, cond, useCode, block, not, set } = Animated;
const AnimatedPath = Animated.createAnimatedComponent(Path);
const DEFAULT_DISPLAY_DELAY = 350;
function runTiming(value, clock, from, to, duration, easing) {
return set(value, timing({ clock, duration, from, to, easing }));
}
const AnimatedSvgPath = ({
d,
fill,
stroke,
strokeWidth,
durationMs,
delayMs,
easing
}) => {
const length = useMemoOne(() => parsePath(d).totalLength, [d]);
const [strokeDashoffset, clock, active, delayed] = useMemoOne(
() => [new Value(length), new Clock(), new Value(0), new Value(0)],
[length]
);
useCode(
block([
cond(
not(delayed),
delay(
[set(active, 1), set(delayed, 1)],
delayMs + DEFAULT_DISPLAY_DELAY
)
),
cond(active, [
runTiming(strokeDashoffset, clock, length, 0, durationMs, easing),
cond(not(clockRunning(clock)), set(active, 0))
])
]),
[]
);
return (
<AnimatedPath
d={d}
strokeDasharray={[length, length]}
strokeDashoffset={strokeDashoffset}
fill={fill}
stroke={stroke}
strokeWidth={strokeWidth}
/>
);
};
Awesome.
Question: can d
be an Animated.Value
? That's what I'm looking for.
Absolutely. And starting with Reanimated 1.3.0, d as an animated values work on both ios and android.
looking into it!
The following snippet doesn't work.
It fails when it tries to parse the path using parse-svg-path
.
I'm guessing I should avoid parsePath
...?
const d1="M25 10 L98 65 L70 25 L16 77 L11 30 L0 4 L90 50 L50 10 L11 22 L77 95 L20 25";
return (
<Svg style={{ flex: 1 }}>
<AnimatedSvgPath
d={concat(d1, "")}
stroke="yellow"
strokeWidth={2}
delayMs={2000}
durationMs={500}
easing={Easing.linear}
fill="none"
/>
</Svg>
);
hello @ShaMan123
I also had some problems with redash's parsePath length getting function.
When I use package called svg-path-properties
especially:
import { svgPathProperties } from 'svg-path-properties';
...
const length = useMemoOne(() => svgPathProperties(d).getTotalLength(), [d]);
to get length, everything worked without any problem. Anyway, for my use-case I'm fine with redash length calculation.
Maybe @wcandillon have any suggestions where the problem can be?
I tried this:
const d = useValue("M0 0");
const counter = useValue(0);
const length = useValue(0);
const lastX = useValue(0);
const lastY = useValue(0);
return (
<PanGestureHandler
onGestureEvent={event<PanGestureHandlerGestureEvent>([{
nativeEvent: ({ x, y, state }) => block([
cond(eq(state, State.ACTIVE), [
set(d, concat(d, " L", x, " ", y)),
set(counter, add(counter, 1)),
set(length, add(length, hypot(sub(x, lastX), sub(y, lastY)))),
set(lastX, x),
set(lastY, y),
])
])
}])}
>
<View collapsable={false} style={{ flex: 1 }}>
<Svg style={{ flex: 1 }}>
<AnimatedSvgPath
d={d}
length={length}
stroke="yellow"
strokeWidth={2}
delayMs={2000}
durationMs={500}
easing={Easing.linear}
fill="none"
/>
</Svg>
</View>
</PanGestureHandler>
)
function hypot(...values: Animated.Adaptable<number>[]) {
return sqrt(_.reduce<Animated.Adaptable<number>, Animated.Adaptable<number>>(values, (acc, curr) => add(acc, pow(curr, 2)), 0));
}
function useValue(value) {
return useMemo(() => new Value(value), [value]);
}
Revised your code:
const AnimatedSvgPath = ({
d,
+ length,
fill,
stroke,
strokeWidth,
durationMs,
delayMs,
easing
}) => {
- const length = useMemoOne(() => parsePath(d).totalLength, [d]);
...
The problem with this solution seems to be the prop strokeDasharray={[length, length]}
, because length
is an Animated.Node
.
Revising as described below and above allows animating d
in response to PanGestureHandler
.
It has caveats related to Reanimated 1.3.0
return (
<AnimatedPath
d={d}
- strokeDasharray={[length, length]}
- strokeDashoffset={strokeDashoffset}
fill={fill}
stroke={stroke}
strokeWidth={strokeWidth}
/>
);
There's no reference of
AnimatedPath
in the docs. Is it justAnimated.createAnimatedComponent(Path)
?? I can't get it working.