React Native가 있는 진행률 표시줄 애니메이션에 대한 이야기
37043 단어 reactreactnativetutorialjavascript
본 강좌에서 저는 웹/모바일 애니메이션의 차이점과react원생 부활, 크로스플랫폼react 구성 요소의 장점을 설명하고 싶습니다.
브라우저에서 애니메이션 진도표를 만드는 방법을 보여 줍니다.
먼저 React 구성 요소를 만듭니다.
const ProgressBar = ({ total, current, fill }) => {
const percent = current / total;
return (
<div class="container">
<div class="progress"></div>
</div>
)
}
CSS 스타일:.container {
background-color: #eee;
height: 4px;
border-radius: 2px;
margin: 20px;
position: relative;
overflow: hidden;
}
.progress {
position: absolute;
left: -100%;
width: 100%;
top: 0;
bottom: 0;
border-radius: 2px;
}
다음 단계는 도구의 스타일을 우리의 레이아웃에 적용하는 것이다....
<div class="progress" style={{ transform: `translateX(${percent * 100}%)`, backgroundColor: fill }}></div>
...
결과를 살펴보겠습니다.애니메이션은요?
웹 응용 프로그램에서 변환이나 배경색 등 속성을 위한 애니메이션을 설정하기 쉬우며 브라우저는 우리가 없는 상황에서 모든 애니메이션 작업을 완성할 것입니다.
우리의 스타일에 전환 속성을 추가하기만 하면 됩니다.
.progress {
...
transition: all 0.2s;
}
이것은 결과입니다.보기에 구성 요소는 매우 간단한데, 왜 내가 너희들에게 이 예를 보여 줄까?
React Native를 사용하여 이 구성 요소를 구현해 보겠습니다.
const AnimatedProgress = ({ fill, current, total }) => {
const percent = current / total;
return (
<View style={styles.container}>
<View style={[styles.progress, { backgroundColor: fill, transform: [{ translateX: `${percent * 100}%` }] }]} />
</View>
);
};
읊다, 읊조리다그렇다면 우리는 어떻게 원소의 폭을 얻을 수 있습니까?
useOnLayout 갈고리를 추가합니다.
export default function useOnLayout() {
const [layout, setLayout] = useState({ x: 0, y: 0, width: 0, height: 0 });
const onLayout = useCallback((event) => setLayout(event.nativeEvent.layout), []);
return [layout, onLayout];
}
onLayout 프로세서를 패키지 뷰로 전송하려면 다음과 같이 하십시오.const AnimatedProgress = ({ fill, current, total }) => {
const percent = current / total;
// we need only width property
const [{ width }, onLayout] = useOnLayout();
return (
<View style={styles.container} onLayout={onLayout}>
<View style={[styles.progress, { backgroundColor: fill, transform: [{ translateX: width * percent }] }]} />
</View>
);
};
다음 단계는 translateX 속성을 설정하는 애니메이션입니다.import { Animated } from "react-native";
// wrap our Animated.Value to useState for memoize it, alternatively you can use useRef
const [translateX] = useState(new Animated.Value(0));
useEffect(() => {
Animated.timing(translateX, {
toValue: width * percent,
duration: 200,
easing: Easing.inOut(Easing.ease),
// using native driver for animation in UI thread
useNativeDriver: true
}).start();
// call our animation when width or percent change
}, [width, percent]);
....
// Change View => Animated.View and translateX to our Animated.Value
<Animated.View style={[styles.progress, { backgroundColor: fill, transform: [{ translateX }] }]} />
오늘의 마지막 애니메이션 - 배경색 애니메이션.
그것은 웹 응용 프로그램처럼 간단합니까?
컬러 애니메이션을 작성하기 전에, 우리는reactnativereanimated library로 전환합니다. 이것은 더욱 유연하고 더 많은 정의 기능을 가지고 있습니다.
reactnativereanimated는 뒤로 기능하는 API를 가지고 있기 때문에 코드 라이브러리를 다시 쓸 필요가 없습니다.
import Animated, { Easing } from "react-native-reanimated";
useEffect(() => {
Animated.timing(translateX, {
toValue: width * percent,
duration: 200,
easing: Easing.inOut(Easing.ease)
}).start();
}, [width, percent]);
reactnative에서 색 애니메이션을 설정하는 주요 문제는 브라우저와 같은 전환이 부족하다는 것입니다.솔직히 브라우저는 백그라운드에서 CSS, 삽입 색상 등이 있는 모든 애니메이션을 많이 했습니다.그래서 우리는 스스로 색을 위해 과도를 만들어야 한다.이전에reactnativereanimated 라이브러리로 전환했습니다. 유용한 기능이 많습니다. 이 기능을 사용할 것입니다.
색상 보간 프로세스를 상상해 보십시오.
1) Convert color: Firstly let's convert color to one format - for example, RGBA(you can choose a different one - HSV, HSL)
2) we need steam of animation which we can iterate - it can be usual for us *Animated.Value*, which we can animate from 0 to some value.
3) In this time we will make interpolation of animation this value each of color part (r, g, b, a);
4) combine all these values into one color.
중요한 요구 사항은 애니메이션이 네이티브 UI 스레드에서 작동해야 한다는 것입니다.이것이 바로 우리가 react native에서string 색깔까지의 간단한 삽입값을 사용할 수 없는 이유입니다. 예를 들어 다음과 같습니다. const interpolateColor = animatedValue.interpolate({
inputRange: [0, 150],
outputRange: ['rgb(0,0,0)', 'rgb(51, 250, 170)']
})
원본 UI 스레드 애니메이션은 매우 큰 한계가 있습니다. 비레이아웃 속성에 대해서만 애니메이션을 설정할 수 있습니다. 예를 들어 변환과 불투명도는 작동할 수 있지만 Flexbox와 위치 속성은 할 수 없습니다.이것은 우리가 시작하기 전에 애니메이션을 정의해야 하기 때문이다.
애니메이션에 대한 자세한 내용은 다음을 참조하십시오. https://reactnative.dev/blog/2017/02/14/using-native-driver-for-animated
우리는 도구 충전이 변할 때 애니메이션을 실행하기를 원하기 때문에, 플러그인을 실행하기 위해 이전의 충전 값을 저장해야 한다.
색상 보간 값에 대한 사용자 정의 연결을 만들고 이전 값을 저장합니다.
export default function useAnimatedColor(color) {
// store our previous color in ref
const prevColor = useRef(color);
// TODO write color interpolation
// updating previous value after creating interpolation
prevColor.current = color;
// TODO return color interpolation
return color;
}
다음 단계는 색 값을 추가하는 것입니다. 색을 삽입하고 색이 변할 때 애니메이션을 실행합니다.물론, 우리는reactnative의useEffect를 사용할 수 있지만,reactnativereanimated는 자체의useCode 연결이 있습니다.// define input range for interpolation
const inputRange = [0, 50];
export default function useAnimatedColor(color) {
// store our value to ref for memoization
const colorValue = useRef(new Animated.Value(0));
...
useCode(() => {
const [from, to] = inputRange;
// TODO iterate colorValue in range
}, [color]);
}
reactnativereanimated는 모든 프레임의 시계를 제어하는 메커니즘을 가지고 있습니다.그리고 유니버설 함수 runTiming-는 시간 애니메이션에 사용됩니다. 이 강좌의 문서나 전체 코드에서 원본 코드를 찾을 수 있습니다.https://github.com/serzmerz/react-native-progress-bar
import Animated, { Clock } from "react-native-reanimated";
const { set, useCode } = Animated;
export default function useAnimatedColor(color) {
const colorValue = useRef(new Animated.Value(0));
...
// create clock instance and memoize it
const clock = useRef(new Clock());
useCode(() => {
const [from, to] = inputRange;
return [set(colorValue.current, runTiming(clock.current, from, to))];
}, [color]);
}
우리가 이 갈고리에서 한 마지막 일 - 색깔 삽입값, 이 갈고리의 전체 코드는 다음과 같다.const inputRange = [0, 50];
export default function useAnimatedColor(color) {
const colorValue = useRef(new Animated.Value(0));
const prevColor = useRef(color);
// call our interpolateColors and wrap it to useMemo
const backgroundColor = useMemo(
() =>
interpolateColors(colorValue.current, {
inputRange,
outputColorRange: [prevColor.current, color]
}),
[color]
);
prevColor.current = color;
const clock = useRef(new Clock());
useCode(() => {
const [from, to] = inputRange;
return [set(colorValue.current, runTiming(clock.current, from, to))];
}, [color]);
return backgroundColor;
}
플러그인 색상 함수는요?현재reactnativereanimated는 코드 라이브러리에서 실행되었지만 아직 발표되지 않았습니다.이 강좌를 읽고reactnativereanimated의 버전이 1.9.0보다 높으면, 이 함수는 그 안에 있어야 합니다.참고로 우리는 이 함수의 작업 원리를 깊이 이해한다.
import { processColor } from "react-native";
import Animated, { round, color, interpolate, Extrapolate } from "react-native-reanimated";
// functions for getting each part of our color
function red(c) {
return (c >> 16) & 255;
}
function green(c) {
return (c >> 8) & 255;
}
function blue(c) {
return c & 255;
}
function opacity(c) {
return ((c >> 24) & 255) / 255;
}
/**
* Use this if you want to interpolate an `Animated.Value` into color values.
*
* #### Why is this needed?
*
* Unfortunately, if you'll pass color values directly into the `outputRange` option
* of `interpolate()` function, that won't really work (at least at the moment).
* See https://github.com/software-mansion/react-native-reanimated/issues/181 .
*
* So, for now you can just use this helper instead.
*/
export default function interpolateColors(animationValue, options) {
const { inputRange, outputColorRange } = options;
// convert our colors to rgba format
const colors = outputColorRange.map(processColor);
// interpolate each part of our color
const r = round(
interpolate(animationValue, {
inputRange,
// map only necessary part
outputRange: colors.map(red),
extrapolate: Extrapolate.CLAMP
})
);
const g = round(
interpolate(animationValue, {
inputRange,
outputRange: colors.map(green),
extrapolate: Extrapolate.CLAMP
})
);
const b = round(
interpolate(animationValue, {
inputRange,
outputRange: colors.map(blue),
extrapolate: Extrapolate.CLAMP
})
);
const a = interpolate(animationValue, {
inputRange,
outputRange: colors.map(opacity),
extrapolate: Extrapolate.CLAMP
});
// combine all parts to one color interpolation
return color(r, g, b, a);
}
이렇게 하면 Animated Progress 구성 요소에서 우리의 갈고리를 호출할 수 있습니다.const AnimatedProgress = ({ fill, current, total }) => {
const backgroundColor = useAnimatedColor(fill);
...
// pass animated props to view
<Animated.View style={[styles.progress, { backgroundColor, transform: [{ translateX }] }]} />
...
}
너는 인터넷과 휴대전화의 배치가 같다는 것을 알아차렸니?
오늘의 마지막 일은 크로스플랫폼 제작 진도표 구성 요소입니다.
이 목표를 실현하기 위해서는 두 가지 절차를 취해야 한다.
1) 우리의 연결고리를 두 개의 연결고리로 나눈다.
- 애니메이션 색상을 사용합니다.js/useAnimatedColor.출생지의회사 명
- 애니메이션 진행 상태를 사용합니다.js/useAnimatedProgress.출생지의회사 명
.출생지의js 확장은 metrobundler가 모바일 플랫폼에 불러옵니다.
.js 확장은 웹에 불러옵니다.
웹에 대해 우리는 단지 이러한 연결을 간소화하기만 하면 된다.모든 애니메이션은transition 속성으로 완성됩니다.
애니메이션 색상을 사용합니다.js:
export default function useAnimatedColor(color) {
return color;
}
애니메이션을 사용하여 진행합니다.회사 명export default function useAnimatedProgress(width, percent) {
return width * percent;
}
2) 스타일에서 웹 응용 프로그램에 변환을 추가합니다.export default StyleSheet.create({
...
progress: {
...
// select only web for avoiding error on mobile devices
...Platform.select({ web: { transition: "0.3s all ease-in-out" } })
}
});
와!우리는 이미 모든 플랫폼을 위해 로컬 애니메이션이 있는 크로스플랫폼 구성 요소를 구축했다.github에서 모든 소스 코드를 찾을 수 있습니다: https://github.com/serzmerz/react-native-progress-bar
사용 예: https://github.com/serzmerz/TestReactNativeProgressBar
당신의 목적을 위해 완성된 라이브러리를 설치합니다.
yarn add react-native-reanimated-progress-bar
Reference
이 문제에 관하여(React Native가 있는 진행률 표시줄 애니메이션에 대한 이야기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/serzmerz/the-story-about-one-progress-bar-animation-with-react-native-3mej텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)