diff --git a/CHANGELOG.md b/CHANGELOG.md
index a22ea63..89323e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
## 1.0.0
- Initial release
+
+## 1.0.1
+
+- Update README
+
+## 1.0.2
+
+- Again update README ( -\_-)
diff --git a/README.md b/README.md
index 90550fa..d5597ad 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,12 @@
Infinite zoomable, pannable 2D canvas using spatial hash for only rendering what's visible.
+Example: https://infinite-lazy-grid.pages.dev/
+
+
+
+
+
## Quick Start
```dart
@@ -18,7 +24,7 @@ class _DemoCanvasState extends State {
// all interactions go through the controller
final controller = LazyCanvasController(
background: const DotGridBackground(),
- debug: true // wrapps each child with debug info visible on screen (positions, id)
+ debug: true, // wraps each child with debug info visible on screen (positions, id)
);
@override
@@ -28,6 +34,13 @@ class _DemoCanvasState extends State {
for (int i = 0; i < 50; i++) {
controller.addChild(
Offset((i % 10) * 140.0, (i ~/ 10) * 140.0),
+ Container(
+ width: 100,
+ height: 100,
+ color: Colors.primaries[i % Colors.primaries.length],
+ alignment: Alignment.center,
+ child: Text('${i + 1}', style: const TextStyle(color: Colors.white)),
+ ),
);
}
}
@@ -51,6 +64,7 @@ class _DemoCanvasState extends State {
// one child, returns its id which is just a uuid string
CanvasChildId oneChild = controller.addChild(
const Offset(500, 1200),
+ const Icon(Icons.place, size: 32),
);
// with custom widget
@@ -115,13 +129,13 @@ LazyCanvasController(
);
```
-### Widet updates
+### Widget updates
-Since the args aren't directly available for you to place in the build tree. Child rebuilds can be handled in three ways:
+Since the args aren't directly available for you to place in the build tree, child rebuilds can be handled in three ways:
-1. _Stateful widget child_: Child handles it's own updates but state is lost when unmounted.
-2. _Manual update_: `updateChildWidget(id, newWidget)`.
-3. _Child listens to external state_: Some `Listenable` or some state management library like `Provider` etc that rebuild child when data changes.
+1. Stateful widget child: Child handles its own updates but state is lost when unmounted.
+2. Manual update: `updateChildWidget(id, newWidget)`.
+3. Child listens to external state: Some `Listenable` or a state management library like Provider, etc., that rebuilds the child when data changes.
### Size based optimisations
diff --git a/demo.gif b/demo.gif
new file mode 100644
index 0000000..1173b75
Binary files /dev/null and b/demo.gif differ
diff --git a/example/README.md b/example/README.md
index 887b2a7..29dc254 100644
--- a/example/README.md
+++ b/example/README.md
@@ -1,8 +1,8 @@
# Demos
-Contains 4 small focused demos.
+Contains four small, focused demos.
-- `Simple Example` – minimal setup, add nodes, pan, zoom, focus.
-- `Build Counts Example` – shows build / culling behavior; watch console for build counts.
-- `Widget State Updates Example` – three patterns for dynamic / reactive child content.
-- `Render Callbacks Example` – logs enter / exit render area callbacks and overlays debug info.
+- Simple Example – minimal setup, add nodes, pan, zoom, focus.
+- Build Counts Example – shows build/culling behavior; watch console for build counts.
+- Widget State Updates Example – three patterns for dynamic/reactive child content.
+- Render Callbacks Example – logs enter/exit render area callbacks and overlays debug info.
diff --git a/lib/core/background.dart b/lib/core/background.dart
index 63bd207..0404be1 100644
--- a/lib/core/background.dart
+++ b/lib/core/background.dart
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'dart:ui' as ui show FragmentProgram; // for runtime shader
-import 'package:flutter/rendering.dart' show RendererBinding; // to mark repaint after async load
+import 'package:flutter/rendering.dart'
+ show RendererBinding; // to mark repaint after async load
/// Abstract definition for a [LazyCanvas] background.
abstract class CanvasBackground {
@@ -12,26 +13,53 @@ abstract class CanvasBackground {
/// different kinds of backgrounds
/// [screenOffset] is the screen space offset for clipping
/// [canvasOffset] is the grid space offset from the controller
- void paint(Canvas canvas, Offset screenOffset, Offset canvasOffset, double scale, Size canvasSize);
+ void paint(
+ Canvas canvas,
+ Offset screenOffset,
+ Offset canvasOffset,
+ double scale,
+ Size canvasSize,
+ );
}
class NoBackground extends CanvasBackground {
const NoBackground();
@override
- void paint(Canvas canvas, Offset screenOffset, Offset canvasOffset, double scale, Size canvasSize) {}
+ void paint(
+ Canvas canvas,
+ Offset screenOffset,
+ Offset canvasOffset,
+ double scale,
+ Size canvasSize,
+ ) {}
}
-class SingleColorBackround extends CanvasBackground {
- const SingleColorBackround(Color backgroundColor) : super(bgColor: backgroundColor);
+class SingleColorBackground extends CanvasBackground {
+ const SingleColorBackground(Color backgroundColor)
+ : super(bgColor: backgroundColor);
@override
- void paint(Canvas canvas, Offset screenOffset, Offset canvasOffset, double scale, Size canvasSize) {
+ void paint(
+ Canvas canvas,
+ Offset screenOffset,
+ Offset canvasOffset,
+ double scale,
+ Size canvasSize,
+ ) {
final paint = Paint()
..color = bgColor
..style = PaintingStyle.fill;
- canvas.drawRect(Rect.fromLTWH(screenOffset.dx, screenOffset.dy, canvasSize.width, canvasSize.height), paint);
+ canvas.drawRect(
+ Rect.fromLTWH(
+ screenOffset.dx,
+ screenOffset.dy,
+ canvasSize.width,
+ canvasSize.height,
+ ),
+ paint,
+ );
}
}
@@ -59,18 +87,21 @@ class DotGridBackground extends CanvasBackground {
static void _ensureProgramLoaded() {
if (_program != null || _programFuture != null) return;
try {
- _programFuture = ui.FragmentProgram.fromAsset('packages/infinite_lazy_grid/shaders/dot_grid.frag')
- ..then((p) {
- _program = p;
- // Request a repaint when shader becomes available
- try {
- for (final renderView in RendererBinding.instance.renderViews) {
- renderView.markNeedsPaint();
- }
- } catch (_) {}
- }).catchError((_) {
- // keep _program null; we'll fallback to CPU/simple paint
- });
+ _programFuture =
+ ui.FragmentProgram.fromAsset(
+ 'packages/infinite_lazy_grid/shaders/dot_grid.frag',
+ )
+ ..then((p) {
+ _program = p;
+ // Request a repaint when shader becomes available
+ try {
+ for (final renderView in RendererBinding.instance.renderViews) {
+ renderView.markNeedsPaint();
+ }
+ } catch (_) {}
+ }).catchError((_) {
+ // keep _program null; we'll fallback to CPU/simple paint
+ });
} catch (_) {
// fromAsset may throw synchronously on unsupported platforms
_programFuture = null;
@@ -79,12 +110,23 @@ class DotGridBackground extends CanvasBackground {
}
@override
- void paint(Canvas canvas, Offset screenOffset, Offset canvasOffset, double scale, Size canvasSize) {
+ void paint(
+ Canvas canvas,
+ Offset screenOffset,
+ Offset canvasOffset,
+ double scale,
+ Size canvasSize,
+ ) {
// Always draw background fill (also serves as fallback while shader loads)
final bgPaint = Paint()
..color = backgroundColor
..style = PaintingStyle.fill;
- final rect = Rect.fromLTWH(screenOffset.dx, screenOffset.dy, canvasSize.width, canvasSize.height);
+ final rect = Rect.fromLTWH(
+ screenOffset.dx,
+ screenOffset.dy,
+ canvasSize.width,
+ canvasSize.height,
+ );
// Ensure shader load started
_ensureProgramLoaded();
@@ -103,8 +145,14 @@ class DotGridBackground extends CanvasBackground {
// Phase to align grid with world origin under pan/zoom
double modPositive(double a, double m) => ((a % m) + m) % m;
final sign = naturalPan ? 1.0 : -1.0;
- final phaseXPx = modPositive(sign * canvasOffset.dx * scale, scaledSpacingPx == 0 ? 1 : scaledSpacingPx);
- final phaseYPx = modPositive(sign * canvasOffset.dy * scale, scaledSpacingPx == 0 ? 1 : scaledSpacingPx);
+ final phaseXPx = modPositive(
+ sign * canvasOffset.dx * scale,
+ scaledSpacingPx == 0 ? 1 : scaledSpacingPx,
+ );
+ final phaseYPx = modPositive(
+ sign * canvasOffset.dy * scale,
+ scaledSpacingPx == 0 ? 1 : scaledSpacingPx,
+ );
// Snap origin: use exact logical origin (no rounding) to match CPU path
final originXPx = screenOffset.dx;
@@ -164,9 +212,20 @@ class DotGridBackgroundCpu extends CanvasBackground {
}) : super();
@override
- void paint(Canvas canvas, Offset screenOffset, Offset canvasOffset, double scale, Size canvasSize) {
+ 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 rect = Rect.fromLTWH(
+ screenOffset.dx,
+ screenOffset.dy,
+ canvasSize.width,
+ canvasSize.height,
+ );
final bgPaint = Paint()
..color = backgroundColor
..style = PaintingStyle.fill;
@@ -194,9 +253,11 @@ class DotGridBackgroundCpu extends CanvasBackground {
final marginGSY = radiusSS / scale;
final xGsMin = sign * canvasOffset.dx - marginGSX;
- final xGsMax = sign * canvasOffset.dx + (canvasSize.width + 2 * radiusSS) / scale;
+ 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;
+ final yGsMax =
+ sign * canvasOffset.dy + (canvasSize.height + 2 * radiusSS) / scale;
int nStartX = (xGsMin / spacing).floor();
int nEndX = (xGsMax / spacing).ceil();
@@ -207,12 +268,14 @@ class DotGridBackgroundCpu extends CanvasBackground {
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
+ 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
+ if (ySS + radiusSS < rect.top || ySS - radiusSS > rect.bottom)
+ continue; // skip out-of-bounds rows
canvas.drawCircle(Offset(xSS, ySS), radiusSS, dotPaint);
}
diff --git a/lib/core/render.dart b/lib/core/render.dart
index e77f93b..6ce7dbc 100644
--- a/lib/core/render.dart
+++ b/lib/core/render.dart
@@ -27,12 +27,6 @@ class _LazyCanvasState extends State with TickerProviderStateMixin