Skip to content

Commit d018c0d

Browse files
committed
feat: improve animations
1 parent bd5309e commit d018c0d

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

docs/articles/api/animation.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,40 @@
11
# animation
22

3-
Helpers for driving simple animations without the Web Animations API.
3+
Helpers for driving simple animations and for leveraging the Web Animations API.
44

55
- `Translate(sel, from, to, dur)` moves elements.
66
- `Fade(sel, from, to, dur)` adjusts opacity.
77
- `Scale(sel, from, to, dur)` scales elements.
88
- `ColorCycle(sel, colors, dur)` cycles background colors.
9+
- `Keyframes(sel, frames, opts)` runs a Web Animations API sequence and
10+
returns the underlying `Animation` object.
911

1012
## Usage
1113

1214
Call the animation helpers with a CSS selector, starting and ending values,
1315
and a duration. They can be invoked from event handlers registered in the DOM.
16+
`Keyframes` accepts arrays of frame definitions and option maps that are
17+
passed directly to the browser's `Element.animate` API.
1418

1519
## Example
1620

1721
```go
1822
dom.RegisterHandlerFunc("animateFade", func() {
1923
anim.Fade("#fadeBox", 1, 0, 500*time.Millisecond)
2024
})
25+
26+
dom.RegisterHandlerFunc("animateSpin", func() {
27+
frames := []map[string]any{
28+
{"transform": "rotate(0deg)"},
29+
{"transform": "rotate(360deg)"},
30+
}
31+
opts := map[string]any{"duration": 500, "iterations": 1}
32+
anim.Keyframes("#spinBox", frames, opts)
33+
})
2134
```
2235

2336
1. `dom.RegisterHandlerFunc` links the `animateFade` ID to a Go function.
2437
2. When triggered, `anim.Fade` fades `#fadeBox` from opaque to transparent
2538
over half a second.
39+
3. `anim.Keyframes` delegates to the Web Animations API to spin `#spinBox`
40+
once around its center.

example/components/animation_component.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ func NewAnimationComponent() *core.HTMLComponent {
3535
colors := []string{"red", "orange", "yellow", "green", "blue", "indigo", "violet"}
3636
anim.ColorCycle("#rainbowBox", colors, 700*time.Millisecond)
3737
})
38+
dom.RegisterHandlerFunc("animateKeyframes", func() {
39+
frames := []map[string]any{
40+
{"transform": "rotate(0deg)"},
41+
{"transform": "rotate(360deg)"},
42+
}
43+
opts := map[string]any{
44+
"duration": 700,
45+
"iterations": 1,
46+
}
47+
anim.Keyframes("#keyframesBox", frames, opts)
48+
})
3849

3950
return c
4051
}

example/components/templates/animation_component.rtml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,10 @@
2121
<div id="rainbowBox" class="w-16 h-16 bg-purple-500"></div>
2222
<button class="mt-2 bg-purple-500 text-white px-3 py-1 rounded" @click:animateRainbow>Color Cycle</button>
2323
</div>
24+
<div>
25+
<h2 class="text-lg font-semibold mb-2">Web Animations API</h2>
26+
<div id="keyframesBox" class="w-16 h-16 bg-yellow-500"></div>
27+
<button class="mt-2 bg-yellow-500 text-white px-3 py-1 rounded" @click:animateKeyframes>Spin</button>
28+
</div>
2429
</div>
2530
</root>

v1/animation/animation.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,34 @@ func animate(el jst.Value, duration time.Duration, step func(p float64)) {
3838
js.RequestAnimationFrame(cb)
3939
}
4040

41+
// Keyframes leverages the Web Animations API to animate the selected element
42+
// using the provided keyframes and options. The returned value is the
43+
// underlying Animation object, allowing further control if needed.
44+
func Keyframes(sel string, keyframes []map[string]any, options map[string]any) jst.Value {
45+
el := query(sel)
46+
47+
frames := make([]any, len(keyframes))
48+
for i, f := range keyframes {
49+
frames[i] = f
50+
}
51+
52+
opts := make(map[string]any, len(options))
53+
for k, v := range options {
54+
switch n := v.(type) {
55+
case int:
56+
opts[k] = float64(n)
57+
case int32:
58+
opts[k] = float64(n)
59+
case int64:
60+
opts[k] = float64(n)
61+
default:
62+
opts[k] = v
63+
}
64+
}
65+
66+
return el.Call("animate", frames, opts)
67+
}
68+
4169
// Translate moves the element selected by sel from the starting coordinates
4270
// to the destination using a translate transform.
4371
func Translate(sel string, fromX, fromY, toX, toY float64, duration time.Duration) {

0 commit comments

Comments
 (0)