flutter_roadmap_viewer 0.1.8 copy "flutter_roadmap_viewer: ^0.1.8" to clipboard
flutter_roadmap_viewer: ^0.1.8 copied to clipboard

A highly customizable roadmap and skill tree visualization widget with interactive pan/zoom, multiple layout orientations, and progress tracking.

Flutter Roadmap Viewer #

A highly customizable roadmap and skill tree visualization widget for Flutter with interactive pan/zoom, multiple layout orientations, and progress tracking.

Features #

  • Simple API - Create roadmaps with just a list of tuples or JSON data
  • Hierarchical Layout - Sugiyama-style layered graph drawing with crossing reduction
  • Automatic Graph Building - Just provide skill data, relationships are computed automatically
  • Progress Tracking - Four status types: Not Started, Current, Complete, Skipped
  • Multiple Orientations - Horizontal (traditional) or vertical layouts
  • Edge Styles - Curved bezier or orthogonal (right-angle) connections
  • Multiple Node Types - Rectangular, capsule, or circular node widgets
  • Custom Themes - Pre-built themes (light, dark, vibrant) or create your own
  • Custom Node Builders - Full control over node rendering
  • Zoom Controls - Optional zoom in/out and fit-to-screen buttons
  • Progress Utilities - Calculate completion percentage, find ready skills, etc.
  • Transitive Reduction - Automatically removes redundant prerequisite edges

Installation #

Add to your pubspec.yaml:

dependencies:
  flutter_roadmap_viewer: ^0.1.8

Then run:

flutter pub get

Quick Start #

Simplest Usage #

import 'package:flutter_roadmap_viewer/flutter_roadmap_viewer.dart';

// Just provide (id, name, prerequisites) tuples
RoadmapViewer.simple([
  ('basics', 'Learn Basics', []),
  ('widgets', 'Master Widgets', ['basics']),
  ('state', 'State Management', ['basics']),
  ('advanced', 'Advanced Topics', ['widgets', 'state']),
])

From JSON #

// Perfect for API responses
RoadmapViewer.fromJson([
  {'id': 'basics', 'name': 'Learn Basics', 'prerequisiteIds': []},
  {'id': 'widgets', 'name': 'Master Widgets', 'prerequisiteIds': ['basics']},
])

With SkillData Objects #

final skillData = [
  SkillData.simple('basics', 'Flutter Basics', [],
    progressStatus: ProgressStatus.complete),
  SkillData.simple('widgets', 'Widgets', ['basics'],
    progressStatus: ProgressStatus.current),
  SkillData.simple('state', 'State Management', ['basics']),
];

RoadmapViewer(
  skillData: skillData,
  onNodeTap: (node) => print('Tapped: ${node.name}'),
)

Usage Examples #

With Theme #

RoadmapViewer(
  skillData: mySkillData,
  theme: RoadmapThemeData.dark(),
  // Or create custom:
  // theme: RoadmapThemeData(
  //   completeColor: Colors.teal,
  //   currentColor: Colors.amber,
  // ),
)

With Zoom Controls #

RoadmapViewer(
  skillData: mySkillData,
  showZoomControls: true,
  showFitButton: true,
  minScale: 0.2,
  maxScale: 4.0,
)

With Custom Node Builder #

RoadmapViewer(
  skillData: mySkillData,
  nodeBuilder: (context, node, config) {
    // Return custom widget or null for default
    return Container(
      width: config.width,
      height: config.height,
      decoration: config.getDefaultDecoration(),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.star, color: config.borderColor),
          Text(node.name),
          if (config.isComplete)
            Icon(Icons.check, color: Colors.green, size: 16),
        ],
      ),
    );
  },
)

With Vertical Orientation #

RoadmapViewer(
  skillData: mySkillData,
  orientation: RoadmapOrientation.vertical,
  edgeStyle: EdgeStyle.curved,
)

With Node Type Mapping #

RoadmapViewer(
  skillData: mySkillData,
  nodeTypeToWidgetType: const {
    'Course': NodeWidgetType.rectangular,
    'Skill': NodeWidgetType.capsule,
    'Achievement': NodeWidgetType.circular,
  },
)

Without Completion Node #

RoadmapViewer(
  skillData: mySkillData,
  showCompletionNode: false,
)

Progress Calculation #

final skills = mySkillData;

// Get completion percentage (0.0 - 1.0)
final completion = ProgressCalculator.calculateCompletion(skills);
print('${(completion * 100).round()}% complete');

// Get completion as integer percentage
final percent = ProgressCalculator.calculateCompletionPercent(skills);
print('$percent% complete');

// Get counts by status
final counts = ProgressCalculator.getStatusCounts(skills);
print('Complete: ${counts[ProgressStatus.complete]}');
print('In Progress: ${counts[ProgressStatus.current]}');

// Get skills ready to start (prerequisites complete)
final ready = ProgressCalculator.getReadySkills(skills);
print('Ready to start: ${ready.map((s) => s.name).join(', ')}');

// Get the critical path (longest dependency chain)
final criticalPath = ProgressCalculator.getCriticalPath(skills);
print('Critical path: ${criticalPath.length} skills');

// Get formatted summary
final summary = ProgressCalculator.getProgressSummary(skills);
print(summary); // "10/25 complete (40%)"

API Reference #

RoadmapViewer #

Main widget for displaying roadmaps.

Constructors:

Constructor Description
RoadmapViewer() Standard constructor with SkillData list
RoadmapViewer.simple() Quick setup with (id, name, prerequisites) tuples
RoadmapViewer.fromJson() Create from JSON list

Parameters:

Parameter Type Default Description
skillData List<SkillData> required List of skills to display
nodeTypeToWidgetType Map<String, NodeWidgetType>? null Maps node types to widget types
edgeStyle EdgeStyle orthogonal Edge connection style
orientation RoadmapOrientation horizontal Layout direction
horizontalSpacing double 200.0 Space between nodes horizontally
verticalSpacing double 100.0 Space between nodes vertically
showCompletionNode bool true Show completion node at end
theme RoadmapThemeData? null Theme configuration
nodeBuilder NodeBuilder? null Custom node widget builder
showZoomControls bool false Show +/- zoom buttons
showFitButton bool false Show fit-to-screen button
initialFit bool false Auto-fit on initial load
minScale double 0.1 Minimum zoom scale
maxScale double 5.0 Maximum zoom scale
onNodeTap Function(RoadmapNode)? null Node tap callback
onNodeLongPress Function(RoadmapNode)? null Node long-press callback

SkillData #

Simple data model for creating roadmap items.

Constructors:

// Full constructor
SkillData(
  id: 'skill-1',
  name: 'Skill Name',
  type: 'Skill',
  prerequisiteIds: ['prereq-1'],
  progressStatus: ProgressStatus.notStarted,
  metadata: {'key': 'value'},
)

// Simple factory
SkillData.simple('skill-1', 'Skill Name', ['prereq-1'])

// From JSON
SkillData.fromJson({'id': '...', 'name': '...', ...})

// List from JSON
SkillData.listFromJson(jsonList)

RoadmapThemeData #

Theme configuration for colors and styling.

Pre-built themes:

RoadmapThemeData()        // Default pastel theme
RoadmapThemeData.light()  // Bright, cheerful colors
RoadmapThemeData.dark()   // Muted, sophisticated colors
RoadmapThemeData.vibrant() // Bold, saturated colors

Custom theme:

RoadmapThemeData(
  notStartedColor: Color(0xFFE8E8E8),
  currentColor: Color(0xFF2196F3),
  completeColor: Color(0xFF4CAF50),
  skippedColor: Color(0xFFFF9800),
  completionNodeColor: Color(0xFFFFD700),
  edgeColor: Color(0xFF9E9E9E),  // null = use prerequisite status colors
  edgeWidth: 2.0,
  nodeBorderWidth: 2.0,
  showCompletionOverlay: true,
  useGradients: false,
  showShadows: false,
)

NodeBuildContext #

Context provided to custom node builders.

Properties:

Property Type Description
node RoadmapNode The node being rendered
width double Allocated width
height double Allocated height
color Color Base color for status
borderColor Color Border color
gradient Gradient? Optional gradient
shadows List<BoxShadow>? Optional shadows
overlay Widget? Optional overlay (hatch pattern)
isComplete bool Convenience getter
isCurrent bool Convenience getter
isNotStarted bool Convenience getter
getDefaultDecoration() BoxDecoration Default styling

ProgressStatus #

enum ProgressStatus {
  notStarted,  // Not yet started
  current,     // Currently in progress
  complete,    // Completed
  skipped,     // Skipped/not applicable
}

EdgeStyle #

enum EdgeStyle {
  orthogonal,  // Right-angle connections
  curved,      // Smooth bezier curves
}

NodeWidgetType #

enum NodeWidgetType {
  rectangular,  // Rounded rectangle (120x60)
  capsule,      // Pill-shaped (120x60)
  circular,     // Circle (60x60)
}

Data Validation #

final errors = GraphBuilder.validateSkills(skillData);
if (errors.isNotEmpty) {
  print('Validation errors: $errors');
}

Checks for:

  • Duplicate IDs
  • Empty IDs
  • Self-references
  • Broken prerequisite references

Best Practices #

Large Roadmaps #

For roadmaps with 50+ nodes:

  • Increase spacing values
  • Enable zoom controls
  • Consider using vertical orientation for deep hierarchies

Performance #

  • Use const constructors for SkillData when possible
  • The widget efficiently handles layout recalculation on data changes

Custom Themes #

// Extend a preset
final myTheme = RoadmapThemeData.dark().copyWith(
  completeColor: Colors.teal,
  showCompletionOverlay: false,
);

Examples #

See the example/ directory for a complete demo app.

License #

MIT License - see LICENSE file for details.

Changelog #

See CHANGELOG.md for version history.

0
likes
150
points
98
downloads

Publisher

unverified uploader

Weekly Downloads

A highly customizable roadmap and skill tree visualization widget with interactive pan/zoom, multiple layout orientations, and progress tracking.

Repository (GitHub)
View/report issues

Topics

#roadmap #visualization #graph #widget #interactive

Documentation

API reference

License

MIT (license)

Dependencies

equatable, flutter

More

Packages that depend on flutter_roadmap_viewer