# Getting started with dragmapr

`dragmapr` is built around a deliberately small loop for draggable plots:

1. Start with projected `sf` geometry and a grouping column.
2. Open the draggable browser helper with `drag_map_prototype(open = interactive())`.
3. Drag regions, labels, or annotation boxes until the layout looks right.
4. Copy or download the offset CSVs from the helper panel.
5. Optionally reproduce the layout as a static `ggplot2` image with `render_dragged_map()`.

The interactive helper is the primary deliverable. Step 5 is optional — use it when you need a reproducible image for a report or publication.

## Toy geometry

All examples below use a projected toy dataset so the workflow can be tested without downloading shapefiles.

    library(dragmapr)

    make_square <- function(x0, y0, size = 100000) {
      sf::st_polygon(list(rbind(
        c(x0, y0), c(x0 + size, y0), c(x0 + size, y0 + size),
        c(x0, y0 + size), c(x0, y0)
      )))
    }

    regions <- sf::st_sf(
      region = c("North", "South", "East", "West"),
      label  = c("North", "South", "East", "West"),
      geometry = sf::st_sfc(
        make_square(0,       140000),
        make_square(0,            0),
        make_square( 140000,  70000),
        make_square(-140000,  70000),
        crs = 3857
      )
    )

## `drag_map_prototype()` — full parameter reference

### Data

These three arguments identify the geometry and what to group or label.

Argument | Default | Description
--- | --- | ---
`x` | (required) | Projected `sf` object. Must not be in a geographic (lon/lat) CRS.
`region_col` | (required) | Column name that defines draggable groups.
`label_col` | `region_col` | Column used for label text. Defaults to the grouping column.

    # Minimal call — one grouping column used for both groups and labels
    drag_map_prototype(regions, region_col = "region", open = interactive())

    # Separate column for label text
    drag_map_prototype(regions, region_col = "region", label_col = "label", open = interactive())

### Labels

Control whether labels appear and whether they can be dragged independently.

Argument | Default | Description
--- | --- | ---
`labels` | `TRUE` | `TRUE` derives one label per region automatically. `FALSE` shows no labels. Supply a data frame from `as_drag_labels()` or `as_drag_annotations()` for custom labels.
`draggable_labels` | `TRUE` | When `TRUE`, labels can be moved independently. When `FALSE`, labels follow their region but cannot be repositioned on their own.

    # No labels
    drag_map_prototype(regions, region_col = "region", labels = FALSE, open = interactive())

    # Labels follow regions but cannot be dragged separately
    drag_map_prototype(regions, region_col = "region",
                       draggable_labels = FALSE, open = interactive())

    # Custom label data frame
    custom_labels <- make_region_labels(regions, region_col = "region", label_col = "label")
    drag_map_prototype(regions, region_col = "region",
                       labels = custom_labels, open = interactive())

### Label styling

Choose between three marker shapes for short text labels — rounded box, circle, or text-only — and control their sizes and font.

Argument | Default | Description
--- | --- | ---
`label_marker` | `TRUE` | Draw a visible marker shape behind label text. `FALSE` is a shortcut for `label_marker_shape = "none"`.
`label_marker_shape` | `"rect"` | Shape behind the label text: `"rect"` (rounded box), `"circle"`, or `"none"` (text only with an invisible drag target).
`label_text_size` | `11` | Label text size in browser pixels. Applies to all label types.
`label_width` | `64` | Width of rounded-box label markers in pixels.
`label_height` | `30` | Height of rounded-box label markers in pixels.
`label_radius` | `12` | Circle radius in pixels. Used when `label_marker_shape = "circle"`.
`label_box_width` | `150` | Width of draggable annotation box (info-box style) in pixels.
`label_box_height` | `72` | Height of draggable annotation box in pixels.

    # Rounded-box markers (default) — adjust size and text
    drag_map_prototype(
      regions, region_col = "region",
      label_marker_shape = "rect",
      label_text_size    = 12,
      label_width        = 80,
      label_height       = 32,
      open = interactive()
    )

    # Circle markers
    drag_map_prototype(
      regions, region_col = "region",
      label_marker_shape = "circle",
      label_radius       = 18,
      label_text_size    = 11,
      open = interactive()
    )

    # Text only — no visible marker, just draggable text
    drag_map_prototype(
      regions, region_col = "region",
      label_marker_shape = "none",
      label_text_size    = 13,
      open = interactive()
    )

    # Annotation boxes (info-box style with connectors)
    notes <- as_drag_annotations(
      make_region_labels(regions, region_col = "region"),
      width_px       = 160,
      height_px      = 70,
      connector      = TRUE,
      connector_type = "elbow"
    )
    drag_map_prototype(
      regions, region_col = "region",
      labels           = notes,
      label_box_width  = 160,
      label_box_height = 70,
      open = interactive()
    )

### Connectors

Connector lines link a label or annotation box back to its region anchor. They are only drawn for labels that have `connector = TRUE` in their label data frame — set that flag via `as_drag_annotations(..., connector = TRUE)` or `as_drag_labels()`. The line style (`"straight"`, `"elbow"`, `"curve"`, `"squiggle"`) is stored per-label in the `connector_type` column.

Argument | Default | Description
--- | --- | ---
`connector_color` | `"#334155"` | Browser connector line colour.
`connector_linewidth` | `1.3` | Connector line thickness in browser pixels.
`connector_linetype` | `"solid"` | Browser connector line pattern: `"solid"`, `"dashed"`, or `"dotted"`.
`connector_endpoint` | `"none"` | Browser connector endpoint: `"none"` or `"arrow"`.
`connector_smart` | `FALSE` | Let the browser choose straight, elbow, or curved connector geometry from the current label displacement.

    drag_map_prototype(
      regions, region_col = "region",
      labels              = notes,   # labels with connector = TRUE
      connector_color     = "#334155",
      connector_linewidth = 2,
      connector_linetype  = "dashed",
      connector_endpoint  = "arrow",
      connector_smart     = TRUE,
      open = interactive()
    )

### Movement context

Movement context is optional and off by default. It helps explain where a moved region came from without changing the underlying offset data.

Argument | Default | Description
--- | --- | ---
`show_origin_outlines` | `FALSE` | Draw the original outline for regions with non-zero offsets.
`show_movement_connectors` | `FALSE` | Draw a line from each moved region’s original representative point to its current location.
`movement_connector_color` | `"#64748b"` | Movement connector colour.
`movement_connector_opacity` | `0.72` | Movement connector opacity from 0 to 1.
`movement_connector_linewidth` | `1.4` | Browser movement connector thickness in pixels.
`movement_connector_linetype` | `"solid"` | Movement connector pattern: `"solid"`, `"dashed"`, or `"dotted"`.
`movement_connector_endpoint` | `"closed"` | Movement connector endpoint: `"closed"`, `"open"`, or `"none"`.
`show_drag_trail` | `FALSE` | Browser-only fading outline trail while a region is actively dragged.

    drag_map_prototype(
      regions, region_col = "region",
      show_origin_outlines = TRUE,
      show_movement_connectors = TRUE,
      movement_connector_color = "#64748b",
      movement_connector_linetype = "dashed",
      movement_connector_endpoint = "open",
      show_drag_trail = TRUE,
      open = interactive()
    )

Static exports support origin outlines and movement connectors too:

    render_dragged_map(
      regions,
      region_offsets = region_offsets,
      region_col = "region",
      show_origin_outlines = TRUE,
      show_movement_connectors = TRUE,
      movement_connector_linetype = "dotted",
      movement_connector_endpoint = "closed"
    )

### Initial positions

Supply previously exported offset tables to pre-load a saved layout so dragging can continue from where it left off.

Argument | Default | Description
--- | --- | ---
`region_offsets` | `NULL` | Data frame with columns `region`, `dx_m`, `dy_m`. All regions start at zero when `NULL`.
`label_offsets` | `NULL` | Data frame with columns `label_id`, `region`, `dx_m`, `dy_m`. All labels start at zero when `NULL`.

    # Resume from previously downloaded CSVs
    region_csv <- read_offsets("drag_region_offsets.csv")
    label_csv  <- read_label_state("drag_label_offsets.csv")

    drag_map_prototype(
      regions, region_col = "region",
      region_offsets = region_csv,
      label_offsets  = label_csv,
      open = interactive()
    )

`read_label_offsets()` is retained as an alias for `read_label_state()`, and `apply_label_offsets()` is retained as an alias for `apply_label_state()`. Likewise, `make_labels()` remains an alias for `make_region_labels()` for older scripts.

If the offsets were exported as a Spatial Studio project ZIP, use the one-line project renderer instead of wiring the CSV files together manually:

    render_dragmapr_project(
      "dragmapr-project.zip",
      file = "dragged-map.png"
    )

### RStudio addin

In RStudio, install the package and use Addins > Launch dragmapr to open a compact prototype gadget. The addin looks for `sf` objects in `.GlobalEnv`, lets you choose the region and label columns, and assigns `region_offsets` and `label_offsets` when you click Done. Create or load the `sf` object before opening the addin. If you call `dragmapr_addin()` directly, pass `env =` to work with another environment.

### Colour palette

Argument | Default | Description
--- | --- | ---
`region_palette` | `NULL` | Named character vector mapping each region value to a hex colour string. Uses a built-in 8-colour cycling palette when `NULL`.

Matching the interactive palette to a `render_dragged_map()` call makes the draggable preview and the final static image look identical.

    my_palette <- c(
      North = "#4C78A8",
      South = "#F58518",
      East  = "#54A24B",
      West  = "#B279A2"
    )

    drag_map_prototype(
      regions, region_col = "region",
      region_palette = my_palette,
      show_legend    = TRUE,
      open = interactive()
    )

### Legend

A compact colour legend can be embedded directly inside the browser helper. It is hidden by default because many maps are labelled and need no legend.

Argument | Default | Description
--- | --- | ---
`show_legend` | `FALSE` | Show a colour legend in the helper.
`max_legend_keys` | `25` | Suppress the legend automatically when the number of groups exceeds this value. Set to `Inf` to always show it regardless of group count.
`legend_position` | `"bottom"` | Where the legend appears: `"bottom"`, `"top"`, `"left"`, `"right"`, or `"none"`.
`legend_title` | `"Region"` | Title shown above the legend keys.
`legend_values` | `NULL` | Optional character vector of region values to include in the legend. `NULL` includes all values.

    drag_map_prototype(
      regions, region_col = "region",
      region_palette  = my_palette,
      show_legend     = TRUE,
      legend_position = "bottom",   # "top" | "left" | "right" | "none"
      legend_title    = "Region",
      legend_values   = c("North", "East"),
      max_legend_keys = 25,
      open = interactive()
    )

Use `label_values` when an app should temporarily display only selected labels while preserving all label offsets:

    drag_map_prototype(
      regions, region_col = "region",
      label_values = c("North", "East"),
      open = interactive()
    )

### Output file and display

Argument | Default | Description
--- | --- | ---
`file` | `"drag-map.html"` | File path for the written standalone HTML.
`open` | `FALSE` | Open the file in the default browser via `browseURL()` after writing.
`side_panel` | `TRUE` | Show the built-in copy/download side panel. Shiny apps that provide their own export controls can set this to `FALSE` to reclaim the full canvas.
`map_background` | `"white"` | Helper background: `"white"`, `"transparent"`, `"light_grid"`, or `"dark"`.

    # Write to a chosen path without opening (e.g. CI, server, or Shiny)
    drag_map_prototype(
      regions, region_col = "region",
      file       = "output/my_map.html",
      map_background = "light_grid",
      side_panel = TRUE,
      open       = FALSE
    )

    # Embedded in a Shiny app — hide the panel; the app provides its own controls
    drag_map_prototype(
      regions, region_col = "region",
      side_panel = FALSE,
      file       = tempfile(fileext = ".html")
    )

## Optional: Static rendering

When you need a reproducible `ggplot2` image, pass the exported offset tables to `render_dragged_map()`. The data frames below stand in for downloaded CSVs:

    region_offsets <- data.frame(
      region = c("North", "South", "East", "West"),
      dx_m   = c(0, 0,  60000, -60000),
      dy_m   = c(50000, -50000, 0, 0)
    )

    label_state <- data.frame(
      label_id = c("North", "South", "East", "West"),
      region   = c("North", "South", "East", "West"),
      dx_m     = c(0, 0,  25000, -25000),
      dy_m     = c(30000, -30000, 0, 0)
    )

    render_dragged_map(
      regions,
      region_offsets = region_offsets,
      region_col     = "region",
      label_col      = "label",
      label_offsets  = label_state,
      title          = "Synthetic draggable map"
    )

The same annotation types available in the interactive helper work in static output:

    notes <- as_drag_annotations(data.frame(
      label_id = "east-note",
      region   = "East",
      label    = "The East label can become a longer draggable note.",
      x = 210000, y = 120000
    ), connector = TRUE, connector_type = "squiggle")

    render_dragged_map(
      regions,
      region_offsets      = region_offsets,
      region_col          = "region",
      labels              = notes,
      label_offsets       = data.frame(
        label_id = "east-note", region = "East",
        dx_m = 80000, dy_m = 45000
      ),
      connector_linewidth = 0.8,
      connector_linetype  = "dotted",
      connector_endpoint  = "arrow",
      legend_title        = "Region",
      map_background      = "light_grid",
      title               = "Static output with an annotation box"
    )

## Running examples

Installed example scripts live under `system.file("examples", package = "dragmapr")`. To exercise the full package surface non-interactively:

    source(system.file("examples", "smoke_examples.R", package = "dragmapr"))

Shiny examples launch interactive apps and must be run separately. See the Shiny workflows vignette for a full walkthrough, or run any example directly:

    if (interactive()) {
      shiny::runApp(system.file("examples", "shiny_draggable_plot.R",   package = "dragmapr"))
      shiny::runApp(system.file("examples", "shiny_custom_labels.R",    package = "dragmapr"))
      shiny::runApp(system.file("examples", "shiny_draggable_export.R", package = "dragmapr"))
      shiny::runApp(system.file("examples", "shiny_spatial_studio.R",   package = "dragmapr"))
      shiny::runApp(system.file("examples", "shiny_static_export.R",    package = "dragmapr"))
    }