paint method

  1. @override
void paint(
  1. Canvas canvas,
  2. Offset screenOffset,
  3. Offset canvasOffset,
  4. double scale,
  5. Size canvasSize,
)
override

draw the backround on this context. Implement this to have different kinds of backgrounds screenOffset is the screen space offset for clipping canvasOffset is the grid space offset from the controller

Implementation

@override
void paint(
  Canvas canvas,
  Offset screenOffset,
  Offset canvasOffset,
  double scale,
  Size canvasSize,
) {
  // Fill background
  final rect = Rect.fromLTWH(
    screenOffset.dx,
    screenOffset.dy,
    canvasSize.width,
    canvasSize.height,
  );
  final bgPaint = Paint()
    ..color = backgroundColor
    ..style = PaintingStyle.fill;
  canvas.drawRect(rect, bgPaint);

  // Early out if dots are too dense or too small
  final spacingSS = (spacing * scale).abs();
  final radiusSS = (size * scale).abs();
  if (spacingSS < 1.0 || radiusSS < 0.25) {
    return; // background already drawn
  }

  final dotPaint = Paint()
    ..color = dotColor
    ..style = PaintingStyle.fill;

  // Choose pan semantics
  final sign = naturalPan ? 1.0 : -1.0;

  // Determine visible grid-space bounds to iterate
  // Screen rect spans [screenOffset, screenOffset + canvasSize]
  // xSS = screenOffset.x + (xGS - sign*canvasOffset.x) * scale
  // Solve for xGS bounds to cover the screen rect (+radius margin)
  final marginGSX = radiusSS / scale;
  final marginGSY = radiusSS / scale;

  final xGsMin = sign * canvasOffset.dx - marginGSX;
  final xGsMax =
      sign * canvasOffset.dx + (canvasSize.width + 2 * radiusSS) / scale;
  final yGsMin = sign * canvasOffset.dy - marginGSY;
  final yGsMax =
      sign * canvasOffset.dy + (canvasSize.height + 2 * radiusSS) / scale;

  int nStartX = (xGsMin / spacing).floor();
  int nEndX = (xGsMax / spacing).ceil();
  int nStartY = (yGsMin / spacing).floor();
  int nEndY = (yGsMax / spacing).ceil();

  // Iterate grid and draw circles
  for (int nx = nStartX; nx <= nEndX; nx++) {
    final xGS = nx * spacing;
    final xSS = screenOffset.dx + (xGS - sign * canvasOffset.dx) * scale;
    if (xSS + radiusSS < rect.left || xSS - radiusSS > rect.right)
      continue; // skip out-of-bounds columns

    for (int ny = nStartY; ny <= nEndY; ny++) {
      final yGS = ny * spacing;
      final ySS = screenOffset.dy + (yGS - sign * canvasOffset.dy) * scale;
      if (ySS + radiusSS < rect.top || ySS - radiusSS > rect.bottom)
        continue; // skip out-of-bounds rows

      canvas.drawCircle(Offset(xSS, ySS), radiusSS, dotPaint);
    }
  }
}