Skip to content

Instantly share code, notes, and snippets.

@wcandillon
Created November 4, 2023 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wcandillon/da5715b7b107bee808193cb637f8539f to your computer and use it in GitHub Desktop.
Save wcandillon/da5715b7b107bee808193cb637f8539f to your computer and use it in GitHub Desktop.
import {
Canvas,
Group,
Rect,
Skia,
useClock,
} from "@shopify/react-native-skia";
import React from "react";
import { StyleSheet, View } from "react-native";
import Animated, {
useAnimatedStyle,
useDerivedValue,
} from "react-native-reanimated";
const array = new Array(1).fill(0).map((_, index) => index);
const paint = Skia.Paint();
paint.setColor(Skia.Color("pink"));
export default function App() {
const clock = useClock();
const offsetTx = useDerivedValue(() => [
{ translateY: 300 + Math.sin(clock.value / 300) * 300 - 300 },
]);
const style = useAnimatedStyle(() => ({
...StyleSheet.absoluteFillObject,
transform: [{ translateY: 300 + Math.sin(clock.value / 300) * 300 - 300 }],
}));
return (
<View
style={{
flex: 1,
flexDirection: "row",
}}
>
<View style={{ flex: 1 }}>
<Animated.View style={style}>
{array.map((index) => (
<View
key={index}
style={{
position: "absolute",
top: 150 * index + 50,
left: 15,
width: 100,
height: 100,
backgroundColor: "blue",
}}
/>
))}
</Animated.View>
</View>
<Canvas
mode="continuous"
style={StyleSheet.absoluteFill}
pointerEvents="none"
>
<Group transform={offsetTx}>
{array.map((index) => (
<Rect
key={index}
x={15}
y={150 * index + 50}
width={100}
height={100}
color="green"
/>
))}
</Group>
</Canvas>
</View>
);
}
@wcandillon
Copy link
Author

import React, { useEffect } from "react";
import { StyleSheet, View } from "react-native";
import Animated, {
  useAnimatedStyle,
  useAnimatedProps,
  withRepeat,
  withTiming,
  Easing,
  cancelAnimation,
  useSharedValue,
} from "react-native-reanimated";
import { Svg, G, Rect as SvgRect } from "react-native-svg";

const AnimatedG = Animated.createAnimatedComponent(G);

const array = new Array(1).fill(0).map((_, index) => index);

export const useLoop = ({ duration }: { duration: number }) => {
  const progress = useSharedValue(0);
  useEffect(() => {
    progress.value = withRepeat(
      withTiming(1, { duration, easing: Easing.linear }),
      -1,
      true
    );
    return () => {
      cancelAnimation(progress);
    };
  }, [duration, progress]);
  return progress;
};

export default function App() {
  const clock = useLoop({ duration: 3000 });
  const animatedProps = useAnimatedProps(() => ({
    translate: `0, ${300 + clock.value * 300 - 300}`,
  }));
  const style = useAnimatedStyle(() => ({
    ...StyleSheet.absoluteFillObject,
    transform: [{ translateY: 300 + clock.value * 300 - 300 }],
  }));
  return (
    <View
      style={{
        flex: 1,
        flexDirection: "row",
      }}
    >
      <View style={{ flex: 1 }}>
        <Animated.View style={style}>
          {array.map((index) => (
            <View
              key={index}
              style={{
                position: "absolute",
                top: 150 * index + 50,
                left: 15,
                width: 100,
                height: 100,
                backgroundColor: "blue",
              }}
            />
          ))}
        </Animated.View>
      </View>
      <Svg style={StyleSheet.absoluteFill}>
        <AnimatedG animatedProps={animatedProps}>
          {array.map((index) => (
            <SvgRect
              key={index}
              x={15}
              y={150 * index + 50}
              width={100}
              height={100}
              fill="red"
            />
          ))}
        </AnimatedG>
      </Svg>
    </View>
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment