Skip to contents

Purpose

ggWebGL can render ordered trajectory/path layers with timeline metadata. The examples below use deterministic in-memory data and browser-side WebGL through htmlwidgets; they do not download data or report performance numbers. The widgets autoplay by default and can be paused, scrubbed, or reset with the timeline controls. If a browser throttles a background tab, pressing Play resumes the timeline.

Status. Trajectory paths, trajectory shader encodings, exact/cumulative timeline controls, and Shiny timeline messages are Experimental public APIs. They are suitable for renderer evaluation and small examples, but should not be described as stable performance or animation guarantees.

The relevant renderer pieces are:

2D Cumulative Trajectory

This spiral is rendered as an ordered path with frame metadata and cumulative timeline filtering. The trajectory_age shader makes the time prefix visible as the timeline is scrubbed.

temporal_spiral_widget(height = 460)

3D Trajectory

The helix uses the same path contract, but supplies z and time values. The view is opt-in 3D with an orbit camera.

temporal_helix_widget(height = 460)

Velocity and Direction Encodings

Trajectory velocity and direction are renderer-side visual encodings computed from the serialized path coordinates and timeline values. They do not add application semantics to the data.

temporal_velocity_widget(height = 460)
temporal_direction_widget(height = 460)

Exact Frame Samples

Exact filtering is useful for point-like animated samples. This example shows only the samples whose frame equals the selected timeline value.

temporal_exact_particles_widget(height = 460)

Shiny Timeline Integration

In Shiny, the browser emits the current timeline state as input$<outputId>_timeline. Server code can update the browser-side timeline with updateGgWebGLTimeline().

library(shiny)
library(ggWebGL)

ui <- fluidPage(
  actionButton("restart", "Reset"),
  ggWebGLOutput("plot", height = "420px"),
  verbatimTextOutput("timeline_state")
)

server <- function(input, output, session) {
  output$plot <- renderGgWebGL({
    temporal_helix_widget(height = 460)
  })

  observeEvent(input$restart, {
    updateGgWebGLTimeline(session, "plot", index = 1L, playing = FALSE)
  })

  output$timeline_state <- renderPrint({
    input$plot_timeline
  })
}

if (interactive()) {
  shinyApp(ui, server)
}

The repository also includes a compact optional app at inst/examples/shiny/timeline-control-demo.R.

Limitations

Missing values and group boundaries break paths. Cumulative timeline filtering draws complete visible prefixes; exact path filtering does not interpolate partial hidden segments. Velocity and direction are renderer-side visual encodings. Shiny timeline events report renderer time/frame state; downstream applications remain responsible for interpreting those values.