Skip to content

Commit

Permalink
aesthetics babbyyyyyy
Browse files Browse the repository at this point in the history
  • Loading branch information
rlch committed Jul 1, 2021
1 parent 99968b1 commit 5f1df8f
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 41 deletions.
95 changes: 59 additions & 36 deletions example/lib/screens/canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class _CanvasScreenState extends State<CanvasScreen>
late final Ticker _ticker;
late final f.ForceSimulation simulation;
late final List<f.Edge> edges;
late final List<int> edgeCounts;
int maxEdgeCount = 0;
int i = 0;

@override
Expand All @@ -28,46 +30,59 @@ class _CanvasScreenState extends State<CanvasScreen>
final size = MediaQuery.of(context).size;

final nodes = List.generate(
100,
(index) => f.Node(
x: size.width / 2,
y: size.height / 2,
),
140,
(index) => f.Node(),
);
final r = Random();
edges = [
for (final n in nodes)
if (r.nextDouble() < 0.8) ...[
for (int i = 0; i < (r.nextDouble() * 3).toInt(); i++)
for (int i = 0; i < (r.nextDouble() * 5).toInt(); i++)
f.Edge(
source: n,
target: nodes[(nodes.length * r.nextDouble()).toInt()],
),
]
];
simulation = f.ForceSimulation()

simulation = f.ForceSimulation(
phyllotaxisX: size.width / 2,
phyllotaxisY: size.height / 2,
phyllotaxisRadius: 20,
)
..nodes = nodes
// ..setForce('collide', f.Collide(radius: 10))
..setForce('collide', f.Collide(radius: 10))
// ..setForce('radial', f.Radial(radius: 400))
..setForce('manyBody', f.ManyBody())
..setForce('manyBody', f.ManyBody(strength: -40))
// ..setForce(
// 'center', f.Center(size.width / 2, size.height / 2, strength: 0.5))
..setForce(
'edges',
f.Edges(edges: edges, distance: 15),
f.Edges(edges: edges, distance: 30),
)
..setForce('x', f.XPositioning(x: size.width / 2))
..setForce('y', f.YPositioning(y: size.height / 2))
..alpha = 1;

_ticker = this.createTicker((_) {
i++;
// if (i % 10 != 0) return;
// if (i% 10 != 0) return;
setState(() {
simulation.tick();
});
})
..start();

edgeCounts = List.filled(nodes.length, 0);
for (int i = 0; i < edges.length; i++) {
final edge = edges[i];
edge.index = i;
edgeCounts[edge.source.index!] += 1;
edgeCounts[edge.target.index!] += 1;
}
for (final count in edgeCounts) {
if (count > maxEdgeCount) maxEdgeCount = count;
}
}

@override
Expand All @@ -84,6 +99,7 @@ class _CanvasScreenState extends State<CanvasScreen>

return Scaffold(
body: Container(
color: Colors.black,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: ConstrainedBox(
Expand All @@ -92,33 +108,40 @@ class _CanvasScreenState extends State<CanvasScreen>
children: [
for (final node in simulation.nodes)
if (!node.isNaN)
SimulationCanvasObject(
constraints: BoxConstraints.tight(Size(10, 10)),
node: node,
edges: [...edges.where((e) => e.source == node)],
child: NodeHitTester(
node,
onDragUpdate: (update) {
node
..fx = update.globalPosition.dx
..fy = update.globalPosition.dy;
simulation..alpha = 1;
},
onDragEnd: (_) {
node
..fx = null
..fy = null;
},
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: Colors.black,
shape: BoxShape.circle,
Builder(builder: (context) {
final double weight = maxEdgeCount == 0
? 0
: edgeCounts[node.index!] / maxEdgeCount;
return SimulationCanvasObject(
weight: weight,
constraints: BoxConstraints.tight(Size(10, 10)),
node: node,
edges: [...edges.where((e) => e.source == node)],
child: NodeHitTester(
node,
onDragUpdate: (update) {
node
..fx = update.globalPosition.dx
..fy = update.globalPosition.dy;
simulation..alpha = 0.3;
},
onDragEnd: (_) {
node
..fx = null
..fy = null;
},
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
border: Border.all(color: Colors.white),
color: Colors.white.withOpacity(sqrt(weight)),
shape: BoxShape.circle,
),
),
),
),
),
);
}),
],
),
),
Expand Down
5 changes: 4 additions & 1 deletion example/lib/widgets/simulation_canvas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ class SimulationCanvas extends MultiChildRenderObjectWidget {
class SimulationCanvasParentData extends ContainerBoxParentData<RenderBox> {
SimulationCanvasParentData({
required this.edges,
required this.weight,
required this.constraints,
});

List<Edge> edges;
double weight;
BoxConstraints constraints;
}

Expand All @@ -36,6 +38,7 @@ class RenderSimulationCanvas extends RenderBox
if (child.parentData is! SimulationCanvasParentData) {
child.parentData = SimulationCanvasParentData(
edges: [],
weight: 0,
constraints: BoxConstraints.tight(Size(0, 0)),
);
}
Expand All @@ -56,7 +59,7 @@ class RenderSimulationCanvas extends RenderBox
pd.offset + offset + edgeOffset,
Offset(edge.target.x, edge.target.y) + offset + edgeOffset,
Paint()
..color = Colors.grey
..color = Colors.grey.withOpacity(pd.weight)
..strokeWidth = 0.75,
);
}
Expand Down
6 changes: 6 additions & 0 deletions example/lib/widgets/simulation_canvas_object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ class SimulationCanvasObject
required this.node,
required this.edges,
required this.constraints,
required this.weight,
Key? key,
}) : super(child: child, key: key);

final Node node;
final List<Edge> edges;
final BoxConstraints constraints;
final double weight;

@override
void applyParentData(RenderObject renderObject) {
Expand All @@ -32,6 +34,10 @@ class SimulationCanvasObject
parentData.constraints = constraints;
}

if (parentData.weight != weight) {
parentData.weight = weight;
}

final targetObject = renderObject.parent;
if (targetObject is RenderObject) {
targetObject.markNeedsLayout();
Expand Down
12 changes: 8 additions & 4 deletions lib/src/simulation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class ForceSimulation<N extends Node> {
this.alphaTarget = 0,
double? velocityDecay,
LCG? random,
this.phyllotaxisX = 0,
this.phyllotaxisY = 0,
this.phyllotaxisRadius = 10,
}) : _velocityDecay = velocityDecay ?? 0.6,
_forces = {},
_random = random ?? LCG(),
Expand All @@ -21,8 +24,9 @@ class ForceSimulation<N extends Node> {
_initializeNodes();
}

static const _initialRadius = 10;
final double phyllotaxisRadius;
static final _initialAngle = pi * (3 - sqrt(5));
final double phyllotaxisX, phyllotaxisY;

late double alphaDecay;
double alpha, alphaMin, alphaTarget;
Expand Down Expand Up @@ -54,11 +58,11 @@ class ForceSimulation<N extends Node> {
if (node.fx != null) node.x = node.fx!;
if (node.fy != null) node.y = node.fy!;
if (node.x.isNaN || node.y.isNaN) {
final radius = _initialRadius * sqrt(0.5 + i),
final radius = phyllotaxisRadius * sqrt(0.5 + i),
angle = i * _initialAngle;
node
..x = radius * cos(angle)
..y = radius * sin(angle);
..x = phyllotaxisX + radius * cos(angle)
..y = phyllotaxisY + radius * sin(angle);
}
if (node.vx.isNaN || node.vy.isNaN) {
node.vx = node.vy = 0;
Expand Down

0 comments on commit 5f1df8f

Please sign in to comment.