Open hasyee opened 6 years ago
@jayhasyee assuming the data looks something like:
const myData = {
name: "root"
children: [
{
name: "leafA",
value: 3
},
{
name: "nodeB",
children: [
{
name: "leafBA",
value: 5
},
{
name: "leafBB",
value: 1
}
]
}
]
}
you can pass one of the (nested) data nodes as function argument, i.e.:
myChart.focusOnNode(myData.children[1].children[0])
This is only necessary if you wish to zoom programatically on a node triggered by a custom event. The click-to-zoom functionality is already included by default, and call the above method internally.
Thanks! Is there any way to listen the node click event? As I see, not. I use this now:
document.querySelectorAll('g.slice').forEach(g => {
g.addEventListener('click', () => {
const node = myChart.focusOnNode();
// do something
});
});
But it would be useful if it had. Something like this:
Sunburst()
.data(data)
.onNodeClick(node => { ... })
...
or just an .on
method with two arguments: .on('nodeClick', node => {...})
, which is can be used for other events later.
@jayhasyee good suggestion. I added a new event handler: onNodeClick(node)
to allow the scenario you described. If that method is overriden, the chart will no longer automatically focus on clicked nodes, so you'd have to do something like the following to maintain that behavior:
myChart
.onNodeClick(node => {
myChart.focusOnNode(node);
// do other operations with node
})
Please try with the latest release (1.2.0
) and let me know if this works for you.
First, thanks for your improve :)
I think focusOnNode
and onNodeClick
should work independently from each other.
https://github.com/vasturiano/sunburst-chart/blob/master/src/sunburst.js#L161
So instead of this:
.on('click', d => {
d3Event.stopPropagation();
(state.onNodeClick || this.focusOnNode)(d);
})
something like this:
.on('click', d => {
d3Event.stopPropagation();
this.focusOnNode(d);
state.onNodeClick(d);
})
Or
instead of onNodeClick
event, an onNodeSelect
event should be more generally. The onNodeSelect
is fired even a user click a slice or even a developer call the focusOnNode
programatically. In this case onNodeSelect
should be fired within focusOnNode
after this line: https://github.com/vasturiano/sunburst-chart/blob/master/src/sunburst.js#L36
What do you think?
@jayhasyee thanks. The reasoning for exposing (and overriding) the click behavior is that it's the only way (at least without further complicating the module's config) to allow the consumer to cancel the "click-to-focus" functionality, if wanted, since that is just a convenience automatic binding which can be reproduced externally.
As for triggering onNodeSelect
whenever focusOnNode
is called programmatically, that could lead to infinite event loops depending on the consumer's implementation, so I'd rather avoid it. In any case, it can be detected and fully controlled externally with the current api.
Basically, the choice was so to keep the api as simple as possible without imposing any functionality limitations on the consumer.
Thanks again for bringing it up though!
I am having trouble using the focusOnNode
method to programatically update the sunburst chart.
My data looks like:
this.chart_data = { // reduced in size for example's sake
"name": "node1",
"is_node": true,
"uuid": "315d139cecb342ba80a4737a2e0d81c0",
"color": "#2196F3",
"size": 4,
"children": [
{
"name": "node2",
"is_node": true,
"uuid": "b5a03196bc3c4070b775bc59452d63bd",
"color": "#2196F3",
"size": 4,
"children": [
{
"name": "leaf1",
"is_leaf": true,
"uuid": "26bbb42cb1b9482b9a0d3bb6770f078e",
"color": "#1EBE78",
"size": 2
},
{
"name": "leaf2",
"is_leaf": true,
"uuid": "e4bf91d78ae041e7b821f10479897d24",
"color": "#1EBE78",
"size": 2
},
{
"name": "leaf3",
"is_leaf": true,
"uuid": "7e922d5bf781460aa6cf7026fe99863c",
"color": "#1EBE78",
"size": 2
},
{
"name": "leaf4",
"is_leaf": true,
"uuid": "c1e491ffc88a40cab8d294186ded4daa",
"color": "#1EBE78",
"size": 2
}
]
},
{
"name": "leaf5",
"is_leaf": true,
"uuid": "0fbe5c99aad2433187ee518f3741b7e1",
"color": "#1EBE78",
"size": 2
},
{
"name": "leaf6",
"is_leaf": true,
"uuid": "aa0ca66d3f4e478c9a46f6e7a0577481",
"color": "#1EBE78",
"size": 2
}
]
}
and I am using the following to programmatically find a node (from an outside selection) and select it in the sunburst chart
findChartNode(chart_node, node_uuid) {
if (chart_node.uuid === node_uuid) {
return chart_node;
}
if (chart_node.children) {
for (let i = 0; i < chart_node.children.length; i++) { // depth first search
let child_ret = this.findChartNode(chart_node.children[i], node_uuid);
if (child_ret) {
return child_ret;
}
}
}
return null;
}
this.hierarchySunburstChart.focusOnNode(this.findChartNode(this.chart_data, this.selected_node_id))
When I print out what the findChartNode
function returns, it finds what it is supposed to, but the call to focusOnNode
causes the sunburst chart to vanish.
I'm not sure what is going on, because that looks like what you said to do up above.
I am using version 1.2.2 with angular 5 on Chrome.
@cjkirk09 the focusOnNode
method was expecting an internal hierarchical node instead of an external data node, which was incorrect. I've fixed this. Please try your example with v1.3.0
, it should be working. Let me know if you run into any issues.
@vasturiano That did the trick. Thanks for the speedy response!
@vasturiano with a similar structure to cj, how would I be able to focus on root node automatically after creation binding it to a variable to display information.
I am programatically doing stuff when a new node is in focus and need it to focus on startup.
For instance when I click on a child / slice I save that node to a variable and I'll display further information about it, would just like to do that on sunburst creation for root node
// this is how im handling each event after initial load
this.sunburstChart
.onNodeClick((node) => {
this.sunburstChart.focusOnNode(node);
// do other operations with node
this.clickedNode = node;
});
@JP-Basson to reset the zoom to the root node, just pass null
to focusOnNode:
sunburstChart.focusOnNode(null)
@vasturiano Think I can better explain my question now.
Is there anyway on load to get .onNodeClick((node))
That node information being generated by on click, is there anyway to get that information pre click? on load of the sunburst? As I'd like to populate the root node info on the side screen when it's generated
@JP-Basson I'm not sure I understand the intent. By 'on load' do you mean initialization? Also, the root node info should be available when clicking on the root node itself.
Could you please describe a bit more in detail the issue you're having?
@vasturiano Yeah, on initialisation I would like to get the root node info without clicking on it. Is that possible?
@JP-Basson if you don't need it based on user interaction, you should be able to read that info directly from the data
object that you pass into the chart.
You can even request it from the chart itself:
const rootData = myChart.data();
@cjkirk09
How did you managed to integrate the sunburt-chart
with Angular 5?
@cjkirk09 How did you managed to integrate the
sunburt-chart
with Angular 5?
Here is a working solution with Angular 9 https://stackoverflow.com/questions/60541172/integrate-vasturiano-sunbrust-chart-with-angular-2-9/60544969#60544969
is it possible to provide a start and end angle for the sunburst-graph? I would like to make it semi-circle!
How can I use
focusOnNode
method. From the README it's not clear. Can I catch the click event on nodes?