| 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 hierarchy detection, upload profiling, make_hierarchy_key(), and inherit_layout(), which recommend parent-child groupings and 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 d_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.3.1 |
| Built: | 2026-09-21 05:16:20 UTC |
| Source: | https://github.com/prigasg/dragmapr |
Add or replace spatial features
add_spatial_features(x, features) replace_spatial_features(x, ids, features, key_col = NULL)add_spatial_features(x, features) replace_spatial_features(x, ids, features, key_col = NULL)
x |
An |
features |
An |
ids |
Existing feature ids to replace. Matched like
|
key_col |
Optional stable id column. |
An sf object.
Apply a dragmapr state to sf geometry
apply_dragmapr_state( x, state, region_col = NULL, base_offsets = NULL, ancestor_offsets = NULL )apply_dragmapr_state( x, state, region_col = NULL, base_offsets = NULL, ancestor_offsets = NULL )
x |
An |
state |
A |
region_col |
Column in |
base_offsets |
Optional algorithmic base movement accepted by
|
ancestor_offsets |
Optional inherited movement accepted by
|
An sf object with region offsets applied.
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 an sf object and transition list for parent-to-child leaf-flip
bloom in drag_map_prototype().
build_branch_transition_data( x, parent_col, child_col, expanded = NULL, dissolve = TRUE, max_child_groups = 600L, animation = c("branch_bloom", "leaf_flip"), duration_ms = 375, easing = c("cubic-out", "cubic-in-out", "linear"), show_parent_ghost = FALSE, parent_ghost_opacity = 0.18, leaf_flip_strength = 0.16, leaf_child_scale = 0.86, leaf_expand_duration_factor = 0.82, leaf_collapse_duration_factor = 0.58, boundary = TRUE, boundary_behavior = c("drag", "none"), boundary_drag_threshold = 8, boundary_label = "Drag to", parent_key_col = "..dragmapr_parent_key..", child_key_col = "..dragmapr_child_key..", shell_col = "..dragmapr_parent_shell.." )build_branch_transition_data( x, parent_col, child_col, expanded = NULL, dissolve = TRUE, max_child_groups = 600L, animation = c("branch_bloom", "leaf_flip"), duration_ms = 375, easing = c("cubic-out", "cubic-in-out", "linear"), show_parent_ghost = FALSE, parent_ghost_opacity = 0.18, leaf_flip_strength = 0.16, leaf_child_scale = 0.86, leaf_expand_duration_factor = 0.82, leaf_collapse_duration_factor = 0.58, boundary = TRUE, boundary_behavior = c("drag", "none"), boundary_drag_threshold = 8, boundary_label = "Drag to", parent_key_col = "..dragmapr_parent_key..", child_key_col = "..dragmapr_child_key..", shell_col = "..dragmapr_parent_shell.." )
x |
An |
parent_col |
Parent grouping column. |
child_col |
Child grouping column. |
expanded |
Optional parent values to start expanded. |
dissolve |
Add dissolved parent shell features for collapsed parents. |
max_child_groups |
Maximum number of child groups allowed. |
animation |
Animation style. Use |
duration_ms |
Animation duration in milliseconds. |
easing |
Animation easing name. |
show_parent_ghost |
Logical. Show a faint parent shell while expanded. |
parent_ghost_opacity |
Parent ghost opacity when shown. |
leaf_flip_strength |
Leaf proxy rotation strength. |
leaf_child_scale |
Starting scale for child polygons in leaf mode. |
leaf_expand_duration_factor |
Leaf expand speed multiplier. |
leaf_collapse_duration_factor |
Leaf collapse speed multiplier. |
boundary |
Logical. Add a dotted drag boundary for expanded groups. |
boundary_behavior |
Boundary mode. Use |
boundary_drag_threshold |
Pixel threshold before a boundary drag counts. |
boundary_label |
Text prefix for the dotted drag boundary. |
parent_key_col, child_key_col, shell_col
|
Internal column names to add. |
A list with sf, transition, parent_key_col, child_key_col,
shell_col, and validation.
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
Adds editorial timing semantics to renderer-neutral movement data, including
tables from explodemap::transition_data() and
explodemap::layout_children(). The browser only needs to interpolate the
supplied anchors according to the returned order and timing columns.
build_transition_plan( movement, duration = 650, easing = "elastic", stagger = 12, overshoot = 1.25 )build_transition_plan( movement, duration = 650, easing = "elastic", stagger = 12, overshoot = 1.25 )
movement |
Data frame with |
duration |
Per-feature duration in milliseconds. |
easing |
Easing identifier carried to the renderer. |
stagger |
Delay between successive animation-order values. |
overshoot |
Non-negative overshoot parameter. |
A dragmapr_transition_plan data frame containing the movement
schema plus delay_ms, duration_ms, easing, and overshoot.
Query hierarchy relationships
children_of(relationships, id, level = NULL) parent_of(relationships, id, level = NULL) descendants_of(relationships, id, level = NULL) ancestors_of(relationships, id, level = NULL) hierarchy_path(relationships, id, level = NULL)children_of(relationships, id, level = NULL) parent_of(relationships, id, level = NULL) descendants_of(relationships, id, level = NULL) ancestors_of(relationships, id, level = NULL) hierarchy_path(relationships, id, level = NULL)
relationships |
A |
id |
Stable node identifier. |
level |
Optional node level used to disambiguate repeated identifiers. |
children_of() and parent_of() return normalized edge subsets;
descendants_of() and ancestors_of() return node tables; and
hierarchy_path() returns the root-to-node IDs.
Collapse drag offsets between hierarchy levels
collapse_drag_offsets(state, from, to, relation, method = "centroid")collapse_drag_offsets(state, from, to, relation, method = "centroid")
state |
A |
from, to
|
Column names in |
relation |
Data frame mapping child keys to parent keys. |
method |
Collapse method. Currently |
A dragmapr_state at level to.
Establishes the cross-package composition contract: algorithmic base
movement (for example from explodemap), inherited ancestor movement, and
local manual edits remain separately inspectable while their sum becomes the
effective movement applied to geometry.
compose_offsets(base = NULL, state, ancestor_offsets = NULL, key_col = NULL) effective_offsets( state, base_offsets = NULL, ancestor_offsets = NULL, key_col = NULL )compose_offsets(base = NULL, state, ancestor_offsets = NULL, key_col = NULL) effective_offsets( state, base_offsets = NULL, ancestor_offsets = NULL, key_col = NULL )
base |
Optional base-offset table, an |
state |
A |
ancestor_offsets |
Optional inherited-offset table. Accepted movement
columns are |
key_col |
Optional identifier column used in external offset tables.
Defaults to |
base_offsets |
Alias for |
effective_offsets() is the state-first alias for this composition path.
Every caller that needs effective offsets goes through one of these two
forms, so algorithmic, inherited, and manual layers always combine
identically.
A data frame with region, separate base/inherited/manual columns,
and effective_dx_m/effective_dy_m.
Coerce connector rows to sf lines
connector_sf(connectors, crs = NA)connector_sf(connectors, crs = NA)
connectors |
Data frame returned by |
crs |
Optional CRS. |
An sf line layer.
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
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().
d_addin(env = d_global_env())d_addin(env = d_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.
d_diagnostics(x, region_col = NULL, quiet = FALSE)d_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 <- d_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 <- d_diagnostics(poly)
A friendly front-door to the native draggable editor and the composition step
of the state-first workflow: compute a layout, edit it, render the edited
state. It accepts the objects produced upstream – a projected sf, an
explodemap grouped_exploded_map, or a dragmapr_layout – together with an
optional d_state(), and returns a configured d_widget()
ready to embed in Shiny, R Markdown, or the viewer.
d_edit(x, region_col = NULL, state = NULL, ...)d_edit(x, region_col = NULL, state = NULL, ...)
x |
A projected |
region_col |
Column defining draggable groups. Required when |
state |
Optional |
... |
Further arguments passed to |
For an explodemap layout, pass the composed state explicitly so the editor opens on the exploded composition rather than the bare geometry:
layout <- explodemap::explode_grouped(x, region_col = "region") state <- explodemap::as_dragmapr_state(layout) d_edit(layout, state = state)
To capture edits back into a dragmapr_state (to persist, merge, or
re-render them), read the widget's state input in Shiny with
d_widget_state():
output$map <- renderDragmapr(d_edit(layout, state = state))
observeEvent(input$map_state, {
state <- d_widget_state(input$map_state)
})
A dragmapr htmlwidget (the interactive editor).
These constructors separate options that affect source geometry from options that can be updated live in the browser.
d_geometry_options(width = 7200, height = 4800) d_display_options( region_palette = NULL, show_origin_outlines = FALSE, show_movement_connectors = FALSE, show_drag_trail = FALSE, map_background = c("white", "transparent", "light_grid", "dark"), connector_color = "#334155", connector_linewidth = 1.3 ) d_interaction_options( draggable_regions = TRUE, draggable_labels = TRUE, state_emit = c("end", "throttled", "continuous"), live_drag = TRUE, throttle_ms = 75 )d_geometry_options(width = 7200, height = 4800) d_display_options( region_palette = NULL, show_origin_outlines = FALSE, show_movement_connectors = FALSE, show_drag_trail = FALSE, map_background = c("white", "transparent", "light_grid", "dark"), connector_color = "#334155", connector_linewidth = 1.3 ) d_interaction_options( draggable_regions = TRUE, draggable_labels = TRUE, state_emit = c("end", "throttled", "continuous"), live_drag = TRUE, throttle_ms = 75 )
width, height
|
Widget canvas dimensions in CSS pixels. |
region_palette |
Optional named color vector. |
show_origin_outlines, show_movement_connectors, show_drag_trail
|
Logical display toggles. |
map_background |
One of |
connector_color |
Browser label-connector color. |
connector_linewidth |
Browser label-connector width. |
draggable_regions, draggable_labels
|
Enable region and label dragging. |
state_emit |
Browser-to-Shiny drag emission policy. |
live_drag |
Update geometry locally during pointer movement. |
throttle_ms |
Minimum milliseconds between compact live drag events. |
A named list of options.
A hierarchy state keeps one parent/root dragmapr_state together with any
child-level states created while drilling into the map. It is useful for apps
that move between levels such as divisions, states, counties, or
municipalities without losing each level's edits.
d_hierarchy_state( root = d_state(), children = list(), active_path = character(), relationships = NULL, version = 0L ) validate_dragmapr_hierarchy_state(hierarchy)d_hierarchy_state( root = d_state(), children = list(), active_path = character(), relationships = NULL, version = 0L ) validate_dragmapr_hierarchy_state(hierarchy)
root |
A root |
children |
Named list of child |
active_path |
Character vector describing the active path through the hierarchy. |
relationships |
Optional normalized table from
|
version |
Integer hierarchy revision. |
hierarchy |
A |
An object of class "dragmapr_hierarchy_state".
d_history() creates an undo/redo stack for dragmapr_state objects. Push
a checkpoint with d_history_push() after each meaningful edit, then step
backwards with d_undo() and forwards with d_redo(). Pushing a new
checkpoint clears the redo stack, matching familiar editor behaviour.
d_history() d_history_push(history, state) d_undo(history) d_redo(history)d_history() d_history_push(history, state) d_undo(history) d_redo(history)
history |
A |
state |
A |
The history object has reference semantics: d_history_push(), d_undo(),
and d_redo() modify it in place, so reassignment is optional.
d_history() returns a dragmapr_history object;
d_history_push() returns the history invisibly; d_undo() and
d_redo() return the restored dragmapr_state.
h <- d_history() s0 <- d_state( region_offsets = data.frame(region = "A", dx_m = 0, dy_m = 0) ) d_history_push(h, s0) s1 <- d_nudge(s0, "A", dx_m = 50) d_history_push(h, s1) back <- d_undo(h) # s0 offsets again fwd <- d_redo(h) # s1 offsets again d_state_equal(back, s0) d_state_equal(fwd, s1)h <- d_history() s0 <- d_state( region_offsets = data.frame(region = "A", dx_m = 0, dy_m = 0) ) d_history_push(h, s0) s1 <- d_nudge(s0, "A", dx_m = 50) d_history_push(h, s1) back <- d_undo(h) # s0 offsets again fwd <- d_redo(h) # s1 offsets again d_state_equal(back, s0) d_state_equal(fwd, s1)
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(...))).
d_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" )d_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(d_iframe_bridge()))).
# In a Shiny UI: if(interactive()){ library(shiny) ui <- fluidPage( tags$head(tags$script(HTML( d_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( d_iframe_bridge(iframe_selector = "#my-helper-frame") ))), uiOutput("helper") # render tags$iframe(id = "my-helper-frame", ...) ) }
Adds a small increment to the current offset of one region or label in a
d_state(). This is the scripted equivalent of dragging slightly in the
browser: existing movement is preserved and the delta is added on top.
Unknown ids gain a new row, matching update_region_offset().
d_nudge(state, id, dx_m = 0, dy_m = 0, target = c("region", "label"))d_nudge(state, id, dx_m = 0, dy_m = 0, target = c("region", "label"))
state |
A |
id |
Region id (when |
dx_m, dy_m
|
Distances in metres added to the current offset. Each must be a single finite number. |
target |
One of |
An updated dragmapr_state with a bumped version.
state <- d_state( region_offsets = data.frame(region = "A", dx_m = 10, dy_m = 0) ) state <- d_nudge(state, "A", dx_m = 5) state$region_offsetsstate <- d_state( region_offsets = data.frame(region = "A", dx_m = 10, dy_m = 0) ) state <- d_nudge(state, "A", dx_m = 5) state$region_offsets
Normalizes application vocabulary into a package-neutral edge table. The package understands levels and stable identifiers; terms such as county, parish, municipality, or district remain data values rather than hard-coded assumptions.
d_relationships( data = NULL, parent_level = NULL, parent_id = NULL, child_level = NULL, child_id = NULL )d_relationships( data = NULL, parent_level = NULL, parent_id = NULL, child_level = NULL, child_id = NULL )
data |
Data frame containing parent and child identifiers. Pass |
parent_level, child_level
|
Single level labels. |
parent_id, child_id
|
Column names in |
A dragmapr_relationships data frame with parent_level,
parent_id, child_level, and child_id.
These pure helpers make hierarchy state operational without imposing UI behavior. Paths are character vectors of branch IDs. Child states may be keyed by the full slash-separated path or, for backward compatibility, by the final path component.
d_set_active_path(hierarchy, path = character()) d_active_state(hierarchy, path = hierarchy$active_path, missing = NULL) d_parent_state(hierarchy, path = hierarchy$active_path, missing = NULL) d_branch_offsets(hierarchy, path = hierarchy$active_path) d_effective_offsets( hierarchy, path = hierarchy$active_path, base_offsets = NULL ) d_move_branch(hierarchy, path = hierarchy$active_path, dx_m = 0, dy_m = 0)d_set_active_path(hierarchy, path = character()) d_active_state(hierarchy, path = hierarchy$active_path, missing = NULL) d_parent_state(hierarchy, path = hierarchy$active_path, missing = NULL) d_branch_offsets(hierarchy, path = hierarchy$active_path) d_effective_offsets( hierarchy, path = hierarchy$active_path, base_offsets = NULL ) d_move_branch(hierarchy, path = hierarchy$active_path, dx_m = 0, dy_m = 0)
hierarchy |
|
path |
Character branch path. Defaults to the hierarchy's active path where applicable. |
missing |
Value returned when no matching state exists. |
base_offsets |
Optional algorithmic base offsets for the active state. |
dx_m, dy_m
|
Incremental branch movement in projected map units. |
Updated hierarchy states, active/parent states, or composed offset tables as described by each function.
Manage child states in a dragmapr hierarchy
d_set_child_state(hierarchy, key, state) d_child_state(hierarchy, key, missing = NULL) d_remove_child_state(hierarchy, key)d_set_child_state(hierarchy, key, state) d_child_state(hierarchy, key, missing = NULL) d_remove_child_state(hierarchy, key)
hierarchy |
A |
key |
Single child key. |
state |
A child |
missing |
Value returned when a child key is absent. |
A hierarchy state for setters/removers, or a dragmapr_state for
d_child_state().
Rounds every region and label offset in a d_state() to the nearest
multiple of grid, tidying hand-dragged layouts into even increments.
d_snap_offsets(state, grid = 1000)d_snap_offsets(state, grid = 1000)
state |
A |
grid |
Single positive number in metres. Offsets snap to the nearest
multiple of |
An updated dragmapr_state with a bumped version.
state <- d_state( region_offsets = data.frame(region = "A", dx_m = 1234, dy_m = -567) ) state <- d_snap_offsets(state, grid = 1000) state$region_offsetsstate <- d_state( region_offsets = data.frame(region = "A", dx_m = 1234, dy_m = -567) ) state <- d_snap_offsets(state, grid = 1000) state$region_offsets
A dragmapr_state stores the mutable, editorial layout of a draggable map
separately from the source geometry and from display options. It is the
shared composition contract handed between layout producers (such as
explodemap::as_dragmapr_state()), the interactive editor, and static
renderers.
d_state( level = "region", region_col = NULL, label_id_col = NULL, region_offsets = NULL, label_offsets = NULL, expanded_groups = character(), view = NULL, version = 0L, crs = NULL, geometry_id = NULL, selected_feature = NULL, styles = NULL, binding = NULL, schema_version = "1.2.0", package_version = as.character(utils::packageVersion("dragmapr")) )d_state( level = "region", region_col = NULL, label_id_col = NULL, region_offsets = NULL, label_offsets = NULL, expanded_groups = character(), view = NULL, version = 0L, crs = NULL, geometry_id = NULL, selected_feature = NULL, styles = NULL, binding = NULL, schema_version = "1.2.0", package_version = as.character(utils::packageVersion("dragmapr")) )
level |
Character label for the active geography level. |
region_col |
Source-geometry column used to join |
label_id_col |
Source or label-table column identifying draggable labels. |
region_offsets |
Data frame with |
label_offsets |
Data frame with |
expanded_groups |
Character vector of expanded parent groups. |
view |
Optional list describing the client view, such as scale and translation. |
version |
Integer state revision. |
crs |
Optional coordinate reference system the metre offsets are
expressed in. Accepts anything |
geometry_id |
Optional single string identifying the geometry this state was composed against (provenance / binding tag). Lets a downstream consumer detect when a state is being applied to a different dataset than it was authored for. |
selected_feature |
Optional single string naming the feature currently selected in a dashboard or editor. Carried so a composition can be restored with focus intact. |
styles |
Optional keyed feature-style table created by
|
binding |
Optional list of binding metadata. When supplied,
|
schema_version |
State schema version. Stored with JSON snapshots so
future migrations can read older projects. Must use whole-number
|
package_version |
Package version that created the state. |
The state is deliberately geometry-free: it carries deltas, not absolute
geometry, and is bound to features at apply time via a join key. That key is
recorded in region_col, while level remains the human geography level
label. For durable round-trips prefer a stable code (e.g. a FIPS/ISO id)
over a display name, and record which geometry the state was composed
against with geometry_id.
An object of class "dragmapr_state".
d_state_diff() reports composition and optional interaction changes
between two states. d_state_equal() is the corresponding predicate.
d_state_diff( draft, canonical, tolerance = 1, compare = c("composition", "interaction", "all") ) d_state_equal( a, b, tolerance = 1, compare = c("composition", "interaction", "all") )d_state_diff( draft, canonical, tolerance = 1, compare = c("composition", "interaction", "all") ) d_state_equal( a, b, tolerance = 1, compare = c("composition", "interaction", "all") )
draft, canonical, a, b
|
|
tolerance |
Numeric tolerance for offset changes. |
compare |
One of |
d_state_diff() returns a dragmapr_state_diff object.
d_state_equal() returns TRUE or FALSE.
Normalizes lightweight, already-classified visual overrides so interactive widgets, static renders, state JSON, and project bundles can preserve the same editorial styling. Data classification and palette selection remain application responsibilities.
d_styles(data = NULL, id_col = "region")d_styles(data = NULL, id_col = "region")
data |
Data frame of keyed styles, or |
id_col |
Column in |
A dragmapr_styles data frame with columns region, fill,
stroke, stroke_width, opacity, label_visible, and highlight.
d_validate_state() checks a d_state() and returns TRUE when it is
valid, throwing an informative error otherwise. It is the d_-prefixed
predicate form of validate_dragmapr_state(), convenient for assertions
and stopifnot().
d_validate_state(state)d_validate_state(state)
state |
A |
TRUE for a valid state.
d_validate_state(d_state())d_validate_state(d_state())
Create a native dragmapr htmlwidget
d_widget( x, region_col, label_col = region_col, labels = TRUE, state = NULL, region_palette = NULL, geometry_options = d_geometry_options(), display_options = d_display_options(), interaction_options = d_interaction_options(), width = "100%", height = "650px", elementId = NULL )d_widget( x, region_col, label_col = region_col, labels = TRUE, state = NULL, region_palette = NULL, geometry_options = d_geometry_options(), display_options = d_display_options(), interaction_options = d_interaction_options(), width = "100%", height = "650px", elementId = NULL )
x |
An |
region_col |
Column defining draggable groups. |
label_col |
Column used for default region-label text. |
labels |
Show draggable labels, omit labels, or pass a label table. |
state |
Optional |
region_palette |
Optional named colour vector passed to
|
geometry_options |
Options from |
display_options |
Options from |
interaction_options |
Options from |
width, height
|
htmlwidget container size. |
elementId |
Optional widget element id. |
An htmlwidget.
The native widget reports edits to Shiny through an input named
paste0(outputId, "_state"). This function turns that value back into a
d_state() so server code can persist, merge, or re-render the user's
live composition. It is the inbound half of the widget bridge that
d_widget() / updateDragmapr() form on the outbound side.
d_widget_state(value)d_widget_state(value)
value |
The list received from |
The browser's monotonic revision becomes the state version unchanged –
the client owns the live counter, so the server records the edit faithfully
rather than bumping it again. The empty-string selection sentinel is mapped
back to NULL.
A dragmapr_state, or NULL if value is NULL.
## Not run: shiny::observeEvent(input$map_state, { state <- d_widget_state(input$map_state) write_dragmapr_state(state, "composition.json") }) ## End(Not run)## Not run: shiny::observeEvent(input$map_state, { state <- d_widget_state(input$map_state) write_dragmapr_state(state, "composition.json") }) ## End(Not run)
Finds candidate hierarchy pairs in a data frame or sf object. A pair is
treated as parent-child when the child column has more groups than the
parent column and most child values sit inside one parent group.
detect_hierarchy_columns( x, cols = NULL, max_child_groups = 600L, min_confidence = 0.72 )detect_hierarchy_columns( x, cols = NULL, max_child_groups = 600L, min_confidence = 0.72 )
x |
A data frame or |
cols |
Optional character vector of columns to inspect. |
max_child_groups |
Maximum number of child groups to recommend for interactive bloom. Pairs above this limit are returned but flagged. |
min_confidence |
Minimum confidence for the |
A data frame with one row per detected pair.
df <- data.frame( county = c("A", "A", "B", "B"), town = c("A1", "A2", "B1", "B2") ) detect_hierarchy_columns(df)df <- data.frame( county = c("A", "A", "B", "B"), town = c("A1", "A2", "B1", "B2") ) detect_hierarchy_columns(df)
Opens an interactive HTML page where you can drag map regions and labels
into any layout you like. When you are happy with the result, click the
copy or download buttons to save two small CSV files (one for regions, one
for labels). Pass those CSVs to render_dragged_map() to reproduce the
layout as a static image.
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, legend_reflects_bloom = FALSE, 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, legend_reflects_bloom = FALSE, 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.
|
legend_reflects_bloom |
When |
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 branch-bloom transition for parent/child
grouping. A named list with elements: |
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 (its "Label style mappings" section translates interactive
styling options to static arguments); 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 = interactive()) } # 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 = interactive()) } # Write to a specific path without opening (e.g. for Shiny or CI). drag_map_prototype(poly, region_col = "region", file = tempfile(fileext = ".html"))
Shiny bindings for dragmapr widgets
dragmaprOutput(outputId, width = "100%", height = "650px") renderDragmapr(expr, env = parent.frame(), quoted = FALSE)dragmaprOutput(outputId, width = "100%", height = "650px") renderDragmapr(expr, env = parent.frame(), quoted = FALSE)
outputId |
Shiny output id. |
width, height
|
Output dimensions. |
expr |
Expression returning |
env |
Evaluation environment. |
quoted |
Is |
Shiny output/render functions.
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)
Inherit drag offsets between hierarchy levels
inherit_drag_offsets(state, from, to, relation)inherit_drag_offsets(state, from, to, relation)
state |
A |
from, to
|
Column names in |
relation |
Data frame mapping parent keys to child keys. |
A dragmapr_state at level to.
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
Builds renderer-neutral connector rows from label anchors and label offsets.
label_connectors( labels, state, threshold_m = 1, connector_type = NULL, include_unmoved = FALSE, as_sf = FALSE, crs = NA )label_connectors( labels, state, threshold_m = 1, connector_type = NULL, include_unmoved = FALSE, as_sf = FALSE, crs = NA )
labels |
Label data accepted by |
state |
A |
threshold_m |
Minimum connector distance to mark visible. |
connector_type |
Optional connector type override. |
include_unmoved |
Include zero-distance rows. |
as_sf |
Return an |
crs |
Optional CRS for |
A data frame or sf object.
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")
Creates the dual-label table understood by the branch-bloom browser helper. Parent labels are safe for normal use. Child labels are optional and mainly useful for testing because many child labels can make branch animation feel busy or slow.
make_branch_bloom_labels( x, parent_key_col = "..dragmapr_parent_key..", child_key_col = "..dragmapr_child_key..", shell_col = "..dragmapr_parent_shell..", parent_label_col = parent_key_col, child_label_col = child_key_col, show_parent_labels = TRUE, show_child_labels = FALSE, max_label_chars = 36, connector = FALSE, label_type = "label" )make_branch_bloom_labels( x, parent_key_col = "..dragmapr_parent_key..", child_key_col = "..dragmapr_child_key..", shell_col = "..dragmapr_parent_shell..", parent_label_col = parent_key_col, child_label_col = child_key_col, show_parent_labels = TRUE, show_child_labels = FALSE, max_label_chars = 36, connector = FALSE, label_type = "label" )
x |
An |
parent_key_col, child_key_col, shell_col
|
Column names holding the parent key, child key, and parent-shell flag. |
parent_label_col, child_label_col
|
Optional columns used for label text. Defaults to the parent and child key columns. |
show_parent_labels, show_child_labels
|
Include parent or child labels. |
max_label_chars |
Maximum number of characters before label text is
shortened with |
connector, label_type
|
Values written to the returned label table. |
A data frame suitable for the labels argument of
drag_map_prototype(). Returns a zero-row label table when both label
levels are disabled.
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
Missing or empty region_col values are dropped before anchors are derived;
an error is raised when no valid region values remain.
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")
Merge dragmapr state updates
merge_dragmapr_state(state, update)merge_dragmapr_state(state, update)
state |
Base |
update |
Update |
A merged dragmapr_state. Its version is one greater than the
higher of the two input revisions, so the merged state always sorts after
both of its inputs.
Merge keyed feature styles
merge_dragmapr_styles(base, update)merge_dragmapr_styles(base, update)
base, update
|
Objects created by |
A dragmapr_styles table.
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
Combines CRS information, geometry counts, candidate hierarchies, and a recommended parent-child bloom setup.
profile_spatial_upload(x, parent_col = NULL)profile_spatial_upload(x, parent_col = NULL)
x |
An |
parent_col |
Optional preferred parent column. |
A list with crs, geometry_type, n_features, hierarchy, and
animation.
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)
Picks a parent column and, when available, a child column suitable for bloom/leaf-flip animation.
recommend_dragmapr_hierarchy(x, parent_col = NULL, max_child_groups = 600L)recommend_dragmapr_hierarchy(x, parent_col = NULL, max_child_groups = 600L)
x |
A data frame or |
parent_col |
Optional preferred parent column. |
max_child_groups |
Maximum number of child groups to recommend. |
A list with parent, child, confidence, reason, and pairs.
Builds renderer-neutral movement connector rows from source geometry and a
dragmapr_state. Each row describes the line from a region's original anchor
to its state-adjusted anchor.
region_connectors( x, state, region_col = NULL, threshold_m = 1, include_unmoved = FALSE, as_sf = FALSE )region_connectors( x, state, region_col = NULL, threshold_m = 1, include_unmoved = FALSE, as_sf = FALSE )
x |
An |
state |
A |
region_col |
Region column in |
threshold_m |
Minimum movement distance to mark a connector visible. |
include_unmoved |
Include zero-distance rows. |
as_sf |
Return an |
A data frame or sf object.
Remove or keep spatial features
remove_spatial_features( x, ids, key_col = NULL, invert = FALSE, prune_empty = TRUE ) delete_spatial_features( x, ids, key_col = NULL, invert = FALSE, prune_empty = TRUE ) keep_spatial_features(x, ids, key_col = NULL, prune_empty = TRUE)remove_spatial_features( x, ids, key_col = NULL, invert = FALSE, prune_empty = TRUE ) delete_spatial_features( x, ids, key_col = NULL, invert = FALSE, prune_empty = TRUE ) keep_spatial_features(x, ids, key_col = NULL, prune_empty = TRUE)
x |
An |
ids |
Feature ids to remove or keep. Matched against |
key_col |
Optional stable id column. |
invert |
When |
prune_empty |
Drop empty geometries after filtering. |
An sf object with the same CRS and geometry column as x.
Takes the offset CSVs you downloaded from drag_map_prototype() and
produces a ggplot2 image with regions and labels in the positions you
dragged them to. If you used Spatial Studio, use
render_dragmapr_project() instead - it reads everything from the project
ZIP in one call.
render_dragged_map( x, region_offsets = NULL, region_col, label_col = region_col, label_offsets = NULL, state = NULL, styles = 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, state = NULL, styles = 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 |
state |
Optional |
styles |
Optional |
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 |
The interactive drag_map_prototype() helper and this static renderer
expose the same label styling concepts under slightly different argument
names and units. Use this mapping to carry a styled interactive layout into
a matching static export:
Interactive (drag_map_prototype()) |
Static (render_dragged_map()) |
Notes |
label_text_size |
label_size |
Pixels become points; the addin uses label_text_size / 3. |
label_radius |
marker_size |
Pixels become points; the addin uses label_radius / 3. |
label_marker |
show_label_marker |
Logical toggle in both. |
label_marker_shape |
label_marker_shape |
Same "circle"/"rect"/"none" values. |
connector_color |
connector_color |
Same name. |
connector_linewidth |
connector_linewidth |
Same name; browser pixels vs. plot units. |
connector_linetype |
connector_linetype |
Same values. |
connector_endpoint |
connector_endpoint |
Same values. |
show_legend, legend_position, legend_title, legend_values, max_legend_keys |
Same names | Identical spelling. |
region_palette |
region_palette |
Same name. |
map_background |
map_background |
Same values. |
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 = interactive()): 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 = interactive()) # 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 = interactive()): 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 = interactive()) # 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") }
Reset offsets in a dragmapr state
reset_region(state, region) reset_regions(state, region) reset_label(state, label_id) reset_labels(state) reset_all(state)reset_region(state, region) reset_regions(state, region) reset_label(state, label_id) reset_labels(state) reset_all(state)
state |
A |
region, label_id
|
Region or label IDs to reset. |
An updated dragmapr_state with a bumped version.
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, label_prefer = NULL, prefer = NULL)select_label_ids(labels, max_labels = 25, label_prefer = NULL, prefer = NULL)
labels |
A drag label table accepted by |
max_labels |
Maximum number of label IDs to return. |
label_prefer |
Optional label IDs to keep first, for example labels from an expanded branch or labels the user has edited. |
prefer |
Deprecated alias for |
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)
Snapshot or restore hierarchy state
snapshot_dragmapr_hierarchy_state(hierarchy) restore_dragmapr_hierarchy_state(snapshot)snapshot_dragmapr_hierarchy_state(hierarchy) restore_dragmapr_hierarchy_state(snapshot)
hierarchy |
|
snapshot |
Plain hierarchy list previously returned by
|
A plain list or restored hierarchy state.
Snapshot or restore dragmapr state
snapshot_dragmapr_state(state) migrate_dragmapr_state(snapshot, target_schema_version = "1.2.0") restore_dragmapr_state(snapshot)snapshot_dragmapr_state(state) migrate_dragmapr_state(snapshot, target_schema_version = "1.2.0") restore_dragmapr_state(snapshot)
state |
A |
snapshot |
A list previously returned by |
target_schema_version |
Schema version to migrate snapshots to before
restoring. Must use whole-number |
snapshot_dragmapr_state() returns a plain list.
restore_dragmapr_state() returns a dragmapr_state.
migrate_dragmapr_state() returns a migrated plain list.
Builds a plain data frame for Shiny tables, review screens, and scripted edit workflows. Geometry is summarized instead of expanded so users can decide which features to remove without accidentally dropping the active geometry column.
spatial_feature_table(x, key_col = NULL, include_geometry = FALSE) view_spatial_features(x, key_col = NULL, include_geometry = FALSE)spatial_feature_table(x, key_col = NULL, include_geometry = FALSE) view_spatial_features(x, key_col = NULL, include_geometry = FALSE)
x |
An |
key_col |
Optional column containing stable feature ids. When omitted,
|
include_geometry |
Include the active geometry list-column. Defaults to
|
A data frame with .feature_id, .row, .geometry_type, bbox
columns, and the non-geometry attributes from x.
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")
Returns plain-language CRS metadata and what the units mean for drag offsets.
summarise_spatial_crs(x)summarise_spatial_crs(x)
x |
An |
A list with CRS id, name, type, units, bounds, and message.
Summarise a dragmapr state
## S3 method for class 'dragmapr_state' summary(object, ...)## S3 method for class 'dragmapr_state' summary(object, ...)
object |
A |
... |
Unused. |
A summary.dragmapr_state object.
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 400 ms branch 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 = 400, overshoot = 0, max_stretch = 0.35, n_frames = 30, preserve_skeleton = TRUE, global_relayout = FALSE, show_ghost = TRUE, show_trails = FALSE, reset_boundary = NULL, group_drag_frame = TRUE, boundary_behavior = c("drag", "none"), boundary_drag_threshold = 8, boundary_label = "Drag to", boundary_padding = 0.025, drag_boundary_with_group = TRUE )transition_options( mode = c("local_elastic", "local_insert"), duration_ms = 400, overshoot = 0, max_stretch = 0.35, n_frames = 30, preserve_skeleton = TRUE, global_relayout = FALSE, show_ghost = TRUE, show_trails = FALSE, reset_boundary = NULL, group_drag_frame = TRUE, boundary_behavior = c("drag", "none"), boundary_drag_threshold = 8, boundary_label = "Drag to", 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 |
Deprecated logical alias for |
group_drag_frame |
Logical. Generate the dotted group-drag boundary
around each expanded group. Defaults to |
boundary_behavior |
Boundary mode. Use |
boundary_drag_threshold |
Pixel threshold before a dotted-frame pointer movement counts as a drag instead of a click. |
boundary_label |
Single string used as the helper label for the
dotted group frame. Defaults to |
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 branch bloom:
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))
Safely update label offsets in a dragmapr state
update_label_offset( state, label_id, dx_m = NULL, dy_m = NULL, mode = c("replace", "increment"), region = NULL )update_label_offset( state, label_id, dx_m = NULL, dy_m = NULL, mode = c("replace", "increment"), region = NULL )
state |
A |
label_id |
Label ID to update. |
dx_m, dy_m
|
New or incremental offsets. |
mode |
|
region |
Optional region for a new label row. Defaults to |
An updated dragmapr_state with a bumped version.
Safely update region offsets in a dragmapr state
update_region_offset( state, region, dx_m = NULL, dy_m = NULL, mode = c("replace", "increment") )update_region_offset( state, region, dx_m = NULL, dy_m = NULL, mode = c("replace", "increment") )
state |
A |
region |
Region ID to update. |
dx_m, dy_m
|
New or incremental offsets. |
mode |
|
An updated dragmapr_state with a bumped version.
Update a dragmapr widget in place
updateDragmapr(session, outputId, ..., generation = NULL, revision = NULL)updateDragmapr(session, outputId, ..., generation = NULL, revision = NULL)
session |
Shiny session. |
outputId |
Widget output id. |
... |
Live updates to apply. Display options use the R API, for example
|
generation |
Optional widget generation token. When supplied, the browser ignores the update unless it targets the active render generation. |
revision |
Optional server-side revision token to echo in the widget acknowledgement input. |
Invisibly returns the sent message.
Checks whether child_col can subdivide parent_col for leaf-flip bloom.
validate_bloom_hierarchy(x, parent_col, child_col, max_child_groups = 600L)validate_bloom_hierarchy(x, parent_col, child_col, max_child_groups = 600L)
x |
A data frame or |
parent_col |
Parent grouping column. |
child_col |
Child grouping column. |
max_child_groups |
Maximum number of child groups allowed. |
A list with valid, message, parent_key, child_key, and
summary counts.
Validate a dragmapr state object
validate_dragmapr_state(state)validate_dragmapr_state(state)
state |
A |
The validated state, invisibly.
Validate compatibility between geometry and dragmapr state
validate_state_compatibility( x, state, region_col = NULL, geometry_id = NULL, strict = TRUE )validate_state_compatibility( x, state, region_col = NULL, geometry_id = NULL, strict = TRUE )
x |
An |
state |
A |
region_col |
Region column in |
geometry_id |
Optional expected geometry ID or fingerprint. |
strict |
Treat warnings as invalid. |
A dragmapr_compatibility object with structured findings.
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, state = NULL, hierarchy = NULL, styles = 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, state = NULL, hierarchy = NULL, styles = 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). |
state |
Optional |
hierarchy |
Optional |
styles |
Optional |
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.
if(interactive()){ 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) }if(interactive()){ 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) }
Read and write dragmapr state JSON
write_dragmapr_state(state, path) read_dragmapr_state(path)write_dragmapr_state(state, path) read_dragmapr_state(path)
state |
A |
path |
File path. |
write_dragmapr_state() invisibly returns path;
read_dragmapr_state() returns a dragmapr_state.
state <- d_state( region_offsets = data.frame(region = "A", dx_m = 10, dy_m = -5) ) path <- tempfile(fileext = ".json") write_dragmapr_state(state, path) restored <- read_dragmapr_state(path) d_state_equal(state, restored)state <- d_state( region_offsets = data.frame(region = "A", dx_m = 10, dy_m = -5) ) path <- tempfile(fileext = ".json") write_dragmapr_state(state, path) restored <- read_dragmapr_state(path) d_state_equal(state, restored)