annotation_scalebar: Add a Spatially-Aware Scale Bar

View source: R/annotation_scalebar.R

annotation_scalebarR Documentation

Add a Spatially-Aware Scale Bar

Description

'annotation_scalebar()' adds a projection-aware scale bar to a ggplot map. It reads the map's CRS (from 'coord_sf()' or from the 'crs' argument), chooses a readable width and units, and uses robust fallbacks so that the scale bar still draws even when CRS information is limited.

Supported styles: * '"segment"' – minimal horizontal bar with ticks and labels (default) * '"ticks"' – baseline with vertical ticks * '"bar"' – alternating black/white blocks

Usage

annotation_scalebar(
  mapping = NULL,
  data = NULL,
  ...,
  location = "bl",
  style = "segment",
  fixed_width = NULL,
  crs_unit = NULL,
  crs = NULL,
  display_unit = NULL,
  unit_labels = NULL,
  width_hint = 0.25,
  unit_category = "metric",
  bar_cols = c("black", "white"),
  line_width = 1,
  height = grid::unit(0.25, "cm"),
  pad_x = grid::unit(0.25, "cm"),
  pad_y = grid::unit(0.25, "cm"),
  text_pad = grid::unit(0.15, "cm"),
  text_cex = 0.7,
  text_face = NULL,
  text_family = "",
  tick_height = 0.6,
  segments = NULL,
  label_show = "ends",
  minor_tick_height = 0.5,
  geographic_mode = c("approx_m", "degrees"),
  text_col = "black",
  line_col = "black"
)

Arguments

mapping, data

Standard ggplot2 layer arguments (typically unused).

...

Additional parameters passed to the layer (rarely needed).

location

Character. One of '"bl"', '"br"', '"tr"', '"tl"'; placement relative to panel edges. Default: '"bl"'.

style

Character. Scale bar style: '"segment"' (default), '"bar"', or '"ticks"'.

fixed_width

Numeric. Bar width in *native CRS units* (for example, meters). Overrides automatic width selection.

crs_unit

Character. CRS units (for example '"m"', '"ft"', '"°"'). Usually auto-detected; set only when auto-detection is not possible.

crs

An [sf::st_crs] object or a PROJ string. Fallback CRS when the plot does not provide one (for example, when not using 'coord_sf()').

display_unit

Character. Display units for labels (for example '"m"', '"km"'). Ignored when 'geographic_mode = "degrees"'.

unit_labels

Named character vector for custom unit labels, e.g. 'c(km = "Kilometers", m = "Meters", "°" = "°")'.

width_hint

Numeric in (0, 1]. Target fraction of the panel width used by the bar. Default: '0.25'.

unit_category

Character. '"metric"' (default) or '"imperial"'. Affects automatic promotion of units (m → km, ft → mi).

bar_cols

Character vector of length two. Fill colours for '"bar"' style blocks. Default: 'c("black", "white")'.

line_width

Numeric. Line width for outlines and ticks. Default: '1'.

height

[grid::unit]. Bar height. Default: 'unit(0.25, "cm")'.

pad_x, pad_y

[grid::unit]. Padding from panel edges. Default: 'unit(0.25, "cm")'.

text_pad

[grid::unit]. Gap between the bar and text labels. Default: 'unit(0.15, "cm")'.

text_cex, text_face, text_family

Font settings for labels. Defaults: '0.7', 'NULL', '""'.

tick_height

Numeric in [0, 1]. Relative height of interior ticks for '"ticks"' style. Default: '0.6'.

segments

Integer. For '"segment"' style, number of major divisions. If 'NULL', an automatic, readable choice is used.

label_show

Which ticks get labels: '"ends"' (default), '"all"', '"major"', a numeric frequency (for example '2'), or a numeric vector of 1-based indices.

minor_tick_height

Numeric in [0, 1]. For '"segment"' style, relative height of minor ticks. Default: '0'.

geographic_mode

Character, for **geographic CRS** only: * '"approx_m"': approximate meters/kilometers (default; warns about approximation). * '"degrees"': show raw degrees (no metric conversion).

text_col, line_col

Colours for text labels and outlines/ticks. Defaults: '"black"', '"black"'.

Details

* With a **projected CRS** (for example UTM or AEQD in meters), the scale bar is measured in native map units and is as accurate as the projection. * With a **geographic CRS** (EPSG:4326, degrees), distance depends on latitude. The 'geographic_mode' argument controls how degrees are handled: - '"approx_m"' (default): approximate meters/kilometers using a great-circle distance at the panel’s mid-latitude (a warning is issued). - '"degrees"': display raw degree units (for example '1°') without converting. * You can override the automatically chosen width with 'fixed_width', which is interpreted in native CRS units.

Value

A ggplot2 layer representing a scale bar.

Examples


nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)

base_plot <- ggplot() +
  geom_sf(data = nc, fill = "grey90") +
  theme_minimal()

# Example 1: Projected CRS with a longer scale bar
base_plot +
  coord_sf(crs = 32617) +
  annotation_scalebar(location = "bl", width_hint = 0.5)

# Example 2: Ticks style, top-right
base_plot +
  coord_sf(crs = 32617) +
  annotation_scalebar(location = "tr", style = "ticks")

# Example 3: Geographic CRS (EPSG:4326), approximate meters (warns)
base_plot +
  coord_sf(crs = 4326) +
  annotation_scalebar(location = "bl", geographic_mode = "approx_m")

# Example 4: Force a 100 km bar with red outlines
base_plot +
  coord_sf(crs = 32617) +
  annotation_scalebar(
    location     = "bl",
    fixed_width  = 100000,
    display_unit = "km",
    line_col     = "red"
  )


ggmapcn documentation built on Nov. 23, 2025, 9:06 a.m.