pub struct Motion { /* private fields */ }Expand description
A declarative animation: preset plus modifiers.
Build with a preset constructor (Motion::fade_up, Motion::fade,
Motion::scale, Motion::slide_left, … — see Preset),
tune with the modifier methods, then either Motion::wrap the markup
or write the attributes by hand (see the module docs).
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let card: Markup = Motion::fade_up().delay(150).wrap(html! {
h2 { "Hello" }
});
assert!(card.into_string().contains(r#"data-motion="fade-up""#));Implementations§
Source§impl Motion
impl Motion
Sourcepub const fn fade_right() -> Self
pub const fn fade_right() -> Self
Fade in while drifting 24px right.
Sourcepub const fn slide_left() -> Self
pub const fn slide_left() -> Self
Fade in while sliding 32px from the right.
Sourcepub const fn slide_right() -> Self
pub const fn slide_right() -> Self
Fade in while sliding 32px from the left.
Sourcepub const fn slide_down() -> Self
pub const fn slide_down() -> Self
Fade in while sinking 32px from above.
Sourcepub const fn parallax(factor: f32) -> Self
pub const fn parallax(factor: f32) -> Self
Scroll-linked drift for hero art and backgrounds.
As the element travels through the viewport, it translates by
factor × its own height: positive lags the scroll (drifts down as
you scroll down), negative moves against it. 0.3 is a good
default; keep |factor| modest — large values fling content away.
Parallax is inherently scroll-linked and ignores the scroll,
scroll_target, and scroll_offset modifiers.
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let html: Markup = Motion::parallax(0.3).wrap(html! { p { "Hi" } });
let s = html.into_string();
assert!(s.contains(r#"data-motion="parallax""#), "{s}");
assert!(s.contains(r#"data-motion-parallax="0.3""#), "{s}");Sourcepub fn scroll_progress() -> Markup
pub fn scroll_progress() -> Markup
Opinionated page-scroll progress bar element.
Renders a fixed top bar that fills left-to-right as the page scrolls — no hand-written JavaScript. Include the plugin stylesheet once per page for the default styling:
use autumn_plugin_motion::{Motion, motion_stylesheet};
use autumn_web::{Markup, html};
let head: Markup = html! { (motion_stylesheet()) };
assert!(head.into_string().contains("/static/_plugins/motion/motion."));
let bar: Markup = Motion::scroll_progress();
let s = bar.into_string();
assert!(s.contains(r#"data-motion="scroll-progress""#), "{s}");
assert!(s.contains(r#"class="motion-progress""#), "{s}");Sourcepub const fn ease(self, ease: Ease) -> Self
pub const fn ease(self, ease: Ease) -> Self
Easing curve (default: a snappy cubic-bezier(0.16,1,0.3,1) applied
by init.js when the attribute is absent).
use autumn_plugin_motion::{Ease, Motion};
use autumn_web::{Markup, html};
let html: Markup = Motion::fade_up()
.ease(Ease::Out)
.wrap(html! { p { "Hi" } });
assert!(html.into_string().contains(r#"data-motion-ease="ease-out""#));Sourcepub const fn repeat(self, n: u32) -> Self
pub const fn repeat(self, n: u32) -> Self
Repeat the animation n times after the first play (so repeat(2)
plays three times total). Useful for pulsing badges and attention
loops.
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let html: Markup = Motion::scale().repeat(2).wrap(html! { p { "Hi" } });
assert!(html.into_string().contains(r#"data-motion-repeat="2""#));Sourcepub const fn repeat_type(self, repeat_type: RepeatType) -> Self
pub const fn repeat_type(self, repeat_type: RepeatType) -> Self
How each repeat cycle restarts: RepeatType::Loop (default),
RepeatType::Reverse, or RepeatType::Mirror (ping-pong).
Sourcepub fn amount(self, amount: impl Into<InViewAmount>) -> Self
pub fn amount(self, amount: impl Into<InViewAmount>) -> Self
How much of the element must be visible before the inView
animation triggers: InViewAmount::Some (default),
InViewAmount::All, or InViewAmount::Fraction. A bare f32
works too, via From:
use autumn_plugin_motion::{InViewAmount, Motion};
use autumn_web::{Markup, html};
let a: Markup = Motion::fade_up().amount(0.5).wrap(html! { p { "Hi" } });
assert!(a.into_string().contains(r#"data-motion-amount="0.5""#));
let b: Markup = Motion::fade_up()
.amount(InViewAmount::All)
.wrap(html! { p { "Hi" } });
assert!(b.into_string().contains(r#"data-motion-amount="all""#));Sourcepub fn margin(self, margin: impl Into<String>) -> Self
pub fn margin(self, margin: impl Into<String>) -> Self
Grow or shrink the viewport used for the inView trigger, in CSS
margin syntax with px or % values — e.g. "-100px" waits until
the element is 100px inside the viewport, "80px" fires early.
Up to four space-separated values, like CSS margin.
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let html: Markup = Motion::fade_up().margin("-100px").wrap(html! { p { "Hi" } });
assert!(html.into_string().contains(r#"data-motion-margin="-100px""#));Sourcepub const fn once(self, once: bool) -> Self
pub const fn once(self, once: bool) -> Self
When false, re-animate every time the element enters the viewport
instead of only the first time.
Sourcepub const fn stagger(self, ms: u32) -> Self
pub const fn stagger(self, ms: u32) -> Self
Cascade the preset over the wrapped element’s direct children, ms
milliseconds apart.
Sourcepub const fn stagger_from(self, from: StaggerFrom) -> Self
pub const fn stagger_from(self, from: StaggerFrom) -> Self
Where the staggered cascade starts: StaggerFrom::First (default),
StaggerFrom::Last, StaggerFrom::Center,
StaggerFrom::Edges, or StaggerFrom::Index. Only applies with
.stagger(ms).
use autumn_plugin_motion::{Motion, StaggerFrom};
use autumn_web::{Markup, html};
let html: Markup = Motion::fade_up()
.stagger(90)
.stagger_from(StaggerFrom::Center)
.wrap(html! { p { "Hi" } });
assert!(
html.into_string().contains(r#"data-motion-stagger-from="center""#)
);Sourcepub const fn stagger_ease(self, ease: Ease) -> Self
pub const fn stagger_ease(self, ease: Ease) -> Self
Ease the stagger distribution across children — e.g. Ease::Out
bunches later children together. Same value syntax as
.ease(); only applies with
.stagger(ms).
Sourcepub const fn scroll(self) -> Self
pub const fn scroll(self) -> Self
Drive the keyframes by scroll progress as the element travels through the viewport, instead of animating on entry.
Sourcepub fn scroll_target(self, selector: impl Into<String>) -> Self
pub fn scroll_target(self, selector: impl Into<String>) -> Self
Drive the scroll-linked keyframes by another element’s traversal
of the viewport — a CSS selector like "#hero". When the selector
matches nothing, the element itself is used.
Implies Motion::scroll.
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let html: Markup = Motion::fade()
.scroll_target("#hero")
.wrap(html! { p { "Hi" } });
let s = html.into_string();
assert!(s.contains(r#"data-motion-scroll-target="#), "{s}");
assert!(s.contains("#hero"), "{s}");
assert!(s.contains("data-motion-scroll"), "{s}");Sourcepub fn scroll_offset(self, offset: [&str; 2]) -> Self
pub fn scroll_offset(self, offset: [&str; 2]) -> Self
Remap the scroll-linked keyframes onto custom viewport edges, e.g.
["start end", "center center"] finishes the animation when the
element’s center reaches the viewport’s center (default
["start end", "end start"]: the full traversal).
Each entry names a target edge and a container edge
(start/center/end, or a number with optional px/%).
Implies Motion::scroll.
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let html: Markup = Motion::fade()
.scroll_offset(["start end", "center center"])
.wrap(html! { p { "Hi" } });
assert!(
html.into_string().contains(
r#"data-motion-scroll-offset="start end,center center""#
)
);Sourcepub const fn hover_scale(self, scale: f32) -> Self
pub const fn hover_scale(self, scale: f32) -> Self
Grow to scale while hovered (e.g. 1.05 for a subtle lift).
The element eases back on pointer leave. Pairs with entrance
presets; combines with Motion::hover_brightness.
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let html: Markup = Motion::fade_up()
.hover_scale(1.05)
.hover_brightness(1.1)
.wrap(html! { p { "Hi" } });
let s = html.into_string();
assert!(s.contains(r#"data-motion-hover="scale(1.05) brightness(1.1)""#), "{s}");Sourcepub const fn hover_brightness(self, brightness: f32) -> Self
pub const fn hover_brightness(self, brightness: f32) -> Self
Brighten to brightness while hovered (e.g. 1.1). Combines with
Motion::hover_scale.
Sourcepub const fn press_scale(self, scale: f32) -> Self
pub const fn press_scale(self, scale: f32) -> Self
Shrink to scale while pressed (e.g. 0.97 for a tactile button).
Releases back on pointer up.
use autumn_plugin_motion::Motion;
use autumn_web::{Markup, html};
let html: Markup = Motion::fade_up().press_scale(0.97).wrap(html! { p { "Hi" } });
assert!(
html.into_string().contains(r#"data-motion-press="scale(0.97)""#)
);Sourcepub fn wrap(self, markup: Markup) -> Markup
pub fn wrap(self, markup: Markup) -> Markup
Wraps markup in a <div> carrying the animation attributes.
This is the Maud-friendly composition path — no attribute splicing, just a wrapper element:
use autumn_plugin_motion::Motion;
use autumn_web::html;
let page = html! {
(Motion::fade_up().delay(100).wrap(html! { p { "Hi" } }))
};Takes markup by value even though Maud only borrows it: the owned
form is the ergonomic call shape (.wrap(html! { ... })).
Trait Implementations§
Auto Trait Implementations§
impl Forget for Motion
impl Freeze for Motion
impl RefUnwindSafe for Motion
impl Send for Motion
impl Sync for Motion
impl Unpin for Motion
impl UnsafeUnpin for Motion
impl UnwindSafe for Motion
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> Scoped for T
impl<T> Scoped for T
Source§fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>
ScopeQuery for this type. Resolves the
registered scope at .load() time, not here.