The changes to fit all nodes in the visual boundary were made in the **`signals`** section, specifically in the definitions of `xdom` and `ydom`, with the addition of four new signals to calculate the data extent.
Here are the exact changes, broken down:
### 1\. New Signals Added:
Four new signals were added to the `signals` array to calculate the minimum and maximum `x` and `y` coordinates of the rendered tree nodes.
```json
{
"name": "minX",
"update": "data('treeLayout') ? min(data('treeLayout').map(d => d.x)) : null"
},
{
"name": "maxX",
"update": "data('treeLayout') ? max(data('treeLayout').map(d => d.x)) : null"
},
{
"name": "minY",
"update": "data('treeLayout') ? min(data('treeLayout').map(d => d.y)) : null"
},
{
"name": "maxY",
"update": "data('treeLayout') ? max(data('treeLayout').map(d => d.y)) : null"
}
```
* `minX` and `maxX`: Find the minimum and maximum `x` values from the `treeLayout` data.
* `minY` and `maxY`: Find the minimum and maximum `y` values from the `treeLayout` data.
### 2\. Changes to `xdom` signal:
The `update` expression for `xdom` was changed to dynamically set the domain on initial load.
Original `xdom`:
```json
{
"name": "xdom",
"update": "slice(xext)",
"on": [ ... ]
}
```
Modified `xdom`:
```json
{
"name": "xdom",
"update": "startingDepth >= 0 ? [minX - nodeWidth / 2, maxX + nodeWidth / 2] : (slice(xext))",
"on": [ ... ]
}
```
* **The new part**: `"startingDepth >= 0 ? [minX - nodeWidth / 2, maxX + nodeWidth / 2] : ..."`
* This is a conditional statement. It checks if the `startingDepth` signal is greater than or equal to `0`. This condition is only true during the initial rendering when the tree is first created.
* If the condition is true, it sets the domain of the x-axis to `[minX - nodeWidth / 2, maxX + nodeWidth / 2]`. This uses the calculated bounding box (`minX`, `maxX`) and adds some padding (`nodeWidth / 2`) to ensure the nodes aren't cut off at the edges.
* If the condition is false (after the initial render, when `startingDepth` becomes `-1`), the signal reverts to its original behavior, allowing for user-controlled panning and zooming (`slice(xext)`).
### 3\. Changes to `ydom` signal:
The `update` expression for `ydom` was changed in a similar way.
Original `ydom`:
```json
{
"name": "ydom",
"update": "slice(yext)",
"on": [ ... ]
}
```
Modified `ydom`:
```json
{
"name": "ydom",
"update": "startingDepth >= 0 ? [minY - (nodeHeight+verticalNodeGap)/2, maxY + (nodeHeight+verticalNodeGap)/2] : (slice(yext))",
"on": [ ... ]
}
```
* **The new part**: `"startingDepth >= 0 ? [minY - (nodeHeight+verticalNodeGap)/2, maxY + (nodeHeight+verticalNodeGap)/2] : ..."`
* This works just like the `xdom` change. On the initial render, it sets the y-axis domain based on the calculated bounding box (`minY`, `maxY`) and adds padding (`(nodeHeight+verticalNodeGap)/2`).
* After the initial render, it reverts to the standard panning and zooming behavior.
No comments:
Post a Comment