force_graph 0.3.9 copy "force_graph: ^0.3.9" to clipboard
force_graph: ^0.3.9 copied to clipboard

Forge2D based force graph with multiple graph layout algorithms (MDS, Spring Embedder, Distance based) and realistic physics.

example/lib/main.dart

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:force_graph/force_graph.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.light(),
      home: const TestPage(),
    );
  }
}

class TestPage extends StatelessWidget {
  const TestPage({super.key});

  @override
  Widget build(BuildContext context) {
    final mockGraphNodes = generateMockGraph(
      maxEdgesPerNode: 6,
      minEdgesPerNode: 1,
      nodeCount: 30,
    );

    // final mockGraphNodes = [
    //   ForceGraphNodeData.from(
    //     id: 'doc1',
    //     title: 'Document 1',
    //     style: GraphComponentStyle(color: Colors.blue),
    //     edges: [
    //       ForceGraphEdgeData.from(
    //         source: 'doc1',
    //         target: 'doc12',
    //         similarity: 1,
    //         weight: 1,
    //       ),
    //     ],
    //   ),
    //   ForceGraphNodeData.from(
    //     id: 'doc2',
    //     title: 'Document 2',
    //     edges: [
    //       ForceGraphEdgeData.from(
    //         source: 'doc2',
    //         target: 'doc13',
    //         similarity: 1,
    //         weight: 1,
    //       ),
    //     ],
    //   ),
    //   // ForceGraphNodeData.from(id: 'doc12', title: 'Document 12'),
    //   // ForceGraphNodeData.from(id: 'doc13', title: 'Document 13'),
    // ];

    return Scaffold(
      body: ForceGraphWidget(
        controller: ForceGraphController(
          nodes: mockGraphNodes,
          // graphBuilder: DistanceGraphBuilder(minDistance: 3, maxDistance: 20),
          uniformEdgeWeight: true,
        ),
        edgeTooltipBuilder: (context, edge) {
          return ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 120),
            child: Card(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(
                  edge.data.similarity.toString(),
                  textAlign: TextAlign.center,
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                ),
              ),
            ),
          );
        },
        nodeTooltipBuilder: (context, node) {
          return ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 120),
            child: Card(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text(node.data.title),
              ),
            ),
          );
        },
      ),
    );
  }
}

List<ForceGraphNodeData> generateMockGraph({
  int nodeCount = 10,
  int minEdgesPerNode = 5,
  int maxEdgesPerNode = 1,
}) {
  final rand = Random();
  final List<ForceGraphNodeData> nodes = [];
  final List<String> ids = List.generate(nodeCount, (i) => 'doc${i + 1}');
  final List<Color> palette = [
    Colors.blue,
    Colors.green,
    Colors.orange,
    Colors.purple,
    Colors.teal,
    Colors.indigo,
  ];

  for (int i = 0; i < nodeCount; i++) {
    final color = palette[i % palette.length];
    nodes.add(
      ForceGraphNodeData.from(
        id: ids[i],
        title: 'Document ${i + 1}',
        style: GraphComponentStyle.from(color: color),
        edges: [],
      ),
    );
  }

  for (final node in nodes) {
    final edgeCount =
        rand.nextInt(maxEdgesPerNode - minEdgesPerNode + 1) + minEdgesPerNode;
    final Set<String> connected = {};

    while (node.edges.length < edgeCount) {
      final targetIndex = rand.nextInt(nodeCount);
      final targetId = ids[targetIndex];

      if (targetId == node.iD || connected.contains(targetId)) continue;
      connected.add(targetId);

      final similarity = rand.nextDouble() * 0.9 + 0.1; // 0.4 - 1.0
      final weight = rand.nextDouble() * 0.8 + 0.2;

      node.edges.add(
        ForceGraphEdgeData.from(
          source: node.iD,
          target: targetId,
          similarity: similarity,
          weight: weight,
          style: GraphComponentStyle.from(
            color: Colors.black.withValues(alpha: 0.2),
          ),
        ),
      );
    }
  }

  return nodes;
}
0
likes
140
points
548
downloads

Publisher

unverified uploader

Weekly Downloads

Forge2D based force graph with multiple graph layout algorithms (MDS, Spring Embedder, Distance based) and realistic physics.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, forge2d, isolate_manager

More

Packages that depend on force_graph