R/timeline.R

Defines functions anime_add anime_timeline

Documented in anime_add anime_timeline

#' Initialise an Anime.js timeline
#'
#' @param duration Default duration in milliseconds for all segments.
#' @param ease Default easing for all segments, an `anime_easing` object or an
#'   Anime.js easing name string.
#' @param delay Default delay in milliseconds between segments.
#' @param loop Logical or positive integer. `FALSE` for no looping, `TRUE` for
#'   infinite looping, or a fixed number of iterations.
#'
#' @examples
#' anime_timeline(duration = 800, ease = anime_easing())
#'
#' @return An `anime_timeline` object.
#' @export
anime_timeline <- function(
  duration = 1000,
  ease = anime_easing(),
  delay = 0,
  loop = FALSE
) {
  validate_duration(duration, "duration")
  check_ease(ease)
  validate_duration(delay, "delay")
  check_loop(loop)

  structure(
    list(
      defaults = list(
        duration = duration,
        ease = ease,
        delay = delay
      ),
      loop = loop,
      segments = list(),
      events = list()
    ),
    class = "anime_timeline"
  )
}

#' Add an animation segment to a timeline
#'
#' Pipe-friendly. Each call appends one segment: a set of CSS property
#' animations applied to a target selector.
#'
#' @param timeline An `anime_timeline` object.
#' @param selector CSS selector string identifying the SVG/HTML elements to
#'   animate. Use `anime_target_*()` helpers to construct selectors.
#' @param props A named list of property animations. Values may be scalars,
#'   two-element numeric vectors (from/to), [anime_from_to()] objects, or
#'   [anime_keyframes()] objects.
#' @param offset Timeline position. `"+=N"` means N ms after the previous
#'   segment ends; a bare number is an absolute position in ms.
#' @param duration Overrides the timeline default for this segment.
#' @param ease Overrides the timeline default for this segment.
#' @param delay Overrides the timeline default for this segment.
#' @param stagger An `anime_stagger` object for per-element delay offsets.
#'
#' @examples
#' anime_timeline() |>
#'   anime_add(
#'     selector = anime_target_class("circle"),
#'     props    = list(opacity = anime_from_to(0, 1)),
#'     duration = 600
#'   )
#'
#' @return The modified `anime_timeline` object.
#' @export
anime_add <- function(
  timeline,
  selector,
  props,
  offset = "+=0",
  duration = NULL,
  ease = NULL,
  delay = NULL,
  stagger = NULL
) {
  if (!inherits(timeline, "anime_timeline")) {
    cli::cli_abort(
      c(
        "{.arg timeline} must be an {.cls anime_timeline} object.",
        x = "You supplied {.obj_type_friendly {timeline}}.",
        i = "Create one with {.fn anime_timeline}."
      )
    )
  }
  check_string(selector, "selector")
  check_props(props)
  if (!is.null(duration)) {
    validate_duration(duration, "duration")
  }
  check_ease(ease)
  if (!is.null(delay)) {
    validate_duration(delay, "delay")
  }
  check_stagger(stagger)

  segment <- list(
    selector = selector,
    props = props,
    offset = offset
  )
  if (!is.null(duration)) {
    segment$duration <- duration
  }
  if (!is.null(ease)) {
    segment$ease <- ease
  }
  if (!is.null(delay)) {
    segment$delay <- delay
  }
  if (!is.null(stagger)) {
    segment$stagger <- stagger
  }

  timeline$segments <- c(timeline$segments, list(segment))
  timeline
}

Try the animejs package in your browser

Any scripts or data that you put into this service are public.

animejs documentation built on Aug. 21, 2026, 5:17 p.m.