human_body_map_selector

A Flutter widget for picking anatomical regions on a front/back human body diagram. Tap a body part to drop a pin and get back which region it landed in - useful for injury/soreness trackers, symptom checkers, fitness apps, or any UI that needs "which part of the body" as input.

Ships with a bundled front/back body diagram and a hand-placed set of ~35 anatomical regions, or bring your own image and region geometry.

Screenshots

Front Back
Front view of the body map selector, with several selected regions numbered Back view of the body map selector, with several selected regions numbered

Features

  • HumanBodyMapSelector - a ready-to-use widget: Front/Back toggle, body diagram, tap-to-select/deselect a region, numbered pins.
  • BodyRegionImagePicker - the lower-level building block if you want full control over state (e.g. driving it from your own view model): give it an image, a list of tappable rectangles, and a list of pins to draw; it calls you back with the region id and exact tapped point.
  • defaultBodyRegions - the bundled region set, or supply your own BodyRegion list against your own diagram.
  • Plain Flutter theming - colors default to Theme.of(context).colorScheme and can be overridden per-widget. No required third-party dependencies.

Getting started

dependencies:
  human_body_map_selector: ^1.0.0

Usage

Drop-in widget

import 'package:human_body_map_selector/human_body_map_selector.dart';

HumanBodyMapSelector(
  onSelectionChanged: (selections) {
    for (final selection in selections) {
      final region = defaultBodyRegionsById[selection.regionId]!;
      debugPrint('${region.label} (${selection.view.label}) at ${selection.point}');
    }
  },
)

Tapping a region drops a pin and adds it to selections; tapping the same region again removes it. Set allowMultiplePerRegion: true if a region should be able to carry more than one pin instead of toggling.

Full control

For a controlled widget (state owned by you, e.g. a view model), use BodyRegionImagePicker directly together with defaultBodyRegions:

import 'dart:ui';
import 'package:human_body_map_selector/human_body_map_selector.dart';

BodyView view = BodyView.front;
final pins = <({String regionId, Offset point})>[];

BodyRegionImagePicker(
  imageAsset: view == BodyView.front ? kBodyFrontAsset : kBodyBackAsset,
  imagePackage: kBodyMapPackageName,
  aspectRatio: view == BodyView.front ? kBodyFrontAspectRatio : kBodyBackAspectRatio,
  areas: [
    for (final region in defaultBodyRegions)
      if (region.view == view)
        for (final rect in region.areas) BodyImageArea(id: region.id, rect: rect),
  ],
  pins: [
    for (var i = 0; i < pins.length; i++)
      BodyPinMark(point: pins[i].point, label: '${i + 1}'),
  ],
  onSelectRegion: (regionId, point) {
    // Update your own state and rebuild.
  },
)

Custom diagram and regions

BodyRegion.areas rectangles are fractions (0..1) of the image's width and height, so they work at any render size:

final myRegions = [
  const BodyRegion(
    id: 'left_shoulder',
    label: 'Left Shoulder',
    view: BodyView.front,
    areas: [Rect.fromLTWH(0.6, 0.15, 0.1, 0.08)],
  ),
  // ...
];

HumanBodyMapSelector(
  regions: myRegions,
  frontImageAsset: 'assets/my_body_front.png',
  backImageAsset: 'assets/my_body_back.png',
  aspectRatio: 1.2,
  showAreaOutlines: true, // handy while tuning rectangles
)

See example/ for a runnable app.

Libraries

human_body_map_selector
A Flutter widget for picking anatomical regions on a front/back human body diagram.