fitToContent method

  1. @override
void fitToContent()
override

Automatically adjusts the view (scale and origin) to fit all items within the viewport.

Implementation

@override
void fitToContent() {
  if (!mounted) return;
  final canvasSize = context.size;
  if (canvasSize == null) return;

  final boundaryPoints = <Offset>[];
  for (final item in widget.items) {
    if (item is SeriesItem) {
      for (final p in item.points) {
        boundaryPoints.add(Offset(p.x, p.y));
      }
    } else if (item is PointItem) {
      boundaryPoints.add(Offset(item.x, item.y));
    } else if (item is PolygonItem) {
      for (final v in item.vertices) {
        boundaryPoints.add(Offset(v.$1, v.$2));
      }
    }
  }
  for (final widgetItem in widget.widgetItems) {
    boundaryPoints.add(Offset(widgetItem.x, widgetItem.y));
  }

  if (boundaryPoints.isEmpty) {
    resetView();
    return;
  }

  final xValues = boundaryPoints.map((p) => p.dx);
  final yValues = boundaryPoints.map((p) => p.dy);
  final minimumX = xValues.reduce(min);
  final maximumX = xValues.reduce(max);
  final minimumY = yValues.reduce(min);
  final maximumY = yValues.reduce(max);

  final rangeX = maximumX - minimumX;
  final rangeY = maximumY - minimumY;
  const marginRatio = 0.18;

  final computedScaleX = rangeX > 1e-10
      ? (canvasSize.width * (1 - 2 * marginRatio)) / rangeX
      : double.infinity;
  final computedScaleY = rangeY > 1e-10
      ? (canvasSize.height * (1 - 2 * marginRatio)) / rangeY
      : double.infinity;

  final calculatedNewScale = min(
    computedScaleX,
    computedScaleY,
  ).clamp(0.00001, 5000000.0);
  final centerX = (minimumX + maximumX) / 2;
  final centerY = (minimumY + maximumY) / 2;

  setState(() {
    currentScale = calculatedNewScale;
    currentOrigin = Offset(
      canvasSize.width / 2 - centerX * calculatedNewScale,
      canvasSize.height / 2 + centerY * calculatedNewScale,
    );
  });
}