본문으로 건너뛰기

PlAnimateAppear

여러 개가 차례로 제자리에 내려앉습니다. 효과가 개별 항목이 아니라 묶음에 속하므로, 읽는 사람의 눈이 읽어야 할 순서대로 목록을 따라 내려갑니다.

React
tsx
import { PlAnimateAppear } from 'plass-ui';

<PlAnimateAppear className="flex flex-col gap-2">
  {services.map((service) => (
    <PlCard key={service.name} title={service.name} />
  ))}
</PlAnimateAppear>;
dart
import 'package:plass_ui/plass_ui.dart';

PlAnimateAppear(
  spacing: 8,
  children: <Widget>[
    for (final Service service in services) PlCard(title: Text(service.name)),
  ],
);

Props

Prop타입기본값설명
staggernumber70한 자식 뒤 다음 자식이 시작하기까지의 시간(ms). 이것이 효과의 전부이고, 나머지는 자식 하나가 하는 일입니다
durationStep공통number0자식마다 duration에 더해지는 시간(ms). 음수도 되고, 0 아래로는 내려가지 않습니다
from공통'top' | 'right' | 'bottom' | 'left''bottom'각 자식이 들어오는 모서리
distancenumber | string'0.75rem'각 자식이 이동하는 거리. 짧은 것은 의도입니다 — 화면 밖에서의 등장이 아니라 내려앉음이고, 여덟 개짜리 목록 위의 긴 이동은 덩어리 전체를 움직이는 것으로 만듭니다
fadebooleantrue각 자식이 내려앉으면서 함께 나타납니다
reversebooleanfalse마지막 자식부터 첫 자식까지 목록을 거꾸로 돌립니다
duration공통number380한 번 도는 데 걸리는 시간(ms). CSS 문자열이 아니라 숫자입니다
delay공통number0시작하기까지 기다리는 시간(ms)
easing공통stringthe house curveCSS가 쓰는 그대로의 이징 곡선
repeat공통number | 'infinite'1몇 번 반복할지. 끝없이 돌리려면 Infinity가 아니라 'infinite' — CSS에 그 단어로 그대로 쓰이기 때문입니다
alternate공통booleanfalse한 번 걸러 거꾸로 돌립니다. 반복이 처음으로 튀어 돌아가는 대신 되돌아옵니다
paused공통booleanfalse있는 자리에 멈춰 세웁니다
trigger공통'mount' | 'visible' | 'hover' | 'manual''mount'무엇이 시작시키는지. mount는 화면에 올라오자마자, visible은 스크롤되어 보일 때, hover는 포인터나 focus가 닿을 때, manual은 play가 시킬 때만
play공통booleantrigger가 manual일 때 실행합니다. false → true가 될 때마다 처음부터 다시 돕니다
once공통booleantruetrigger="visible"에서 처음 한 번만 돌릴지. 끄면 화면에 다시 들어올 때마다 다시 돕니다
threshold공통number0.2trigger="visible"에서 얼마나 보여야 보이는 것으로 칠지, 0에서 1 사이
renderReactElement | (props, state) => ReactElement<div> 대신 다른 요소로 렌더링합니다
Prop타입기본값설명
children * List<Widget>차례로 나타나는 것들. 시차는 자식마다 세므로, 여덟 개를 담은 자식 하나는 한 단계입니다
orientation공통PlassOrientationPlassOrientation.vertical묶음이 흐르는 방향. React 쪽에서 className이 하던 일입니다 — 여기에는 컨테이너에 display를 걸어 줄 스타일시트가 없습니다
spacingdouble0자식 사이의 간격(논리 픽셀)
staggerDurationDuration(milliseconds: 70)한 자식 뒤 다음 자식이 시작하기까지의 시간(ms). 이것이 효과의 전부이고, 나머지는 자식 하나가 하는 일입니다
from공통PlassSidePlassSide.bottom각 자식이 들어오는 모서리
distancedouble12각 자식이 이동하는 거리. 짧은 것은 의도입니다 — 화면 밖에서의 등장이 아니라 내려앉음이고, 여덟 개짜리 목록 위의 긴 이동은 덩어리 전체를 움직이는 것으로 만듭니다
fadebooltrue각 자식이 내려앉으면서 함께 나타납니다
reverseboolfalse마지막 자식부터 첫 자식까지 목록을 거꾸로 돌립니다
duration공통DurationDuration(milliseconds: 380)한 번 도는 데 걸리는 시간(ms). CSS 문자열이 아니라 숫자입니다
delay공통DurationDuration.zero시작하기까지 기다리는 시간(ms)
curve공통Curve?the house curveCSS가 쓰는 그대로의 이징 곡선
repeat공통int?1몇 번 반복할지. null이 멈추지 않음을 뜻합니다 — 적을 'infinite'가 없고, -1은 찾아봐야 하는 sentinel입니다
alternate공통boolfalse한 번 걸러 거꾸로 돌립니다. 반복이 처음으로 튀어 돌아가는 대신 되돌아옵니다
paused공통boolfalse있는 자리에 멈춰 세웁니다
trigger공통PlassAnimateTriggerPlassAnimateTrigger.mount무엇이 시작시키는지. mount는 화면에 올라오자마자, visible은 스크롤되어 보일 때, hover는 포인터나 focus가 닿을 때, manual은 play가 시킬 때만
play공통boolfalsetrigger가 manual일 때 실행합니다. false → true가 될 때마다 처음부터 다시 돕니다
once공통booltruetrigger="visible"에서 처음 한 번만 돌릴지. 끄면 화면에 다시 들어올 때마다 다시 돕니다
threshold공통double0.2trigger="visible"에서 얼마나 보여야 보이는 것으로 칠지, 0에서 1 사이

애니메이션은 자식을 감싸는 wrapper가 아니라 자식 자신에게 쓰입니다. <li> 한 줄은 <li> 한 줄로 남고, 그리드의 셀은 그리드의 직계 자식으로 남고, 목록이 애니메이션된다고 레이아웃에 대해 달라지는 것이 없습니다. 자식이 이미 가지고 있던 class와 style은 이것이 더하는 것 옆에 그대로 남습니다. 맨 문자열만은 쓸 요소가 없어서 <span>으로 감싸집니다.

네이티브 <div> 속성은 그대로 통과하고, render로 컨테이너를 다른 요소로 바꿀 수 있습니다.

이 widget은 자식을 직접 배치합니다. React 빌드는 그럴 필요가 없죠. 여기에는 컨테이너에 display: flex를 걸어 줄 스타일시트가 없으므로, orientationspacingclassName이 했을 일을 합니다. 행이나 열보다 복잡한 배치는 자식 에 두세요. 그러면 그 배치 전체가 시차의 한 단계가 되기도 합니다. distance는 논리 픽셀 단위의 double입니다.

공유되는 열 가지 설정 — duration, delay, easing, repeat, alternate, paused, trigger, play, once, threshold — 은 모든 PlAnimate* 컴포넌트에서 같습니다. delay첫 단계 이전에 일어나는 일이므로, 자식마다가 아니라 한 번만 더해집니다.

Examples

stagger

효과의 전부입니다. 나머지는 자식 하나가 하는 일 — 짧은 이동과 fade — 이고, 그것을 순서로 만드는 것이 시차입니다.

자식을 세지, 잎을 세지 않습니다. 자식 여덟이면 여덟 단계이고, 여덟 개를 담은 자식 하나는 한 단계입니다. 목록의 일부를 빼는 방법도 이것입니다. 묶으세요.

React

from and reverse

from은 각 자식이 들어오는 모서리이고, reverse는 마지막 자식부터 첫 자식까지 목록을 거꾸로 돌립니다. 거리가 짧은 것은 의도입니다. 이것은 화면 밖에서의 등장이 아니라 내려앉음이고, 여덟 개짜리 목록 위에서의 긴 이동은 덩어리 전체를 움직이는 무언가로 만듭니다. 하나가 먼 데서 오는 것이라면 PlAnimateSlide를 쓰세요.

React

Accessibility

  • prefers-reduced-motion에서는 애니메이션이 통째로 없어지고 목록 전체가 그냥 거기 있습니다.
  • 어느 시점에도 스크린리더에게 숨겨지는 것은 없습니다. 자식은 전부 첫 프레임부터 문서에 있고, 시차가 붙는 것은 각각이 언제 그려지는지이지 언제 존재하는지가 아닙니다.
  • 전체 길이를 짧게 두세요. 자식 여덟에 70ms면 마지막이 앉기까지 0.5초이고, 300ms면 2.5초입니다. 그동안 읽는 사람은 완성되지 않은 목록을 보고 있습니다.
  • 시차는 장식이지 순서가 아닙니다. 순서가 중요하다면 마크업에 있어야 합니다.
  • 플랫폼에서 애니메이션이 꺼져 있으면(MediaQuery.disableAnimations) 효과가 통째로 없어지고 목록 전체가 그냥 거기 있습니다.
  • 어느 시점에도 스크린리더에게 숨겨지는 것은 없습니다. 모든 자식은 첫 프레임부터 트리에 있고, 시차가 붙는 것은 각각이 언제 그려지는지이지 언제 존재하는지가 아닙니다.
  • 전체 길이를 짧게 두세요. 자식 여덟에 70ms면 마지막이 앉기까지 0.5초이고, 300ms면 2.5초입니다.
  • 시차는 장식이지 순서가 아닙니다. 순서가 중요하다면 트리에 있어야 합니다.

React 빌드와 다른 점

ReactFlutter이유
애니메이션을 자식 자신의 classNamestyle에 씀자식을 각각 감쌈더할 class 목록이 없습니다. 감싸는 것은 Flex에 투명하지만, 무언가의 직계 자식이어야 하는 것 — Expanded 같은 — 은 이 widget 바깥에 두어야 합니다.
컨테이너가 caller가 스타일링하는 맨 <div>orientationspacing스타일시트가 없으니 widget이 자식을 배치해야 합니다.
distance가 CSS 길이double논리 픽셀입니다.
renderFlutter에는 다형적 요소가 없습니다.
duration, delay가 밀리초Duration프레임워크에 이미 타입이 있습니다.
easing이 CSS 문자열curve, Curve같은 것에 대한 Dart 자신의 이름입니다.
repeat: number | 'infinite'int?, null이 멈추지 않음적을 'infinite'가 없고, -1은 caller가 찾아봐야 하는 sentinel입니다.
trigger="visible"IntersectionObserver가장 가까운 Scrollable을 봅니다여기에는 observer가 없습니다. 위에 scrollable이 없으면 볼 것이 없으므로 그냥 돕니다.
prefers-reduced-motionMediaQuery.disableAnimations플랫폼 자신의 신호입니다.
className, style통과시킬 class 목록도 style 속성도 없습니다.

Released under the MIT License