Skip to main content

blur_demo/
blur_demo.rs

1use motion_canvas_rs::prelude::*;
2use std::time::Duration;
3
4const FAST: Duration = Duration::from_millis(1200);
5const SLOW: Duration = Duration::from_millis(2400);
6const BEAT: Duration = Duration::from_millis(600);
7
8fn main() {
9    let mut project = Project::default()
10        .with_title("Blur Demo")
11        .with_background(Color::rgb8(0x08, 0x08, 0x10))
12        .close_on_finish();
13
14    // Dot Grid Backdrop
15    for x in 1..8 {
16        for y in 1..6 {
17            project.scene.add(
18                Circle::default()
19                    .with_position(Vec2::new(x as f32 * 100.0, y as f32 * 100.0))
20                    .with_radius(1.5)
21                    .with_fill(Color::rgb8(0x1a, 0x1a, 0x2e)),
22            );
23        }
24    }
25
26    // Title
27    let title = TextNode::default()
28        .with_position(Vec2::new(400.0, 60.0))
29        .with_text("Universal Blur")
30        .with_font_size(42.0)
31        .with_fill(Color::rgb8(0xe2, 0xe8, 0xf0))
32        .with_blur(0.0);
33    project.scene.add(&title);
34
35    // Shape
36    let orb = Circle::default()
37        .with_position(Vec2::new(180.0, 220.0))
38        .with_radius(55.0)
39        .with_fill(Color::rgb8(0xa7, 0x6b, 0xf1))
40        .with_opacity(0.9)
41        .with_blur(20.0);
42    project.scene.add(&orb);
43
44    // SVG
45    let logo = SvgNode::default()
46        .with_position(Vec2::new(620.0, 220.0))
47        .with_path("./examples/images/motion-canvas-rs.svg")
48        .with_size(Vec2::new(100.0, 100.0))
49        .with_blur(0.0);
50    project.scene.add(&logo);
51
52    // Math
53    let eq = MathNode::default()
54        .with_position(Vec2::new(200.0, 400.0))
55        .with_equation(r#"E = m c^2"#)
56        .with_font_size(38.0)
57        .with_fill(Color::rgb8(0xfb, 0xd3, 0x8d))
58        .with_blur(0.0);
59    project.scene.add(&eq);
60
61    // Code
62    let snippet = CodeNode::default()
63        .with_position(Vec2::new(400.0, 400.0))
64        .with_language("rs")
65        .with_code("let blur = 20.0;\ncircle.with_blur(blur);")
66        .with_font_size(18.0)
67        .with_blur(0.0);
68    project.scene.add(&snippet);
69
70    // Group
71    let card = GroupNode::new(vec![
72        Box::new(
73            Rect::default()
74                .with_size(Vec2::new(200.0, 90.0))
75                .with_radius(12.0)
76                .with_fill(Color::rgba8(0x38, 0xa1, 0xdb, 0xbb)),
77        ),
78        Box::new(
79            TextNode::default()
80                .with_text("Group Blur")
81                .with_font_size(22.0)
82                .with_fill(Color::WHITE),
83        ),
84    ])
85    .with_position(Vec2::new(400.0, 300.0))
86    .with_blur(0.0);
87    project.scene.add(&card);
88
89    // Subtitle
90    let sub = TextNode::default()
91        .with_position(Vec2::new(400.0, 550.0))
92        .with_text("Shape · SVG · Math · Code · Group")
93        .with_font_size(16.0)
94        .with_fill(Color::rgb8(0x64, 0x6e, 0x7a))
95        .with_blur(0.0);
96    project.scene.add(&sub);
97
98    // Animation: staggered blur waves
99    // Phase 1 — blur everything except the orb (which sharpens)
100    // Phase 2 — restore, then blur the card and equation
101    // Phase 3 — return to initial state
102    project.scene.video_timeline.add(loop_anim!(
103        chain![
104            wait(BEAT),
105            // Phase 1: orb sharpens, everything else softens
106            all![
107                orb.blur.to(0.0, FAST),
108                logo.blur.to(18.0, FAST),
109                eq.blur.to(14.0, FAST),
110                snippet.blur.to(14.0, FAST),
111                card.blur.to(12.0, FAST),
112                title.blur.to(6.0, FAST),
113                sub.blur.to(4.0, FAST),
114            ],
115            wait(BEAT),
116            // Phase 2: card + equation sharp, rest blurred
117            all![
118                orb.blur.to(24.0, SLOW),
119                logo.blur.to(0.0, SLOW),
120                eq.blur.to(0.0, SLOW),
121                snippet.blur.to(18.0, SLOW),
122                card.blur.to(0.0, SLOW),
123                title.blur.to(0.0, SLOW),
124                sub.blur.to(0.0, SLOW),
125            ],
126            wait(BEAT),
127            // Phase 3: return to opening state
128            all![
129                orb.blur.to(20.0, FAST),
130                logo.blur.to(0.0, FAST),
131                eq.blur.to(0.0, FAST),
132                snippet.blur.to(0.0, FAST),
133                card.blur.to(0.0, FAST),
134                title.blur.to(0.0, FAST),
135                sub.blur.to(0.0, FAST),
136            ],
137        ],
138        None,
139    ));
140
141    project.show().expect("Failed to show window");
142}