reglScatterplot is a thin R wrapper around the
JavaScript regl-scatterplot
library, exposing it as an htmlwidgets widget. It renders
millions of two-dimensional points in the browser via
WebGL, which makes it well suited to:
(x, y) scatter that ggplot2 would draw too
slowly.The widget works in:
htmlwidgets::saveWidget(),IRkernel
(e.g. VSCode’s Jupyter extension).The simplest call needs only a data.frame and the names
of the two coordinate columns.
Pass a character or factor column name (or vector) to
colorBy. A draggable legend appears in the upper-right
corner of the plot; clicking a legend entry filters the data, and
shift/ctrl-click extends the selection.
Numeric colorBy produces a continuous colour scale. Use
vmin/vmax to clip outliers; the strings
"p1", "p99" and so on select percentiles.
reglScatterplot(df,
x = "x", y = "y", colorBy = "score",
continuousPalette = "magma",
vmin = "p1", vmax = "p99"
)For log-fold-change-style data use centerZero = TRUE to
force a symmetric diverging scale.
reglScatterplot() accepts any
data.frame-like object. To plot a UMAP embedding stored in
a SingleCellExperiment, build a small data frame from its
reducedDim() and colData() slots:
When several reglScatterplot() widgets share the same
plotIds, you can synchronise pan/zoom across them with
enableReglScatterplotSync():
library(shiny)
ui <- fluidPage(
fluidRow(
column(6, reglScatterplotOutput("plotA")),
column(6, reglScatterplotOutput("plotB"))
),
actionButton("link", "Link cameras")
)
server <- function(input, output, session) {
output$plotA <- renderReglScatterplot({
reglScatterplot(df,
x = "x", y = "y", colorBy = "cluster",
plotId = "plotA"
)
})
output$plotB <- renderReglScatterplot({
reglScatterplot(df,
x = "x", y = "y", colorBy = "score",
plotId = "plotB"
)
})
observeEvent(input$link, {
enableReglScatterplotSync(c("plotA", "plotB"))
})
}
shinyApp(ui, server)On first use the JavaScript bundles (d3,
regl-scatterplot, pickr,
html2canvas, jsPDF) are loaded from a CDN
(esm.sh and cdnjs.cloudflare.com). Once loaded
they are cached by the browser. A helpful error message is displayed
in-place if the network is unavailable.
sessionInfo()
#> R version 4.6.0 (2026-04-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] reglScatterplotR_0.99.3
#>
#> loaded via a namespace (and not attached):
#> [1] digest_0.6.39 RColorBrewer_1.1-3 R6_2.6.1 fastmap_1.2.0
#> [5] xfun_0.58 maketools_1.3.2 cachem_1.1.0 knitr_1.51
#> [9] htmltools_0.5.9 rmarkdown_2.31 buildtools_1.0.0 lifecycle_1.0.5
#> [13] cli_3.6.6 viridisLite_0.4.3 sass_0.4.10 jquerylib_0.1.4
#> [17] compiler_4.6.0 sys_3.4.3 tools_4.6.0 evaluate_1.0.5
#> [21] bslib_0.11.0 yaml_2.3.12 otel_0.2.0 htmlwidgets_1.6.4
#> [25] jsonlite_2.0.0 rlang_1.2.0 crosstalk_1.2.2