Energy Orb

Energy ORB made using Skia's Shader

Last updated on

Edit on GitHub

Manual

Install the following dependencies:

npm install react-native-reanimated @shopify/react-native-skia

Copy and paste the following code into your project. component/organisms/energy-orb

// @ts-checkimport React, { useMemo, memo } from "react";import { StyleSheet } from "react-native";import {  Canvas,  Fill,  Skia,  Shader,  type Uniforms,} from "@shopify/react-native-skia";import {  useSharedValue,  useFrameCallback,  useDerivedValue,} from "react-native-reanimated";import {  SHADER_SOURCE,  DEFAULT_COLORS,  DEFAULT_SPEED,  DEFAULT_INTENSITY,  DEFAULT_GLOW_RADIUS,  DEFAULT_SIZE,} from "./conf";import { parseColor } from "./helper";import type { IEnergyOrb, RGB } from "./types";const source = Skia.RuntimeEffect.Make(SHADER_SOURCE);export const EnergyOrb: React.FC<IEnergyOrb> &  React.FunctionComponent<IEnergyOrb> = memo<IEnergyOrb>(  ({    width = DEFAULT_SIZE,    height = DEFAULT_SIZE,    speed = DEFAULT_SPEED,    intensity = DEFAULT_INTENSITY,    colors = DEFAULT_COLORS,    glowRadius = DEFAULT_GLOW_RADIUS,  }: IEnergyOrb):    | (React.ReactNode & React.ReactElement & React.JSX.Element)    | null => {    const time = useSharedValue<number>(0);    useFrameCallback(() => {      time.value += 0.016 * speed;    });    const [c0r, c0g, c0b] = useMemo<RGB>(      () => parseColor(colors[0] || DEFAULT_COLORS[0]),      [colors],    );    const [c1r, c1g, c1b] = useMemo<RGB>(      () => parseColor(colors[1] || colors[0] || DEFAULT_COLORS[1]),      [colors],    );    const [c2r, c2g, c2b] = useMemo<RGB>(      () => parseColor(colors[2] || colors[0] || DEFAULT_COLORS[2]),      [colors],    );    const uniforms = useDerivedValue<Uniforms>(() => ({      iTime: time.value,      iResolution: [width, height],      uSpeed: speed,      uIntensity: intensity,      uColor0: [c0r, c0g, c0b],      uColor1: [c1r, c1g, c1b],      uColor2: [c2r, c2g, c2b],      uGlowRadius: glowRadius,    }));    if (!source) return null;    return (      <Canvas style={[styles.canvas, { width, height }]}>        <Fill>          <Shader source={source} uniforms={uniforms} />        </Fill>      </Canvas>    );  },);const styles = StyleSheet.create({  canvas: {    backgroundColor: "transparent",  },});export default memo<React.FC<IEnergyOrb> & React.FunctionComponent<IEnergyOrb>>(  EnergyOrb,);

Usage

import { View, Text, StyleSheet } from "react-native";import { GestureHandlerRootView } from "react-native-gesture-handler";import { StatusBar } from "expo-status-bar";import { Ionicons } from "@expo/vector-icons";import Dropdown from "@/components/organisms/dropdown";import { useFonts } from "expo-font";import EnergyOrb from "@/components/organisms/energy-orb";export default function App(): React.JSX.Element {  const [fontLoaded] = useFonts({    SfProRounded: require("@/assets/fonts/sf-pro-rounded.ttf"),    HelveticaNowDisplay: require("@/assets/fonts/HelveticaNowDisplayMedium.ttf"),    Coolvetica: require("@/assets/fonts/Coolvetica-Rg.otf"),  });  return (    <GestureHandlerRootView style={styles.container}>      <StatusBar style="light" />      <View        style={{          justifyContent: "center",          alignItems: "center",          marginTop: 100,        }}      >        <EnergyOrb glowRadius={0.5} width={300} height={300} />      </View>    </GestureHandlerRootView>  );}const styles = StyleSheet.create({  container: {    flex: 1,    backgroundColor: "#000",    paddingHorizontal: 24,  },  card: {    backgroundColor: "rgba(255,255,255,0.08)",    borderRadius: 20,    padding: 20,    top: 120,  },  header: {    flexDirection: "row",    justifyContent: "space-between",    alignItems: "center",  },  title: {    color: "#fff",    fontSize: 17,    fontWeight: "600",  },  subtitle: {    color: "rgba(255,255,255,0.6)",    fontSize: 13,    marginTop: 2,  },  body: {    marginTop: 12,    color: "rgba(255,255,255,0.75)",    fontSize: 14,    lineHeight: 20,  },  trigger: {    width: 36,    height: 36,    borderRadius: 10,    backgroundColor: "rgba(255,255,255,0.12)",    justifyContent: "center",    alignItems: "center",  },  menu: {    backgroundColor: "#fff",  },  itemText: {    fontSize: 15,    color: "#111",  },  destructive: {    color: "#dc2626",  },});

Props

React Native Reanimated
React Native Skia