frame method

void frame({
  1. double padding = 200.0,
  2. Duration? animationDuration,
  3. Curve curve = Curves.easeInOut,
})

frame

Animates the viewport to fit all nodes within view, including zooming out if necessary.

Implementation

void frame({
  double padding = 200.0,
  Duration? animationDuration,
  Curve curve = Curves.easeInOut,
}) {
  if (nodes.isEmpty || viewController.viewportSize == null) return;

  final viewportSize = viewController.viewportSize!;

  // Compute the bounding box of all nodes
  double minX = double.infinity;
  double minY = double.infinity;
  double maxX = double.negativeInfinity;
  double maxY = double.negativeInfinity;

  for (var node in nodes) {
    final pos = node.position.toOffset();
    if (pos.dx < minX) minX = pos.dx;
    if (pos.dy < minY) minY = pos.dy;
    if (pos.dx > maxX) maxX = pos.dx;
    if (pos.dy > maxY) maxY = pos.dy;
  }

  final contentWidth = maxX - minX;
  final contentHeight = maxY - minY;

  // Compute scale to fit the bounding box into the viewport
  final scaleX = (viewportSize.width - padding * 2) / contentWidth;
  final scaleY = (viewportSize.height - padding * 2) / contentHeight;
  final targetScale = scaleX < scaleY ? scaleX : scaleY;

  // Clamp to min/max zoom
  final clampedScale = targetScale.clamp(
    viewController.mimZoomLevel,
    viewController.maxZoomLevel,
  );

  // Compute center of the bounding box
  final center = Offset(minX + contentWidth / 2, minY + contentHeight / 2);

  // Compute the offset to center the bounding box
  final newOffset =
      -center * clampedScale +
      Offset(viewportSize.width / 2, viewportSize.height / 2);

  viewController.animateZoomAndPanTo(
    targetOffset: newOffset,
    targetZoom: clampedScale,
    duration: animationDuration ?? const Duration(milliseconds: 400),
    curve: curve,
  );
}