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

feat: allow reanimated animation markerview #3294

Merged

Conversation

jleprinc
Copy link
Contributor

@jleprinc jleprinc commented Dec 29, 2023

Description

Change implementation MarkerView in ios and android to allow to use react native reanimated to animate a marker coordinate

Pass list of coordinates instead of a string to the marker

Discussion: #3097 (reply in thread)

Checklist

  • I've read CONTRIBUTING.md
  • I updated the doc/other generated code with running yarn generate in the root folder
  • I have tested the new feature on /example app.
    • In V11 mode/ios
    • In New Architecture mode/ios
    • In V11 mode/android
    • In New Architecture mode/android
  • I added/updated a sample - if a new feature was implemented (/example)

Video

az_recorder_20231229_193355_edited.mp4

@mfazekas
Copy link
Contributor

@jleprinc thanks much, looks nice

@trungledangAxonActive
Copy link

trungledangAxonActive commented Jan 2, 2024

Hi @jleprinc , That looks awesome! Could you please give me the example using react reanimated for the one in the attached video? I would really appreciate it. I've been following the thread and doing the same changes but no luck to make the animation work.

@jleprinc
Copy link
Contributor Author

jleprinc commented Jan 2, 2024

Hi @jleprinc , That looks awesome! Could you please give me the example using react reanimated for the one in the attached video? I would really appreciate it. I've been following the thread and doing the same changes but no luck to make the animation work.


import { useCallback } from "react";
import { Easing, useAnimatedProps, useSharedValue, withTiming } from "react-native-reanimated";

export const useAnimatedCoord = (coordinate: [number, number]) => {
  const [long, lat] = coordinate;
  const longitude = useSharedValue(long);
  const latitude = useSharedValue(lat);
  const animatedProps = useAnimatedProps(() => {
    return {
      coordinate: [longitude.value ?? 0, latitude.value ?? 0],
    };
  }, [long, lat]);

  const animate = useCallback((options: { latitude?: any; longitude?: any; duration?: any; easing?: any }) => {
    console.log("options", options);
    const { duration = 500, easing = Easing.inOut(Easing.ease) } = options;

    const animateValue = (value: { value: any }, toValue: any) => {
      if (!toValue) {
        return;
      }

      value.value = withTiming(toValue, {
        duration,
        easing,
      });
    };

    animateValue(latitude, options.latitude);
    animateValue(longitude, options.longitude);
  }, []);
  return [animatedProps, animate];
};

const AnimatedMarkerView = Animated.createAnimatedComponent(MarkerView);

const Container = styled.View`
  align-items: center;
  justify-content: center;
`;
const PhotoContainer = styled.View`
  height: 70px;
  width: 70px;
  border-radius: 70px;
  border: 4px solid ${(p) => p.theme.colors.white};
  overflow: hidden;
  background-color: ${(p) => p.theme.colors.white};
`;

const Photo = styled(FastImage)`
  width: 100%;
  height: 100%;
`;

const UserMarker: React.FC<{
  friend: FriendInfo;
  onPress: (friend: FriendInfo) => void;
  isSelected: boolean;
}> = ({ friend, onPress, index, animation, isSelected }) => {
  const user = friend.info;
  const yTranslate = useSharedValue(0);
  const [animatedProps, animate] = useAnimatedCoord([friend?.location?.lng ?? 0, friend?.location?.lat ?? 0]);

  useEffect(() => {
    yTranslate.value = withRepeat(
      withSequence(withTiming(-10, { duration: 700 }), withTiming(10, { duration: 700 })),
      -1,
      true,
    );
  }, []);

  const translateStyle = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateY: yTranslate.value,
        },
      ],
    };
  });

 

  const getUri = () => {
    ...
  };

  useEffect(() => {
    animate({
      latitude: friend.location?.lat,
      longitude: friend.location?.lng,
      duration: 1000,
      easing: Easing.linear,
    });
  }, [friend.location]);

  return (
    <AnimatedMarkerView
      anchor={{ x: 0.5, y: 0.5 }}
      id="marker"
      allowOverlap={true}
      allowOverlapWithPuck={true}
      isSelected={isSelected}
      animatedProps={animatedProps}
    >
      <TapGestureHandler onActivated={() => onPress(friend)}>
        <Container style={[translateStyle]}>
          <PhotoContainer>
            <Photo source={getUri()} resizeMode={FastImage.resizeMode.cover} />
          </PhotoContainer>
        </Container>
      </TapGestureHandler>
    </AnimatedMarkerView>
  );
};

export default UserMarker;

@jleprinc jleprinc temporarily deployed to CI with Mapbox Tokens January 2, 2024 09:27 — with GitHub Actions Inactive
@jleprinc jleprinc temporarily deployed to CI with Mapbox Tokens January 2, 2024 09:27 — with GitHub Actions Inactive
@jleprinc jleprinc temporarily deployed to CI with Mapbox Tokens January 2, 2024 09:27 — with GitHub Actions Inactive
@jleprinc jleprinc temporarily deployed to CI with Mapbox Tokens January 2, 2024 09:27 — with GitHub Actions Inactive
@jleprinc jleprinc temporarily deployed to CI with Mapbox Tokens January 2, 2024 09:27 — with GitHub Actions Inactive
@jleprinc jleprinc temporarily deployed to CI with Mapbox Tokens January 2, 2024 09:27 — with GitHub Actions Inactive
@trungledangAxonActive
Copy link

Thanks @jleprinc! You saved my day.

@mfazekas mfazekas merged commit a280a6c into rnmapbox:main Jan 3, 2024
10 checks passed
@mfazekas mfazekas changed the title Feat/allow reanimated animation markerview feat: allow reanimated animation markerview Jan 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants