import React from "react";
import { Animated, Easing, StyleSheet, View } from "react-native";
import Indicator, { IndicatorProps } from "./indicator";
export type MaterialIndicatorProps = IndicatorProps & {
count?: number;
size?: number;
color?: string;
};
/** A component used to provide a visual cue that an action is either processing, awaiting a course of change or a result. */
const MaterialIndicator = React.memo(
React.forwardRef(
(
{
count = 2,
size = 30,
color = "rgb(0, 0, 0)",
animationDuration = 3600,
...rest
}: MaterialIndicatorProps,
ref: any
): JSX.Element => {
const _renderComponent = React.useCallback(
({
index,
count,
progress,
}: {
index: number;
count: number;
progress: Animated.Value;
}) => {
const trackWidth = size / 10;
let frames = (60 * animationDuration) / 1000;
let easing = Easing.bezier(0.4, 0.0, 0.7, 1.0);
let sa = 7.5;
let ea = 30;
let sequences = 3;
let rotations = 5;
let inputRange = Array.from(
new Array(frames),
(item, frameIndex) => frameIndex / (frames - 1)
);
let outputRange = Array.from(
new Array(frames),
(item, frameIndex) => {
let progress = (2 * sequences * frameIndex) / (frames - 1);
let rotation = index ? +(360 - sa) : -(180 - sa);
let sequence = Math.ceil(progress);
if (sequence % 2) {
progress = progress - sequence + 1;
} else {
progress = sequence - progress;
}
let direction = index ? -1 : +1;
return (
direction * (180 - (sa + ea)) * easing(progress) +
rotation +
"deg"
);
}
);
let layerStyle = {
width: size,
height: size,
transform: [
{
rotate: 90 - sa + "deg",
},
{
rotate: progress.interpolate({
inputRange: [0, 1],
outputRange: ["0deg", 360 * rotations + "deg"],
}),
},
],
};
let viewportStyle = {
width: size,
height: size,
transform: [
{
translateY: index ? -size / 2 : 0,
},
{
rotate: progress.interpolate({ inputRange, outputRange }),
},
],
};
let containerStyle = {
width: size,
height: size / 2,
overflow: "hidden" as "hidden",
};
let offsetStyle = index ? { top: size / 2 } : null;
let lineStyle = {
width: size,
height: size,
borderColor: color,
borderRadius: size / 2,
borderWidth: trackWidth,
};
return (
);
},
[size, color, animationDuration]
);
const { style, ...props } = rest;
return (
);
}
)
);
export default MaterialIndicator;