| Title: | Create Draggable Plots from Projected Geometry |
|---|---|
| Description: | Creates interactive draggable plots from grouped projected 'sf' geometry. The primary deliverable is a browser-based 'D3' helper where regions and labels can be moved freely; users drag, then copy or download the resulting offset tables. Labels can be derived automatically with make_region_labels(), supplied directly with as_drag_labels(), and their moved positions saved and restored with read_label_state() and apply_label_state(). Hierarchical spatial datasets are supported via make_hierarchy_key() and inherit_layout(), which propagate parent-level drag offsets to finer child groupings. Automatic starting layouts are provided by suggest_offsets() using radial, grid, or directional algorithms. Spatial file diagnostics are available through dragmapr_diagnostics(). When a reproducible static image is also needed, render_dragged_map() reconstructs the layout as a 'ggplot2' plot from the source geometry plus the exported offset tables. Project bundles can be written with write_dragmapr_project() and rendered with render_dragmapr_project(). The interactive layer is built on the 'D3' library: Bostock, Ogievetsky and Heer (2011) <doi:10.1109/TVCG.2011.185>. Spatial data handling uses the 'sf' package: Pebesma (2018) <doi:10.32614/RJ-2018-009>. |
| Authors: | George Arthur [aut, cre] (ORCID: <https://orcid.org/0000-0002-1975-1459>) |
| Maintainer: | George Arthur <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-06-23 10:39:06 UTC |
| Source: | https://github.com/prigasg/dragmapr |
apply_label_offsets() is deprecated. Use apply_label_state() instead.
apply_label_offsets(labels, label_offsets = NULL)apply_label_offsets(labels, label_offsets = NULL)
labels |
A data frame from |
label_offsets |
A data frame with |
A label data frame with adjusted x and y.
Apply draggable label state to a label table
apply_label_state(labels, label_state = NULL)apply_label_state(labels, label_state = NULL)
labels |
A data frame from |
label_state |
A data frame with |
A label data frame with adjusted x and y.
labels <- as_drag_labels(data.frame( label_id = "North", region = "North", label = "North", x = 50000, y = 150000, stringsAsFactors = FALSE )) state <- data.frame( label_id = "North", region = "North", dx_m = 5000, dy_m = -2000, stringsAsFactors = FALSE ) apply_label_state(labels, state)labels <- as_drag_labels(data.frame( label_id = "North", region = "North", label = "North", x = 50000, y = 150000, stringsAsFactors = FALSE )) state <- data.frame( label_id = "North", region = "North", dx_m = 5000, dy_m = -2000, stringsAsFactors = FALSE ) apply_label_state(labels, state)
Apply rigid offsets to grouped sf geometries
apply_offsets(x, offsets, region_col)apply_offsets(x, offsets, region_col)
x |
An |
offsets |
A data frame with |
region_col |
Column in |
An sf object with geometries translated by group.
regions <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc(sf::st_point(c(0, 0)), sf::st_point(c(100, 100)), crs = 3857) ) offsets <- data.frame(region = "A", dx_m = 5000, dy_m = -2000) apply_offsets(regions, offsets, region_col = "region")regions <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc(sf::st_point(c(0, 0)), sf::st_point(c(100, 100)), crs = 3857) ) offsets <- data.frame(region = "A", dx_m = 5000, dy_m = -2000) apply_offsets(regions, offsets, region_col = "region")
Annotation boxes use the same position and state workflow as labels, but render as larger text boxes for notes, callouts, or location descriptions.
as_drag_annotations( labels, width_px = 150, height_px = 72, connector = FALSE, connector_type = c("straight", "elbow", "curve", "squiggle") )as_drag_annotations( labels, width_px = 150, height_px = 72, connector = FALSE, connector_type = c("straight", "elbow", "curve", "squiggle") )
labels |
A data frame with |
width_px, height_px
|
Default browser box dimensions for rows that do not
already include |
connector |
Add connector lines from anchors to annotation boxes. |
connector_type |
One of |
A normalized label data frame with label_type = "box".
as_drag_annotations(data.frame( label_id = "note-1", region = "North", label = "This note can hold more text than a short label.", x = 50000, y = 150000 ))as_drag_annotations(data.frame( label_id = "note-1", region = "North", label = "This note can hold more text than a short label.", x = 50000, y = 150000 ))
Use this for user-supplied labels. Extra columns are preserved so interactive applications can carry styling, tooltip, or grouping metadata alongside the core label position columns.
as_drag_labels(labels)as_drag_labels(labels)
labels |
A data frame with |
A normalized label data frame.
as_drag_labels(data.frame( label_id = "note-1", region = "North", label = "Check this", x = 50000, y = 150000, tooltip = "extra metadata" ))as_drag_labels(data.frame( label_id = "note-1", region = "North", label = "Check this", x = 50000, y = 150000, tooltip = "extra metadata" ))
Prepares everything needed to animate child regions blooming out of their parent region: per-child anchor and final positions, relative motion strengths, ready-to-plot animation frames, and the dotted group-drag boundary for each expanded group. The parent layout itself is never moved (stable skeleton); only the expanded branch animates.
build_elastic_transition( child_sf, parent_sf, parent_col, parent_id_col = parent_col, options = transition_options() )build_elastic_transition( child_sf, parent_sf, parent_col, parent_id_col = parent_col, options = transition_options() )
child_sf |
An |
parent_sf |
An |
parent_col |
Column in |
parent_id_col |
Column in |
options |
A list created by |
Children whose parent id has no match in parent_sf fall back to their own
centroid as the anchor (they fade in place instead of blooming), and a
warning lists the unmatched ids so data problems are visible early.
The returned frames interpolate each child from a small seed at the
parent centroid (frame 1) to its exact final geometry (last frame) using an
ease-out-back curve, so the last frame equals child_sf and can be used as
the settled state.
A list of class "dragmapr_transition" with elements:
anchoredchild_sf plus anchor_x, anchor_y, final_x,
final_y, move_dist, move_ratio, stretch_strength, and
duration_ms columns.
framesAn sf object of n_frames stacked copies of the
children with frame_id, frame_progress, and frame_eased columns
and interpolated geometry, suitable for ggplot2 playback or export.
boundariesThe dotted group-drag boundary per parent group
from make_group_boundaries(), or NULL when
options$group_drag_frame is FALSE.
optionsThe validated options used.
transition_options(), make_group_boundaries(),
layout_metrics(), inherit_layout() for carrying drag offsets from
parent to child groupings.
rect <- function(x0, x1, y0, y1) { sf::st_polygon(list(cbind(c(x0, x1, x1, x0, x0), c(y0, y0, y1, y1, y0)))) } parents <- sf::st_sf( county = c("A", "B"), geometry = sf::st_sfc(rect(0, 3, 0, 3), rect(4, 7, 0, 3), crs = 3857) ) children <- sf::st_sf( county = c("A", "A", "B", "B"), mun = c("A1", "A2", "B1", "B2"), geometry = sf::st_sfc( rect(-1, 1, 0, 3), rect(2, 4, 0, 3), rect(3, 5, 0, 3), rect(6, 8, 0, 3), crs = 3857 ) ) tr <- build_elastic_transition( children, parents, parent_col = "county", options = transition_options(n_frames = 5) ) names(tr) head(tr$anchored[, c("county", "mun", "anchor_x", "final_x")]) tr$boundariesrect <- function(x0, x1, y0, y1) { sf::st_polygon(list(cbind(c(x0, x1, x1, x0, x0), c(y0, y0, y1, y1, y0)))) } parents <- sf::st_sf( county = c("A", "B"), geometry = sf::st_sfc(rect(0, 3, 0, 3), rect(4, 7, 0, 3), crs = 3857) ) children <- sf::st_sf( county = c("A", "A", "B", "B"), mun = c("A1", "A2", "B1", "B2"), geometry = sf::st_sfc( rect(-1, 1, 0, 3), rect(2, 4, 0, 3), rect(3, 5, 0, 3), rect(6, 8, 0, 3), crs = 3857 ) ) tr <- build_elastic_transition( children, parents, parent_col = "county", options = transition_options(n_frames = 5) ) names(tr) head(tr$anchored[, c("county", "mun", "anchor_x", "final_x")]) tr$boundaries
Captures the current drag offsets for a given grouping and returns a named
list. Snapshots can be passed to inherit_layout() when switching to a
finer grouping, or stored and later recovered with
restore_layout_snapshot().
create_layout_snapshot(x, group, offsets = NULL)create_layout_snapshot(x, group, offsets = NULL)
x |
A data frame or |
group |
Column name (scalar character) defining the current grouping. |
offsets |
A data frame with |
A named list with elements group (character), offsets (data
frame or NULL), and timestamp (POSIXct).
restore_layout_snapshot(), inherit_layout().
poly <- sf::st_sf( county = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) offsets <- data.frame(region = c("A", "B"), dx_m = c(10000, -10000), dy_m = 0) snap <- create_layout_snapshot(poly, group = "county", offsets = offsets) snap$group snap$offsetspoly <- sf::st_sf( county = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) offsets <- data.frame(region = c("A", "B"), dx_m = c(10000, -10000), dy_m = 0) snap <- create_layout_snapshot(poly, group = "county", offsets = offsets) snap$group snap$offsets
Write a draggable plot prototype HTML file
drag_map_prototype( x, region_col, label_col = region_col, labels = TRUE, draggable_labels = TRUE, label_marker = TRUE, label_marker_shape = c("rect", "circle", "none"), label_radius = 12, label_text_size = 11, label_width = 64, label_height = 30, label_box_width = 150, label_box_height = 72, connector_color = "#334155", connector_linewidth = 1.3, region_offsets = NULL, label_offsets = NULL, region_palette = NULL, show_legend = FALSE, max_legend_keys = 25L, legend_position = c("bottom", "top", "left", "right", "none"), legend_title = "Region", legend_values = NULL, label_values = NULL, map_background = c("white", "transparent", "light_grid", "dark"), connector_linetype = c("solid", "dashed", "dotted"), connector_endpoint = c("none", "arrow"), connector_smart = FALSE, show_origin_outlines = FALSE, show_movement_connectors = FALSE, show_movement_band = FALSE, movement_connector_color = "#64748b", movement_connector_opacity = 0.72, movement_connector_linewidth = 1.4, movement_connector_linetype = c("solid", "dashed", "dotted"), movement_connector_endpoint = c("closed", "open", "none"), show_drag_trail = FALSE, side_panel = TRUE, transition = NULL, file = NULL, open = FALSE )drag_map_prototype( x, region_col, label_col = region_col, labels = TRUE, draggable_labels = TRUE, label_marker = TRUE, label_marker_shape = c("rect", "circle", "none"), label_radius = 12, label_text_size = 11, label_width = 64, label_height = 30, label_box_width = 150, label_box_height = 72, connector_color = "#334155", connector_linewidth = 1.3, region_offsets = NULL, label_offsets = NULL, region_palette = NULL, show_legend = FALSE, max_legend_keys = 25L, legend_position = c("bottom", "top", "left", "right", "none"), legend_title = "Region", legend_values = NULL, label_values = NULL, map_background = c("white", "transparent", "light_grid", "dark"), connector_linetype = c("solid", "dashed", "dotted"), connector_endpoint = c("none", "arrow"), connector_smart = FALSE, show_origin_outlines = FALSE, show_movement_connectors = FALSE, show_movement_band = FALSE, movement_connector_color = "#64748b", movement_connector_opacity = 0.72, movement_connector_linewidth = 1.4, movement_connector_linetype = c("solid", "dashed", "dotted"), movement_connector_endpoint = c("closed", "open", "none"), show_drag_trail = FALSE, side_panel = TRUE, transition = NULL, file = NULL, open = FALSE )
x |
An |
region_col |
Column defining draggable groups. |
label_col |
Column used for default region-label text. Defaults to
|
labels |
Show draggable labels. Use |
draggable_labels |
Allow labels to be dragged independently of regions. |
label_marker |
Draw a marker behind ordinary text labels. Set to
|
label_marker_shape |
Marker shape for ordinary draggable text labels:
|
label_radius |
Retained for compatibility with earlier circle markers.
Used when |
label_text_size |
Label text size in screen pixels. |
label_width, label_height
|
Default browser dimensions for ordinary draggable text-label markers. |
label_box_width, label_box_height
|
Default browser dimensions for draggable annotation boxes. |
connector_color |
Browser label-connector color. |
connector_linewidth |
Browser connector line width in pixels. |
region_offsets |
Optional data frame with |
label_offsets |
Optional data frame with |
region_palette |
Optional named character vector mapping region values
to hex color strings (e.g. |
show_legend |
Show a compact region legend inside the browser helper. |
max_legend_keys |
Maximum number of legend keys to show in the browser
helper before suppressing the legend. Set to |
legend_position |
Browser-helper legend position. One of |
legend_title |
Title shown above the browser-helper legend. |
legend_values |
Optional character vector of region values to include
in the browser-helper legend. |
label_values |
Optional character vector of label IDs to display.
|
map_background |
Browser helper background. One of |
connector_linetype |
Browser helper connector line style. One of
|
connector_endpoint |
Browser helper connector endpoint. One of
|
connector_smart |
Choose connector geometry dynamically in the browser
based on label displacement. When |
show_origin_outlines |
Show the original, unshifted outlines of regions with non-zero offsets beneath the moved regions. |
show_movement_connectors |
Draw a connector from each moved region's
original representative point to its current location. Hidden for zero-
offset regions. Defaults to |
show_movement_band |
Draw a swept shadow in the browser between each
region's original polygon footprint and its translated position. The shadow
traces the actual boundary of the shape rather than a flat bounding-box
band. Defaults to |
movement_connector_color, movement_connector_opacity, movement_connector_linewidth
|
Browser styling for movement connectors and the swept movement shadow. |
movement_connector_linetype |
Movement connector line style. One of
|
movement_connector_endpoint |
Movement connector endpoint. One of
|
show_drag_trail |
Show a short fading trail of outline snapshots while
a region is actively being dragged. The trail is cleared immediately when
dragging ends and does not appear in static exports or project metadata.
Defaults to |
side_panel |
Show the built-in copy/download side panel in the helper
HTML. Defaults to |
transition |
Optional local elastic transition played on first render,
typically built from |
file |
Output HTML path. When |
open |
Open the written file in the default browser via
|
Invisibly returns file.
render_dragged_map() for the optional static ggplot2 render after
dragging; make_region_labels() and as_drag_annotations() to build
custom label tables; prepare_dragmapr_sf() to project uploaded geometry.
poly <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) # Primary usage: open the interactive draggable plot in the browser. # Drag regions and labels, then copy or download the offset CSVs. if(interactive()){ drag_map_prototype(poly, region_col = "region", open = TRUE) } # Write to a specific path without opening (e.g. for Shiny or CI). drag_map_prototype(poly, region_col = "region", file = tempfile(fileext = ".html"))poly <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) # Primary usage: open the interactive draggable plot in the browser. # Drag regions and labels, then copy or download the offset CSVs. if(interactive()){ drag_map_prototype(poly, region_col = "region", open = TRUE) } # Write to a specific path without opening (e.g. for Shiny or CI). drag_map_prototype(poly, region_col = "region", file = tempfile(fileext = ".html"))
Launches a compact Shiny gadget that lets you pick a projected sf object
from an environment, choose the region and label columns, adjust label,
connector, legend, label-filter, movement-context, colour, and static-output
settings, and interact with the D3 drag-map prototype inside the IDE viewer
pane. When you click Done, the current region and label offsets are
assigned as region_offsets and label_offsets in the same environment,
ready to pass to render_dragged_map().
dragmapr_addin(env = dragmapr_global_env())dragmapr_addin(env = dragmapr_global_env())
env |
Environment to scan for |
The addin appears under Addins > Launch dragmapr in RStudio once the package is installed.
Invisibly returns a list with elements region_offsets,
label_offsets, and static_options. The offset data frames are also
assigned into env as region_offsets and label_offsets; static render
settings are assigned as dragmapr_static_options.
drag_map_prototype() for the underlying HTML generator;
render_dragged_map() to reconstruct a static ggplot2 image from the
returned offsets.
Inspects an sf object and reports geometry type, coordinate reference
system, feature count, candidate grouping columns (including empty-value
counts), detected parent-to-child column hierarchies (including cases where
child names repeat across parents), and invalid geometry counts. The output
guides column selection in drag_map_prototype() and helps diagnose
unexpected behaviour when uploading custom spatial files to Spatial Studio.
dragmapr_diagnostics(x, region_col = NULL, quiet = FALSE)dragmapr_diagnostics(x, region_col = NULL, quiet = FALSE)
x |
An |
region_col |
Optional column name. When supplied, hierarchy details are reported relative to that column and it is highlighted in the summary. |
quiet |
Logical. When |
An invisible named list with components:
geometry_typeCharacter vector of unique geometry type names.
crsCRS identifier string (e.g. "EPSG:3857" or
"Unknown CRS").
is_longlatLogical — TRUE when the CRS is geographic.
n_featuresInteger row count.
candidate_colsCharacter vector of candidate grouping columns.
column_detailsNamed list with n_unique and n_empty per
candidate column.
n_invalid_geometriesNumber of features with invalid geometry.
hierarchy_pairsList of detected parent-to-child column pairs,
each with parent, child, n_parent, n_child, and
child_repeats_across_parents.
recommended_pathSuggested grouping path string, or NULL.
poly <- sf::st_sf( county = c("Essex", "Essex", "Morris", "Morris"), mun = c("Fairfield", "Caldwell", "Fairfield", "Roxbury"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), sf::st_polygon(list(rbind(c(1e5,1e5),c(2e5,1e5),c(2e5,2e5),c(1e5,2e5),c(1e5,1e5)))), sf::st_polygon(list(rbind(c(1e5,0),c(2e5,0),c(2e5,1e5),c(1e5,1e5),c(1e5,0)))), crs = 3857 ) ) diag <- dragmapr_diagnostics(poly)poly <- sf::st_sf( county = c("Essex", "Essex", "Morris", "Morris"), mun = c("Fairfield", "Caldwell", "Fairfield", "Roxbury"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), sf::st_polygon(list(rbind(c(1e5,1e5),c(2e5,1e5),c(2e5,2e5),c(1e5,2e5),c(1e5,1e5)))), sf::st_polygon(list(rbind(c(1e5,0),c(2e5,0),c(2e5,1e5),c(1e5,1e5),c(1e5,0)))), crs = 3857 ) ) diag <- dragmapr_diagnostics(poly)
Returns the JavaScript needed to pass region and label offset state from the
draggable helper iframe back into Shiny inputs via postMessage, and to
poll the iframe until state arrives. The string is suitable for wrapping
in tags$head(tags$script(HTML(...))).
dragmapr_iframe_bridge( region_input = "region_csv", label_input = "label_csv", slow_poll_ms = 2000L, fast_poll_ms = 500L, allowed_origin = "same-origin", iframe_selector = "iframe" )dragmapr_iframe_bridge( region_input = "region_csv", label_input = "label_csv", slow_poll_ms = 2000L, fast_poll_ms = 500L, allowed_origin = "same-origin", iframe_selector = "iframe" )
region_input |
Name of the Shiny input that receives the region-offset
CSV text. Defaults to |
label_input |
Name of the Shiny input that receives the label-offset
CSV text. Defaults to |
slow_poll_ms |
Polling interval in milliseconds once initial state has
been received. Defaults to |
fast_poll_ms |
Polling interval in milliseconds before initial state
arrives. Defaults to |
allowed_origin |
Origin allowed to send drag state messages. Use
|
iframe_selector |
CSS selector used to find the drag-map helper iframe
in the parent document. Defaults to |
A character string of JavaScript ready for
tags$head(tags$script(HTML(dragmapr_iframe_bridge()))).
# In a Shiny UI: if(interactive()){ library(shiny) ui <- fluidPage( tags$head(tags$script(HTML( dragmapr_iframe_bridge(iframe_selector = "#my-helper-frame") ))), uiOutput("helper") # render tags$iframe(id = "my-helper-frame", ...) ) }# In a Shiny UI: if(interactive()){ library(shiny) ui <- fluidPage( tags$head(tags$script(HTML( dragmapr_iframe_bridge(iframe_selector = "#my-helper-frame") ))), uiOutput("helper") # render tags$iframe(id = "my-helper-frame", ...) ) }
This copies the HHS region membership, names, colors, and published display offsets used by the explodemap paper workflow into a lightweight fixture that does not depend on the explodemap package or its generated paper outputs. See the explodemap vignette "Reproducing the paper examples", section 6: https://CRAN.R-project.org/package=explodemap.
example_hhs_layout()example_hhs_layout()
A list with states, labels, region_offsets, label_offsets,
region_names, and region_colors.
hhs <- example_hhs_layout() names(hhs)hhs <- example_hhs_layout() names(hhs)
This creates simple projected rectangles that behave like plot panels, dashboard tiles, or diagram cards. It is useful for checking that dragmapr's offset workflow is not tied to administrative map boundaries.
example_panel_layout()example_panel_layout()
A list with panels, labels, region_offsets, label_offsets,
region_names, and region_colors.
panels <- example_panel_layout() names(panels)panels <- example_panel_layout() names(panels)
When switching from a parent grouping (e.g., county) to a child grouping
(e.g., municipality), inherit_layout() maps the parent's drag offsets to
every child region that belongs to each parent. Each child inherits the mean
offset of the parent group it belongs to.
inherit_layout(x, from, to, parent_offsets)inherit_layout(x, from, to, parent_offsets)
x |
An |
from |
A character vector of one or more column names defining the
coarser (parent) grouping. The |
to |
A character vector of one or more column names defining the finer
(child) grouping. The |
parent_offsets |
A data frame with |
When child names repeat across parents (e.g., "Fairfield" exists in both
Essex and Morris counties), pass both columns in to so that composite keys
are used: to = c("county", "mun"). The resulting region values will be
composite strings like "county=Essex | mun=Fairfield", which can be passed
directly to drag_map_prototype() or render_dragged_map() via
make_hierarchy_key().
A data frame with region, dx_m, and dy_m columns. Rows whose
parent has no offset entry receive zero movement.
make_hierarchy_key() for composite key construction,
create_layout_snapshot() for capturing and restoring layouts.
poly <- sf::st_sf( county = c("Essex", "Essex", "Morris", "Morris"), mun = c("Fairfield", "Caldwell", "Fairfield", "Roxbury"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), sf::st_polygon(list(rbind(c(1e5,1e5),c(2e5,1e5),c(2e5,2e5),c(1e5,2e5),c(1e5,1e5)))), sf::st_polygon(list(rbind(c(1e5,0),c(2e5,0),c(2e5,1e5),c(1e5,1e5),c(1e5,0)))), crs = 3857 ) ) county_offsets <- data.frame( region = c("Essex", "Morris"), dx_m = c(50000, -50000), dy_m = c(0, 0) ) # "Fairfield" repeats, so use composite to= key mun_offsets <- inherit_layout( poly, from = "county", to = c("county", "mun"), parent_offsets = county_offsets ) mun_offsetspoly <- sf::st_sf( county = c("Essex", "Essex", "Morris", "Morris"), mun = c("Fairfield", "Caldwell", "Fairfield", "Roxbury"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), sf::st_polygon(list(rbind(c(1e5,1e5),c(2e5,1e5),c(2e5,2e5),c(1e5,2e5),c(1e5,1e5)))), sf::st_polygon(list(rbind(c(1e5,0),c(2e5,0),c(2e5,1e5),c(1e5,1e5),c(1e5,0)))), crs = 3857 ) ) county_offsets <- data.frame( region = c("Essex", "Morris"), dx_m = c(50000, -50000), dy_m = c(0, 0) ) # "Fairfield" repeats, so use composite to= key mun_offsets <- inherit_layout( poly, from = "county", to = c("county", "mun"), parent_offsets = county_offsets ) mun_offsets
Compares region centroids before and after a transition and reports how far
regions drifted. Use it to confirm that expanding one branch left the rest
of the map stable: pass the non-expanded (sibling) regions as before and
after. Lower drift means the user's mental map survived.
layout_metrics(before, after, id_col)layout_metrics(before, after, id_col)
before |
An |
after |
An |
id_col |
Column present in both objects identifying each region. |
A named list with mean_drift and max_drift (map units),
stability (0-100; 100 means no drift, 0 means mean drift of one third
of the before bounding-box diagonal or more), and n_matched (regions
compared). Regions missing from after are dropped with a warning.
rect <- function(x0, x1, y0, y1) { sf::st_polygon(list(cbind(c(x0, x1, x1, x0, x0), c(y0, y0, y1, y1, y0)))) } before <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc(rect(0, 1, 0, 1), rect(2, 3, 0, 1), crs = 3857) ) after <- before sf::st_geometry(after)[2] <- sf::st_geometry(after)[[2]] + c(0.5, 0) layout_metrics(before, after, id_col = "region")rect <- function(x0, x1, y0, y1) { sf::st_polygon(list(cbind(c(x0, x1, x1, x0, x0), c(y0, y0, y1, y1, y0)))) } before <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc(rect(0, 1, 0, 1), rect(2, 3, 0, 1), crs = 3857) ) after <- before sf::st_geometry(after)[2] <- sf::st_geometry(after)[[2]] + c(0.5, 0) layout_metrics(before, after, id_col = "region")
Computes one padded rectangular boundary per group. The boundary is returned as real geometry with the group's id so it can be drawn inside the same container as the children and therefore moves with the group when dragged. In Spatial Studio this boundary is a drag handle, not a collapse control.
make_group_boundaries(sf_obj, group_col, padding = NULL)make_group_boundaries(sf_obj, group_col, padding = NULL)
sf_obj |
An |
group_col |
Column in |
padding |
Single positive number in map units, or |
An sf object with one row per group and columns group_id,
xmin, xmax, ymin, ymax (padded bounds), plus the rectangle
geometry.
build_elastic_transition(), which calls this automatically when
group_drag_frame = TRUE.
rect <- function(x0, x1, y0, y1) { sf::st_polygon(list(cbind(c(x0, x1, x1, x0, x0), c(y0, y0, y1, y1, y0)))) } children <- sf::st_sf( county = c("A", "A", "B"), geometry = sf::st_sfc( rect(0, 1, 0, 1), rect(2, 3, 0, 1), rect(5, 6, 0, 1), crs = 3857 ) ) make_group_boundaries(children, group_col = "county")rect <- function(x0, x1, y0, y1) { sf::st_polygon(list(cbind(c(x0, x1, x1, x0, x0), c(y0, y0, y1, y1, y0)))) } children <- sf::st_sf( county = c("A", "A", "B"), geometry = sf::st_sfc( rect(0, 1, 0, 1), rect(2, 3, 0, 1), rect(5, 6, 0, 1), crs = 3857 ) ) make_group_boundaries(children, group_col = "county")
Creates a character vector of composite group identifiers by combining values
from two or more columns of a data frame or sf object. The result is
suitable as the region column of an offset data frame, and is the key
building block for parent-to-child layout inheritance in hierarchical spatial
datasets where child names repeat across parents.
make_hierarchy_key(x, cols)make_hierarchy_key(x, cols)
x |
A data frame or |
cols |
A character vector of column names to combine into a composite
key. At least one column is required. Columns must exist in |
When length(cols) == 1, the values of that column are returned directly
(after whitespace trimming and NA replacement). When length(cols) > 1,
values are joined as "col1=val1 | col2=val2 | ...".
A character vector of length nrow(x).
inherit_layout() to propagate parent offsets to child groups,
create_layout_snapshot() to capture a layout for later restoration.
df <- data.frame( county = c("Essex", "Essex", "Morris"), mun = c("Fairfield", "Caldwell", "Fairfield") ) # Single column: values returned as-is make_hierarchy_key(df, "county") # Two columns: composite key disambiguates repeated child names make_hierarchy_key(df, c("county", "mun"))df <- data.frame( county = c("Essex", "Essex", "Morris"), mun = c("Fairfield", "Caldwell", "Fairfield") ) # Single column: values returned as-is make_hierarchy_key(df, "county") # Two columns: composite key disambiguates repeated child names make_hierarchy_key(df, c("county", "mun"))
make_labels() is deprecated. Use make_region_labels() instead.
make_labels( x, region_col, label_col = region_col, point = c("point_on_surface", "centroid") )make_labels( x, region_col, label_col = region_col, point = c("point_on_surface", "centroid") )
x |
An |
region_col |
Column defining draggable groups. |
label_col |
Column used for label text. Defaults to |
point |
One of |
A drag label table.
Derive one default label per draggable region
make_region_labels( x, region_col, label_col = region_col, point = c("point_on_surface", "centroid") )make_region_labels( x, region_col, label_col = region_col, point = c("point_on_surface", "centroid") )
x |
An |
region_col |
Column defining draggable groups. |
label_col |
Column used for label text. Defaults to |
point |
One of |
A drag label table with label_id, region, label, x, and y.
as_drag_labels() for user-supplied labels; as_drag_annotations()
for draggable info boxes; apply_label_state() to restore saved positions;
drag_map_prototype() which accepts the result as its labels argument.
poly <- sf::st_sf( region = c("North", "South"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) make_region_labels(poly, region_col = "region")poly <- sf::st_sf( region = c("North", "South"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) make_region_labels(poly, region_col = "region")
Repairs invalid geometry, filters to polygon types, assigns a fallback CRS
when none is present, and reprojects geographic (longitude/latitude) data to
a projected CRS so metre offsets work correctly. CRS-less inputs trigger a
warning because the fallback is an assumption; pass target_crs explicitly
when your data uses a different projected CRS.
prepare_dragmapr_sf(x, target_crs = 3857)prepare_dragmapr_sf(x, target_crs = 3857)
x |
An |
target_crs |
EPSG code for the projected CRS to use when the input is
geographic. Defaults to |
A projected sf object containing only polygon or multipolygon
features with valid geometry.
read_dragmapr_sf_upload() and read_dragmapr_sf_url() to read
spatial files before passing them to this function; drag_map_prototype()
which requires a projected sf object.
poly <- sf::st_sf( region = "A", geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(-1,0),c(1,0),c(1,1),c(-1,1),c(-1,0)))), crs = 4326 ) ) out <- prepare_dragmapr_sf(poly) sf::st_is_longlat(out) # FALSEpoly <- sf::st_sf( region = "A", geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(-1,0),c(1,0),c(1,1),c(-1,1),c(-1,0)))), crs = 4326 ) ) out <- prepare_dragmapr_sf(poly) sf::st_is_longlat(out) # FALSE
Reads a Spatial Studio project ZIP or extracted project directory and
returns its components as a named list. This is the low-level companion to
render_dragmapr_project(): use it when you want to access the raw source
geometry, offsets, labels, or palette programmatically before rendering.
read_dragmapr_project(project)read_dragmapr_project(project)
project |
Path to a |
A named list with elements:
sourceThe source sf object read from source.gpkg.
region_offsetsData frame from drag_region_offsets.csv, or
NULL if not present.
label_offsetsData frame from drag_label_offsets.csv, or
NULL if not present.
labelsLabel table from labels.csv (as returned by
as_drag_labels()), or NULL.
region_paletteNamed character vector of colors from
palette.csv, or NULL.
metadataNamed list parsed from metadata.json.
pathPath to the extracted project directory.
render_dragmapr_project() to render a project bundle directly;
write_dragmapr_project() to create a project bundle from R objects.
if(interactive()){ bundle <- read_dragmapr_project("dragmapr-project.zip") names(bundle) nrow(bundle$source) }if(interactive()){ bundle <- read_dragmapr_project("dragmapr-project.zip") names(bundle) nrow(bundle$source) }
Handles the data frame returned by shiny::fileInput(), including
multi-file uploads of shapefile sidecars (.shp, .dbf, .shx, .prj)
and zipped archives containing any supported format. When upload is
NULL or empty the function returns NULL so callers can fall back to
demo data.
read_dragmapr_sf_upload(upload)read_dragmapr_sf_upload(upload)
upload |
The value of |
An sf object, or NULL if upload is NULL or empty.
# Typical Shiny server usage: if(interactive()){ observeEvent(input$spatial_upload, { x <- read_dragmapr_sf_upload(input$spatial_upload) if (!is.null(x)) { state$source <- x } }) }# Typical Shiny server usage: if(interactive()){ observeEvent(input$spatial_upload, { x <- read_dragmapr_sf_upload(input$spatial_upload) if (!is.null(x)) { state$source <- x } }) }
Downloads a spatial file from url into a temporary directory and reads it
with sf::st_read(). Supported direct formats are .geojson, .json,
and .gpkg. A .zip URL is extracted first and the first supported file
inside is read. For ambiguous extensions the function assumes a zip archive.
read_dragmapr_sf_url(url, timeout = 60)read_dragmapr_sf_url(url, timeout = 60)
url |
A non-empty character string pointing to a downloadable spatial file. |
timeout |
Download timeout in seconds. Defaults to |
An sf object.
if(interactive()){ x <- read_dragmapr_sf_url("https://example.com/regions.geojson") }if(interactive()){ x <- read_dragmapr_sf_url("https://example.com/regions.geojson") }
read_label_offsets() is deprecated. Use read_label_state() instead.
read_label_offsets(path)read_label_offsets(path)
path |
Path to a CSV with |
A normalized label state data frame.
Read draggable label state from CSV
read_label_state(path)read_label_state(path)
path |
Path to a CSV with |
A normalized label state data frame.
path <- tempfile(fileext = ".csv") writeLines(c("label_id,region,dx_m,dy_m", "North,North,500,200"), path) read_label_state(path)path <- tempfile(fileext = ".csv") writeLines(c("label_id,region,dx_m,dy_m", "North,North,500,200"), path) read_label_state(path)
Read region offsets from CSV
read_offsets(path)read_offsets(path)
path |
Path to a CSV with |
A data frame with normalized region, dx_m, and dy_m columns.
path <- tempfile(fileext = ".csv") writeLines(c("region,dx_m,dy_m", "North,1000,-500", "South,0,0"), path) read_offsets(path)path <- tempfile(fileext = ".csv") writeLines(c("region,dx_m,dy_m", "North,1000,-500", "South,0,0"), path) read_offsets(path)
Render an adjusted draggable plot with labels
render_dragged_map( x, region_offsets = NULL, region_col, label_col = region_col, label_offsets = NULL, labels = NULL, label_values = NULL, max_labels = Inf, label_prefer = NULL, region_palette = NULL, region_labels = NULL, show_legend = TRUE, max_legend_keys = 25L, legend_position = c("bottom", "top", "left", "right", "none"), legend_title = "Region", legend_values = NULL, title = NULL, label_size = 3.4, show_label_marker = TRUE, label_marker_shape = c("circle", "rect", "none"), marker_size = 3.2, marker_fill = "white", marker_color = "black", marker_stroke = 0.8, box_label_size = 3, box_fill = "white", box_color = "black", box_wrap = 24, connector_color = "#334155", connector_linewidth = 0.35, connector_linetype = "solid", connector_endpoint = c("none", "arrow"), connector_curvature = 0.18, connector_squiggle_amplitude = 12000, connector_squiggle_waves = 4, connector_end_gap = NULL, show_origin_outlines = FALSE, show_movement_connectors = FALSE, show_movement_band = FALSE, movement_connector_color = "#64748b", movement_connector_opacity = 0.72, movement_connector_linewidth = 0.45, movement_connector_linetype = c("solid", "dashed", "dotted"), movement_connector_endpoint = c("closed", "open", "none"), label_padding = 0.08, map_background = c("white", "transparent", "light_grid", "dark"), file = NULL, width = 8, height = 6, dpi = 300 )render_dragged_map( x, region_offsets = NULL, region_col, label_col = region_col, label_offsets = NULL, labels = NULL, label_values = NULL, max_labels = Inf, label_prefer = NULL, region_palette = NULL, region_labels = NULL, show_legend = TRUE, max_legend_keys = 25L, legend_position = c("bottom", "top", "left", "right", "none"), legend_title = "Region", legend_values = NULL, title = NULL, label_size = 3.4, show_label_marker = TRUE, label_marker_shape = c("circle", "rect", "none"), marker_size = 3.2, marker_fill = "white", marker_color = "black", marker_stroke = 0.8, box_label_size = 3, box_fill = "white", box_color = "black", box_wrap = 24, connector_color = "#334155", connector_linewidth = 0.35, connector_linetype = "solid", connector_endpoint = c("none", "arrow"), connector_curvature = 0.18, connector_squiggle_amplitude = 12000, connector_squiggle_waves = 4, connector_end_gap = NULL, show_origin_outlines = FALSE, show_movement_connectors = FALSE, show_movement_band = FALSE, movement_connector_color = "#64748b", movement_connector_opacity = 0.72, movement_connector_linewidth = 0.45, movement_connector_linetype = c("solid", "dashed", "dotted"), movement_connector_endpoint = c("closed", "open", "none"), label_padding = 0.08, map_background = c("white", "transparent", "light_grid", "dark"), file = NULL, width = 8, height = 6, dpi = 300 )
x |
An |
region_offsets |
Region offsets as a data frame, CSV path, or |
region_col |
Column defining draggable groups. |
label_col |
Column used for default region-label text. Defaults to
|
label_offsets |
Label state as a data frame, CSV path, or |
labels |
Optional label table from |
label_values |
Optional character vector of label IDs to render.
|
max_labels |
Maximum number of label IDs to render when |
label_prefer |
Optional label IDs to prioritize when |
region_palette |
Optional named vector of fill colors keyed by region. |
region_labels |
Optional named vector of legend labels keyed by region. |
show_legend |
Show the region fill legend. When the number of distinct
regions exceeds |
max_legend_keys |
Maximum number of legend keys before the legend is
automatically hidden. Defaults to |
legend_position |
Position of the fill legend in static exports.
One of |
legend_title |
Title shown above the fill legend. Defaults to
|
legend_values |
Optional character vector of region values to include
in the legend. |
title |
Optional plot title. |
label_size |
Text size passed to |
show_label_marker |
Draw markers behind ordinary text labels. Use
|
label_marker_shape |
Marker shape for ordinary text labels in static
exports. One of |
marker_size |
Point size passed to |
marker_fill |
Fill colour of the label marker circle. Defaults to
|
marker_color |
Stroke colour of the label marker circle. Defaults to
|
marker_stroke |
Stroke width of the label marker circle. Defaults to
|
box_label_size |
Text size for annotation boxes. Defaults to |
box_fill, box_color
|
Fill and border colours for annotation boxes. |
box_wrap |
Approximate character width used to wrap annotation-box text. |
connector_color, connector_linewidth, connector_linetype
|
Static export styling for label connector lines. |
connector_endpoint |
Connector endpoint style. One of |
connector_curvature |
Curvature used by |
connector_squiggle_amplitude, connector_squiggle_waves
|
Appearance of
|
connector_end_gap |
Distance, in plot units, to trim connector endpoints away from label centers. Defaults to an automatic value based on plot size. |
show_origin_outlines |
Show the original, unshifted outlines of regions with non-zero offsets beneath the moved regions. |
show_movement_connectors |
Draw a connector from each moved region's original representative point to its translated location. |
show_movement_band |
Draw a swept shadow between each region's original footprint and its translated position. The shadow is built from the actual polygon boundary, so it follows the shape of the region rather than a flat bounding-box band. |
movement_connector_color, movement_connector_opacity, movement_connector_linewidth
|
Static export styling for movement connectors and the swept movement shadow. |
movement_connector_linetype |
Movement connector line style. One of
|
movement_connector_endpoint |
Movement connector endpoint. One of
|
label_padding |
Proportional padding added around displaced labels and connectors to avoid clipping static exports. |
map_background |
Static map background. One of |
file |
Optional output image path. When supplied, |
width, height, dpi
|
Output settings used when |
A ggplot object.
drag_map_prototype() for the interactive draggable browser helper
that produces the offset CSVs; read_offsets() and read_label_state()
to load saved offsets from disk; as_drag_annotations() for info-box labels.
# render_dragged_map() is an optional static-export step. # The primary workflow is drag_map_prototype(open = TRUE): open the # interactive HTML, drag regions and labels to your liking, then # copy or download the offset CSVs. Only call render_dragged_map() # if you also need a reproducible ggplot2 image from those offsets. if(interactive()){ # Step 1 (always): open the interactive draggable plot. drag_map_prototype(poly, region_col = "region", open = TRUE) # Step 2 (optional): after dragging, reconstruct as a static image. region_offsets <- read_offsets("my_region_offsets.csv") render_dragged_map(poly, region_col = "region", region_offsets = region_offsets) } # Minimal runnable example (no prior dragging session needed). poly <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) render_dragged_map(poly, region_col = "region")# render_dragged_map() is an optional static-export step. # The primary workflow is drag_map_prototype(open = TRUE): open the # interactive HTML, drag regions and labels to your liking, then # copy or download the offset CSVs. Only call render_dragged_map() # if you also need a reproducible ggplot2 image from those offsets. if(interactive()){ # Step 1 (always): open the interactive draggable plot. drag_map_prototype(poly, region_col = "region", open = TRUE) # Step 2 (optional): after dragging, reconstruct as a static image. region_offsets <- read_offsets("my_region_offsets.csv") render_dragged_map(poly, region_col = "region", region_offsets = region_offsets) } # Minimal runnable example (no prior dragging session needed). poly <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) render_dragged_map(poly, region_col = "region")
render_dragmapr_project() turns a Spatial Studio project ZIP, or an
extracted project directory, into the same ggplot2 image produced by
render_dragged_map(). It reads the saved source geometry, region offsets,
label offsets, label table, palette, and metadata, then validates that the
pieces still match before rendering.
render_dragmapr_project( project, file = NULL, width = 10, height = 8, dpi = 300, title = NULL, quiet = FALSE, ... )render_dragmapr_project( project, file = NULL, width = 10, height = 8, dpi = 300, title = NULL, quiet = FALSE, ... )
project |
Path to a |
file |
Optional output image path. When supplied, the rendered plot is
saved with |
width, height, dpi
|
Output settings used when |
title |
Optional plot title. Defaults to the title saved in project metadata, when available. |
quiet |
Use |
... |
Additional arguments passed to |
A ggplot object.
if(interactive()){ render_dragmapr_project("dragmapr-project.zip", file = "map.png") }if(interactive()){ render_dragmapr_project("dragmapr-project.zip", file = "map.png") }
Extracts the offset data frame from a snapshot created by
create_layout_snapshot().
restore_layout_snapshot(snapshot)restore_layout_snapshot(snapshot)
snapshot |
A named list as returned by |
A data frame with region, dx_m, and dy_m columns, or NULL
if the snapshot was created with offsets = NULL.
offsets <- data.frame(region = c("A", "B"), dx_m = c(10000, -10000), dy_m = 0) snap <- create_layout_snapshot( data.frame(county = c("A", "B")), group = "county", offsets = offsets ) restore_layout_snapshot(snap)offsets <- data.frame(region = c("A", "B"), dx_m = c(10000, -10000), dy_m = 0) snap <- create_layout_snapshot( data.frame(county = c("A", "B")), group = "county", offsets = offsets ) restore_layout_snapshot(snap)
This helper is useful for interfaces that should keep all label state, but
show only a manageable subset by default. It returns label IDs only; callers
can pass the result to label_values in drag_map_prototype() or
render_dragged_map().
select_label_ids(labels, max_labels = 25, prefer = NULL)select_label_ids(labels, max_labels = 25, prefer = NULL)
labels |
A drag label table accepted by |
max_labels |
Maximum number of label IDs to return. |
prefer |
Optional label IDs to keep first, for example labels from an expanded branch or labels the user has edited. |
A character vector of label IDs.
labels <- as_drag_labels(data.frame( label_id = c("A", "B", "C"), region = c("A", "B", "C"), label = c("A", "B", "C"), x = 1:3, y = 1:3 )) select_label_ids(labels, max_labels = 2)labels <- as_drag_labels(data.frame( label_id = c("A", "B", "C"), region = c("A", "B", "C"), label = c("A", "B", "C"), x = 1:3, y = 1:3 )) select_label_ids(labels, max_labels = 2)
Computes a starting layout for drag_map_prototype() or
render_dragged_map() without manual dragging. The result is a data frame
of offsets that can be refined interactively in the browser.
suggest_offsets( x, region_col, method = c("radial", "horizontal", "vertical", "grid", "none"), scale = 1 )suggest_offsets( x, region_col, method = c("radial", "horizontal", "vertical", "grid", "none"), scale = 1 )
x |
An |
region_col |
Column in |
method |
Layout algorithm. One of |
scale |
Positive numeric multiplier applied to all offsets. Defaults to
|
Available layout methods:
"radial"Each region is pushed outward from the collective centroid in the direction of its own centroid. Regions that are already spread out are pushed further than regions near the centre.
"horizontal"Regions are ranked by centroid x-coordinate and spread evenly along the x-axis. Useful for left-to-right layouts.
"vertical"Regions are ranked by centroid y-coordinate and spread evenly along the y-axis.
"grid"Regions are arranged in a rectangular grid ordered by centroid position (top-to-bottom, left-to-right).
"none"Returns zero offsets for every region. Useful as a placeholder when you want to start from an undisplaced state.
The scale argument multiplies all computed offsets uniformly. Increase it
to spread regions further apart; decrease it for a tighter layout.
A data frame with region, dx_m, and dy_m columns, one row per
unique region value. Suitable for use as region_offsets in
drag_map_prototype() or render_dragged_map().
drag_map_prototype() to open the interactive helper with the
suggested layout as a starting point; apply_offsets() to apply offsets
directly to an sf object.
poly <- sf::st_sf( region = c("A", "B", "C", "D"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), sf::st_polygon(list(rbind(c(1e5,1e5),c(2e5,1e5),c(2e5,2e5),c(1e5,2e5),c(1e5,1e5)))), sf::st_polygon(list(rbind(c(1e5,0),c(2e5,0),c(2e5,1e5),c(1e5,1e5),c(1e5,0)))), crs = 3857 ) ) suggest_offsets(poly, region_col = "region", method = "radial") suggest_offsets(poly, region_col = "region", method = "horizontal") suggest_offsets(poly, region_col = "region", method = "grid")poly <- sf::st_sf( region = c("A", "B", "C", "D"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), sf::st_polygon(list(rbind(c(1e5,1e5),c(2e5,1e5),c(2e5,2e5),c(1e5,2e5),c(1e5,1e5)))), sf::st_polygon(list(rbind(c(1e5,0),c(2e5,0),c(2e5,1e5),c(1e5,1e5),c(1e5,0)))), crs = 3857 ) ) suggest_offsets(poly, region_col = "region", method = "radial") suggest_offsets(poly, region_col = "region", method = "horizontal") suggest_offsets(poly, region_col = "region", method = "grid")
Builds a validated list of animation and behaviour settings for
build_elastic_transition(). Defaults follow the user-tested values from
the dragmapr transition prototype: a 550 ms ease-out-back bloom, a dotted
group-drag boundary around the expanded group, and a stable parent
skeleton.
transition_options( mode = c("local_elastic", "local_insert"), duration_ms = 550, overshoot = 1.70158, max_stretch = 0.35, n_frames = 30, preserve_skeleton = TRUE, global_relayout = FALSE, show_ghost = TRUE, show_trails = FALSE, reset_boundary = TRUE, group_drag_frame = reset_boundary, boundary_behavior = c("drag", "reset", "none"), boundary_drag_threshold = 8, boundary_label = "Drag to", collapse_duration_ms = 260, collapse_visual_freeze_ms = 340, collapse_scale = 0.16, collapse_opacity = 0.04, boundary_padding = 0.025, drag_boundary_with_group = TRUE )transition_options( mode = c("local_elastic", "local_insert"), duration_ms = 550, overshoot = 1.70158, max_stretch = 0.35, n_frames = 30, preserve_skeleton = TRUE, global_relayout = FALSE, show_ghost = TRUE, show_trails = FALSE, reset_boundary = TRUE, group_drag_frame = reset_boundary, boundary_behavior = c("drag", "reset", "none"), boundary_drag_threshold = 8, boundary_label = "Drag to", collapse_duration_ms = 260, collapse_visual_freeze_ms = 340, collapse_scale = 0.16, collapse_opacity = 0.04, boundary_padding = 0.025, drag_boundary_with_group = TRUE )
mode |
Transition style. |
duration_ms |
Single positive number. Total animation duration in
milliseconds. Defaults to |
overshoot |
Single non-negative number controlling the elastic
"snap" of the ease-out-back curve. |
max_stretch |
Single positive number. Upper cap on the per-feature
stretch strength (movement distance relative to the layout diagonal).
Defaults to |
n_frames |
Single integer (>= 2). Number of animation frames produced
for static/ |
preserve_skeleton |
Logical. Keep the parent layout stable while a
branch expands. Must remain |
global_relayout |
Logical. Must be |
show_ghost |
Logical. Render the collapsed parent as a faint ghost
behind its expanded children. Defaults to |
show_trails |
Logical. Render dotted movement trails from the parent
centroid to each child's final position. Defaults to |
reset_boundary |
Logical. Legacy alias for |
group_drag_frame |
Logical. Generate the dotted group-drag boundary
around each expanded group. Defaults to the value of |
boundary_behavior |
What a plain click on the dotted frame does in
the interactive helper: |
boundary_drag_threshold |
Single non-negative number. Pointer
movement (in pixels) below which a frame gesture counts as a click
rather than a drag. Defaults to |
boundary_label |
Single string used as the helper label for the
dotted group frame. Defaults to |
collapse_duration_ms |
Single positive number. Browser-side reversible
leaf-return animation duration in milliseconds. Defaults to |
collapse_visual_freeze_ms |
Single non-negative number. How long the
Studio should defer label and legend refresh messages while collapsing.
Defaults to |
collapse_scale |
Number from |
collapse_opacity |
Number from |
boundary_padding |
Single positive number. Boundary padding as a
fraction of the child layout's bounding-box diagonal. Defaults to
|
drag_boundary_with_group |
Logical. The group-drag boundary is part of the
expanded group and must move with it when dragged; it is never a static
overlay. Defaults to |
The transition model is always stable skeleton + local elastic insert:
the parent layout is preserved and children expand locally from the parent
centroid. global_relayout exists only as an explicit guard rail; setting
it to TRUE is an error because recomputing the whole layout on every
expansion destroys the user's mental map.
A named list of class "dragmapr_transition_options".
build_elastic_transition(), make_group_boundaries().
transition_options() transition_options(duration_ms = 800, overshoot = 0) try(transition_options(global_relayout = TRUE))transition_options() transition_options(duration_ms = 800, overshoot = 0) try(transition_options(global_relayout = TRUE))
Packages a source sf object together with region offsets, label offsets,
labels, a palette, and metadata into a ZIP file that can be reopened in
Spatial Studio or rendered with render_dragmapr_project(). This lets you
create and share reproducible project bundles entirely from R, without
opening the Shiny app.
write_dragmapr_project( x, region_col, file = NULL, region_offsets = NULL, label_offsets = NULL, labels = NULL, region_palette = NULL, label_col = region_col, title = NULL, ... )write_dragmapr_project( x, region_col, file = NULL, region_offsets = NULL, label_offsets = NULL, labels = NULL, region_palette = NULL, label_col = region_col, title = NULL, ... )
x |
An |
region_col |
Column in |
file |
Output path for the ZIP file. Should end in |
region_offsets |
Optional data frame with |
label_offsets |
Optional data frame with |
labels |
Optional label table as returned by |
region_palette |
Optional named character vector of fill colors (names are region values, values are hex strings). |
label_col |
Column used for default label text. Defaults to
|
title |
Optional project title stored in metadata. |
... |
Additional named metadata fields written to |
Invisibly returns file (the path to the written ZIP).
read_dragmapr_project() to read a project back into R;
render_dragmapr_project() to render a project bundle directly.
poly <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) offsets <- data.frame(region = c("A", "B"), dx_m = c(50000, -50000), dy_m = 0) zip_path <- write_dragmapr_project( poly, region_col = "region", region_offsets = offsets, title = "Demo project", file = tempfile(fileext = ".zip") ) file.exists(zip_path)poly <- sf::st_sf( region = c("A", "B"), geometry = sf::st_sfc( sf::st_polygon(list(rbind(c(0,1e5),c(1e5,1e5),c(1e5,2e5),c(0,2e5),c(0,1e5)))), sf::st_polygon(list(rbind(c(0,0),c(1e5,0),c(1e5,1e5),c(0,1e5),c(0,0)))), crs = 3857 ) ) offsets <- data.frame(region = c("A", "B"), dx_m = c(50000, -50000), dy_m = 0) zip_path <- write_dragmapr_project( poly, region_col = "region", region_offsets = offsets, title = "Demo project", file = tempfile(fileext = ".zip") ) file.exists(zip_path)