Charts / CH-SPA-05
CH-SPA-05 . family SPA

FLOW MAP

curved width-scaled arrows between supplied places. Needs: base polygons + places + flows [{from, to, value}], <= 8 flows.

flowmagnitude

DL-01 AGRAW
The port feeds the south corridor with 140 loads a week 140 loads Port Hub South site West site North site Source: sample dataset v1, 2026-07-12

Use when

  • origin-destination stories over real geography
  • corridor volumes: what moves where, how much

Do not use when

  • more than ~8 flows (spaghetti)
  • flows both directions between the same pair (split or net them first)

See instead

Alternatives

  • CH-FLO-02 (flows without geography)
  • CH-FLO-04 (dense mutual exchange)

Rules

  • arrow width proportional to value; the largest flow is labeled
  • arrowheads mark direction; curves bend one deterministic way

Never do this

  • two-way arrows on one curve
  • more than 8 flows
  • width not proportional to value

QA before delivering

  • width-true arrows
  • largest flow labeled
  • <= 8 flows
  • source present

Data shape

titleaction title with a number
sourcebottom-left always
unitflow unit
notecoordinates are author-supplied unit-square (0-100) geometry; the renderer scales, the author owns projection and aspect
regionsbase polygons
places[{name, at}]
flows[{from: [x,y], to: [x,y], value}]
Sample data (golden)
{
  "title": "The port feeds the south corridor with 140 loads a week",
  "eyebrow": "WEEKLY FLOWS",
  "source": "Source: sample dataset v1, 2026-07-12",
  "unit": "loads",
  "regions": [
    {
      "name": "North",
      "label_at": [
        32,
        17
      ],
      "polygon": [
        [
          10,
          5
        ],
        [
          55,
          2
        ],
        [
          60,
          25
        ],
        [
          35,
          32
        ],
        [
          8,
          28
        ]
      ]
    },
    {
      "name": "West",
      "label_at": [
        19,
        45
      ],
      "polygon": [
        [
          8,
          28
        ],
        [
          35,
          32
        ],
        [
          30,
          60
        ],
        [
          5,
          58
        ]
      ]
    },
    {
      "name": "Central",
      "label_at": [
        48,
        42
      ],
      "polygon": [
        [
          35,
          32
        ],
        [
          60,
          25
        ],
        [
          68,
          50
        ],
        [
          30,
          60
        ]
      ]
    },
    {
      "name": "East",
      "label_at": [
        78,
        38
      ],
      "polygon": [
        [
          60,
          25
        ],
        [
          92,
          20
        ],
        [
          95,
          55
        ],
        [
          68,
          50
        ]
      ]
    },
    {
      "name": "South",
      "label_at": [
        58,
        72
      ],
      "polygon": [
        [
          30,
          60
        ],
        [
          68,
          50
        ],
        [
          95,
          55
        ],
        [
          90,
          90
        ],
        [
          25,
          88
        ]
      ]
    }
  ],
  "places": [
    {
      "name": "Port",
      "at": [
        80,
        30
      ]
    },
    {
      "name": "Hub",
      "at": [
        48,
        42
      ]
    },
    {
      "name": "South site",
      "at": [
        55,
        75
      ]
    },
    {
      "name": "West site",
      "at": [
        19,
        45
      ]
    },
    {
      "name": "North site",
      "at": [
        32,
        17
      ]
    }
  ],
  "flows": [
    {
      "from": [
        80,
        30
      ],
      "to": [
        48,
        42
      ],
      "value": 140
    },
    {
      "from": [
        48,
        42
      ],
      "to": [
        55,
        75
      ],
      "value": 90
    },
    {
      "from": [
        48,
        42
      ],
      "to": [
        19,
        45
      ],
      "value": 45
    },
    {
      "from": [
        48,
        42
      ],
      "to": [
        32,
        17
      ],
      "value": 30
    },
    {
      "from": [
        80,
        30
      ],
      "to": [
        55,
        75
      ],
      "value": 25
    }
  ]
}