Компоненты/Гамбургер

Гамбургер

1 февраля 2025

Иконка меню плавно превращается в крестик

Установка

npx astra-rn add hamburger
pnpm dlx astra-rn add hamburger
yarn dlx astra-rn add hamburger
bunx --bun astra-rn add hamburger

Файлы

index.tsx
НазадКарточки с градиентомДалееШлейф картинок

Вручную

Поставьте зависимости:

npm install expo-blur react-native-reanimated
pnpm add expo-blur react-native-reanimated
yarn add expo-blur react-native-reanimated
bun add expo-blur react-native-reanimated

Скопируйте эти файлы в src/shared/components/micro-interactions/hamburger/:

Проверьте алиас путей. Импорты в коде выше записаны так, как их пишет astra-rn add: @/shared/components, @/shared/utils и @/shared/hooks. Нужен алиас "@/*": ["./src/*"] в tsconfig.json — или поправьте импорты под свои пути.

Использование

import { HamburgerIcon } from "@/shared/components/micro-interactions/hamburger";
import React, { useCallback, useRef } from "react";
import { StyleSheet, View } from "react-native";
import { useSharedValue, withTiming } from "react-native-reanimated";
import { Showcase, useAutoplay, useCustomize } from "~/showcase";

const CUSTOMIZE = [
  { key: "color", label: "Цвет", type: "color", default: "#ffffff" },
  { key: "size", label: "Размер", type: "slider", min: 40, max: 260, step: 2, unit: "px", default: 150 },
  { key: "stroke", label: "Толщина линий", type: "slider", min: 0.01, max: 0.12, step: 0.005, default: 0.04 },
  { key: "lineWidth", label: "Длина линий", type: "slider", min: 0.3, max: 1, step: 0.05, default: 0.75 },
  { key: "lineGap", label: "Интервал", type: "slider", min: 0.1, max: 0.45, step: 0.01, default: 0.25 },
  { key: "duration", label: "Длительность", type: "slider", min: 100, max: 1500, step: 50, unit: "ms", default: 300 },
] as const;

export default function HamburgerScreen() {
  const custom = useCustomize(CUSTOMIZE);
  const progress = useSharedValue<number>(0);
  const target = useRef<number>(0);
  const duration = useRef<number>(custom.duration);
  duration.current = custom.duration;
  const animateTo = useCallback((value: number) => {
    target.current = value;
    progress.value = withTiming(value, { duration: duration.current });
  }, []);
  const onPress = useCallback(() => {
    animateTo(target.current === 1 ? 0 : 1);
  }, [animateTo]);

  useAutoplay(async ({ wait }) => {
    await wait(250);
    animateTo(1);
    await wait(600 + duration.current);
    animateTo(0);
    await wait(100 + duration.current);
  });

  return (
    <Showcase>
      <View style={styles.container}>
        <HamburgerIcon
          progress={progress}
          color={custom.color}
          onPress={onPress}
          size={custom.size}
          strokeWidth={custom.size * custom.stroke}
          lineWidth={custom.size * custom.lineWidth}
          lineGap={custom.size * custom.lineGap}
        />
      </View>
    </Showcase>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#0a0a0a",
    justifyContent: "center",
    alignItems: "center",
  },
});

Пропсы

Пропс
Описание
progress

Тип SharedValue<number>

size?

Тип number

color?

Тип string

strokeWidth?

Тип number

onPress?

Тип () => void

lineGap?

Тип number

lineWidth?

Тип number

style?

Тип StyleProp<ViewStyle>