timeline

package module
v0.0.0-...-0bc4896 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 29, 2025 License: MIT Imports: 0 Imported by: 0

README

timeline

Go Reference

A Go library for time-based sequencing of animations and events.

Overview

Timeline provides a fluent API for scheduling callbacks based on elapsed time. It supports sequential spans, finite loops, and infinite loops with progress tracking.

Usage

Basic Timeline

Create a timeline with current time:

tl := timeline.New(currentTime)
Sequential Spans

Execute callbacks within specific time ranges:

timeline.New(t).
    Span(3, func(tl Timeline[int]) {
        // Executes when t is in [0,3)
        fmt.Println("First span, elapsed:", tl.Elapsed())
    }).
    Span(5, func(tl Timeline[int]) {
        // Executes when t is in [3,8)
        fmt.Println("Second span, elapsed:", tl.Elapsed())
    })
Loops

Repeat callbacks at fixed intervals:

// Finite loop (2 iterations)
timeline.New(t).
    LoopN(4, 2, func(n int, tl Timeline[int]) {
        // Executes at t=0,1,2,3 (n=0) and t=4,5,6,7 (n=1)
        fmt.Printf("Loop %d, progress: %.0f%%\n", n, tl.Ratio()*100)
    })

// Infinite loop
timeline.New(t).
    Loop(3, func(n int, tl Timeline[int]) {
        // Executes every 3 time units forever
        fmt.Printf("Cycle %d\n", n)
    })
Progress Tracking

Get elapsed time and progress ratio:

elapsed := tl.Elapsed()        // Time since segment start
elapsedF := tl.Elapsedf()     // As float64
ratio := tl.Ratio()           // Progress (0.0 to 1.0)
One-time Events

Execute callbacks at specific time points:

timeline.New(t).
    Once(func() {
        // Executes when t=0 (initialization)
    }).
    Span(3, func(tl Timeline[int]) {
        // Executes during t=0,1,2
    }).
    Once(func() {
        // Executes when t=3 (transition)
    })

Note: Once only executes when time exactly matches the current position. It may not work reliably with variable time steps.

Nested Timelines

Create complex timing patterns by nesting timelines:

timeline.New(t).
    Span(6, func(tl Timeline[int]) {
        // Create inner timeline based on outer timeline's elapsed time
        tl.
            LoopN(3, 2, func(n int, tl Timeline[int]) {
                // Inner timeline executes within outer span
                fmt.Printf("Inner loop %d\n", n)
            })
    })

This allows for sophisticated animation sequences where inner timelines can have their own independent timing logic while being synchronized with outer timelines.

Examples

See example_test.go for complete examples.

License

MIT

Documentation

Overview

Package timeline provides time-based sequencing for animations and events.

Example
package main

import (
	"fmt"

	"github.com/eihigh/timeline"
)

type TL = timeline.Timeline[int]

func main() {
	// Span: Execute callbacks only within defined time ranges
	fmt.Println("=== Span Example ===")
	for t := range 8 {
		timeline.New(t).
			Span(3, func(tl TL) {
				fmt.Printf("t=%d: In span [0,3), elapsed=%d\n", t, tl.Elapsed())
			}).
			Span(3, func(tl TL) {
				fmt.Printf("t=%d: In span [3,6), elapsed=%d\n", t, tl.Elapsed())
			})
	}

	// LoopN: Execute callbacks n times at fixed intervals
	fmt.Println("=== LoopN Example ===")
	for t := range 10 {
		timeline.New(t).
			LoopN(4, 2, func(n int, tl TL) { // Every 4 units, repeat 2 times
				fmt.Printf("t=%d: Loop %d, elapsed=%d, ratio=%v\n", t, n, tl.Elapsed(), tl.Ratio())
			})
	}

	// Loop: Execute callbacks indefinitely at fixed intervals
	fmt.Println("=== Loop Example ===")
	for t := range 8 {
		timeline.New(t).
			Loop(3, func(n int, tl TL) { // Every 3 units, repeat forever
				fmt.Printf("t=%d: Infinite loop %d, elapsed=%d\n", t, n, tl.Elapsed())
			})
	}

}
Output:
=== Span Example ===
t=0: In span [0,3), elapsed=0
t=1: In span [0,3), elapsed=1
t=2: In span [0,3), elapsed=2
t=3: In span [3,6), elapsed=0
t=4: In span [3,6), elapsed=1
t=5: In span [3,6), elapsed=2
=== LoopN Example ===
t=0: Loop 0, elapsed=0, ratio=0
t=1: Loop 0, elapsed=1, ratio=0.25
t=2: Loop 0, elapsed=2, ratio=0.5
t=3: Loop 0, elapsed=3, ratio=0.75
t=4: Loop 1, elapsed=0, ratio=0
t=5: Loop 1, elapsed=1, ratio=0.25
t=6: Loop 1, elapsed=2, ratio=0.5
t=7: Loop 1, elapsed=3, ratio=0.75
=== Loop Example ===
t=0: Infinite loop 0, elapsed=0
t=1: Infinite loop 0, elapsed=1
t=2: Infinite loop 0, elapsed=2
t=3: Infinite loop 1, elapsed=0
t=4: Infinite loop 1, elapsed=1
t=5: Infinite loop 1, elapsed=2
t=6: Infinite loop 2, elapsed=0
t=7: Infinite loop 2, elapsed=1
Example (Nested)
package main

import (
	"fmt"

	"github.com/eihigh/timeline"
)

type TL = timeline.Timeline[int]

func main() {
	// Nested timelines allow complex timing patterns
	fmt.Println("=== Nested Timeline Example ===")
	for t := range 12 {
		tl := timeline.New(t)
		tl.
			// Outer timeline: 3 spans of 6 units each
			Span(6, func(tl TL) {
				fmt.Printf("t=%d: Outer span 1, ", t)
				// Inner timeline: 2 loops within the outer span
				tl.
					Loop(3, func(n int, tl TL) {
						fmt.Printf("inner loop %d (elapsed=%d)\n", n, tl.Elapsed())
					})
			}).
			Span(6, func(tl TL) {
				fmt.Printf("t=%d: Outer span 2, ", t)
				// Inner timeline: spans within the outer span
				tl.
					Span(2, func(tl TL) {
						fmt.Printf("inner span A (ratio=%.1f)\n", tl.Ratio())
					}).
					Span(2, func(tl TL) {
						fmt.Printf("inner span B (ratio=%.1f)\n", tl.Ratio())
					}).
					Span(2, func(tl TL) {
						fmt.Printf("inner span C (ratio=%.1f)\n", tl.Ratio())
					})
			})
	}

}
Output:
=== Nested Timeline Example ===
t=0: Outer span 1, inner loop 0 (elapsed=0)
t=1: Outer span 1, inner loop 0 (elapsed=1)
t=2: Outer span 1, inner loop 0 (elapsed=2)
t=3: Outer span 1, inner loop 1 (elapsed=0)
t=4: Outer span 1, inner loop 1 (elapsed=1)
t=5: Outer span 1, inner loop 1 (elapsed=2)
t=6: Outer span 2, inner span A (ratio=0.0)
t=7: Outer span 2, inner span A (ratio=0.5)
t=8: Outer span 2, inner span B (ratio=0.0)
t=9: Outer span 2, inner span B (ratio=0.5)
t=10: Outer span 2, inner span C (ratio=0.0)
t=11: Outer span 2, inner span C (ratio=0.5)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Timeline

type Timeline[T integer] struct {
	// contains filtered or unexported fields
}

Timeline is a builder for creating time-based sequences of animations and events.

func New

func New[T integer](now T) Timeline[T]

New creates a timeline starting at 0 with the given current time.

func (Timeline[T]) Elapsed

func (t Timeline[T]) Elapsed() T

Elapsed returns time passed since start.

func (Timeline[T]) ElapsedF

func (t Timeline[T]) ElapsedF() float64

ElapsedF returns elapsed time as float64.

func (Timeline[T]) Loop

func (t Timeline[T]) Loop(duration T, f ...func(int, Timeline[T]))

Loop repeats callbacks indefinitely at fixed intervals.

func (Timeline[T]) LoopN

func (t Timeline[T]) LoopN(duration T, n int, f ...func(int, Timeline[T])) Timeline[T]

LoopN repeats callbacks n times at fixed intervals.

func (Timeline[T]) Once

func (t Timeline[T]) Once(f ...func()) Timeline[T]

Once executes callbacks at the current time point. This is useful for one-time events like playing sounds or initializing states.

Note: This method only executes when Elapsed() returns 0. It may not work reliably with variable time steps or when frames are skipped. For reliable execution, ensure time increments by consistent steps (e.g., 1 per frame).

Example
package main

import (
	"fmt"

	"github.com/eihigh/timeline"
)

type TL = timeline.Timeline[int]

func main() {
	// Once: Execute callbacks at specific time points
	fmt.Println("=== Once Example ===")
	for t := range 10 {
		timeline.New(t).
			Once(func() {
				fmt.Printf("t=%d: Initialize at start\n", t)
			}).
			Span(3, func(tl TL) {
				fmt.Printf("t=%d: Animation phase 1 (elapsed=%d)\n", t, tl.Elapsed())
			}).
			Once(func() {
				fmt.Printf("t=%d: Play sound effect\n", t)
			}).
			Span(4, func(tl TL) {
				fmt.Printf("t=%d: Animation phase 2 (elapsed=%d)\n", t, tl.Elapsed())
			}).
			Once(func() {
				fmt.Printf("t=%d: Cleanup\n", t)
			})
	}

}
Output:
=== Once Example ===
t=0: Initialize at start
t=0: Animation phase 1 (elapsed=0)
t=1: Animation phase 1 (elapsed=1)
t=2: Animation phase 1 (elapsed=2)
t=3: Play sound effect
t=3: Animation phase 2 (elapsed=0)
t=4: Animation phase 2 (elapsed=1)
t=5: Animation phase 2 (elapsed=2)
t=6: Animation phase 2 (elapsed=3)
t=7: Cleanup

func (Timeline[T]) Ratio

func (t Timeline[T]) Ratio() float64

Ratio returns progress within the current span (0.0 to 1.0).

Example
package main

import (
	"fmt"

	"github.com/eihigh/timeline"
)

type TL = timeline.Timeline[int]

func main() {
	for t := range 15 {
		timeline.New(t).
			Span(5, func(tl TL) {
				fmt.Print(tl.Ratio(), " ")
			}).
			Span(10, func(tl TL) {
				fmt.Print(tl.Ratio(), " ")
			})
	}

}
Output:
0 0.2 0.4 0.6 0.8 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9

func (Timeline[T]) Span

func (t Timeline[T]) Span(duration T, f ...func(Timeline[T])) Timeline[T]

Span defines a time segment and executes callbacks within it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL