AmCharts 4 Force Directed Chart - Select Bubble by Parent -> Child Location - javascript

Using the demo chart available from the AmCharts website (here), if I know the parent Phoebe, and the child David, how can I programmatically get the David bubble?
My goal is to alter the fill of the bubble, which I can do in an event handler. I just am uncertain of how to select the element I want programmatically, given what I have to work with.
Edit: I realize that I can just traverse graph.data and modify the color attribute, but I can't call graph.invalidateRawData() as that doesn't pick up the coloring change (makes sense). I really would rather not have to force a complete graph redraw!
Thanks!

The easiest way to get a desired node would be to set id data field (it can be the same as your name field) and use series.getDataItemById method to retrieve the data item.
function changeColor(){
let dataItem = networkSeries.getDataItemById(networkSeries.dataItems, "Fifth");
dataItem.node.circle.fill = am4core.color("#00ff00");
// change color of all children
dataItem.children.each(function(child){
child.node.circle.fill = am4core.color("#00ffff");
})
}
Here is a demo:
https://codepen.io/team/amcharts/pen/mZMYKx
The demo also illustrates how access and change color of all children of the data item.

Related

How do I get node data by clicking a node in the diagram?

I'm making a dynamic genogram in GoJS, where I want to be able to click a parent node, click a button in HTML that adds the child and links it to the parents. For this I need to be able to get the key from the parent node by clicking on it in the diagram.
I was thinking I'd have to use the addDiagramListener() function but I think that function is only for changes in appearance of the node e.g. changing the color of the node on click and not for getting node data.
You have several options. The two most common are to implement a "ChangedSelection" Diagram event, and looking at all selected nodes (or just the first one: myDiagram.selection.first()) and inspecting the node.data or just node.key (which is a shortcut for node.data.key)
And to do something similar on each individual node by setting selectionChanged on your Node template. This function will be called every time a given node is selected or deselected.
There's a simple live example of selectionChanged being used here: https://gojs.net/latest/intro/selection.html#SelectionAppearanceChanges

Chart does not reflect active entries unless I set it to array.slice() in the markup -- this will disable selecting points - Stackblitz inside

On the line chart there is the select event where you can select points & legend items.Line chart has activeElements input property which takes an array of the active elements.
Line chart will not react to changes to the activeElements array unless you enter it in the markup using .slice() either as a local variable OR redux state object:
[activeEntries]="array.slice()"
[activeEntries]="(array | async).slice()"
This works but then the (select) event is not triggered when you click on points anymore.
If you however remove .slice() -- you will be able to select both -- but the chart will no longer react to activeEntries changes no matter what.
This includes having the activeEntries a redux state object where the whole state is a new object on each change -- calling changeDetection everywhere does not affect it at all.
Here's a stackblitz:
https://stackblitz.com/edit/angular-ngx-charts-testing-stuff?file=src/ -- stackblitz.
I have commented the code & markup everywhere so you can understand what I'm trying to do in the code.
I'd like to be able to click on points + legend when using .slice() or have the chart react to changes to activeEntries array.
It actually takes a whole lot more to highlight the active entries and it was purely a coincidence that calling .slice worked at all.
What I needed wasn't actually a feature yet.

Aurelia JS - multi level binding/update?

I'm not sure whether I'm using the right terminology here - but here is an example:
https://gist.run/?id=57ed46429e4583eb4c3fb11814451a55
This is how it looks like in Chromium:
Basically, the entries on top (red outline) are a visualization of an array as the "first-level" data display; here one can toggle each element's selection, and make a multi-element selection (red background). The array that is the source of the "first-level" display is mydata in first-level-items.js.
Those items that are selected in "first-level", are then shown again in "second-level" (green outline); here the same information of name and value is displayed, although a bit differently. Here also one can toggle an elements selection - but only one "second-level" element can be selected. The array that is the source of the "second-level" display is myseldata in second-level-items.js.
The intent here, is that once a "second-level" selection has been made, a slider appears, to change the .value property of the particular object which is the selected array element.
My original question (which is why I started this post/example at all), was:
How do I ensure that whenever the slider is changed, the value is updated in both second-level and first-level display?
... however, for reasons beyond me, this in fact does work somewhat in this gist.run example (but it still doesn't work in my actual project, which forced me to come up with the example to begin with). Also it only works somewhat, in the sense that when loading the example page at first, after making first and second level selections, and then changing the slider, the .value will be updated in both first- and second-level display. But as soon as I try deselecting on second level - or changing the selection on second level - then updating stops. So, I guess this question still stands...
After a second-level selection has been made, deselecting on second level (by clicking to toggle) does NOT remove the slider; how can I have it behave like that?
The update happens only on the slider's onChange - basically, while you drag and slide, this component emits onSlide, but it will generate onChange only at the end when the mouse is released (that is, when the sliding has stopped). How can I update both first- and second- level display while the slider is sliding?
And finally - is this how this kind of a problem is best addressed in Aurelia? That is - I currently have one array in first-level-items.js; first-level-items.js then has a singleton reference to second-level-items.js, so it can call a method within it, to change a filtered copy of the array on the second level, which then serves as a source both for second-level display and the slider... Is there a better way to organise this?
Boy, this was a pain, but here's what I think is the solution:
https://gist.run/?id=c09fea3b82a9ebc41e0a4c90e8665b04
Here are some notes:
Apparently, there is something wrong applying if.bind or show.bind on the input element of the slider - instead, the input element should be put in an enclosing div, and the div should have if/show.bind applied
Furthermore, if.bind should not be used, as it re-instantiates the slider element - use show.bind so we can get a reference to the slider widget at start already, even if it is hidden
Seemingly, using TaskQueue in attached() is the only way to get a reference to the slider at start
Once we have a reference to the widget, re-apply it on each second level element, whenever they change
Do not set this.myselChanging to null to specify no target of the slider (simply count on hiding the slider appropriately)
For a continuous change (onSlide), simply use this.myselChanging.value = e.value; in the handler - both first-level and second-level values will be changed
Beyond this, it seems arrays are copied by reference, so the multi-level update happens without further intervention...
Though, would still love to know what is the proper way to do this...

Add a click event to the bar chart of chartjs

Is it possible to identify the exact segment that is clicked on in a bar chart? I've three "bars" in the chart. When I click on a particular bar, I'm calling the getBarsAtEvent() to see which particular portion of the bar is called. But getBarsAtEvent() is returning an array of all the data points in that bar. I need to know which exact portion is clicked. Is there anyway to achieve this?
Try using the event parameter. Every function called by your webpage has an event object as the last parameter.
You can read more about the event object here
I suspect you would use something like event.target to get the specific node you clicked on.

Paper.js - Get first ''selected item'' from selectedItems

I'm trying my way around building a graphics editor with Paper.js
I would like to select the first(1st) element that was picked using a selection tool(either Shift+Click, or dragging a selection box). Direct-click detection is done via hit-testing and selection box via getIntersection
If it's Shift+Click its the first selected element. Which element was clicked is found with HitResult
If its selectionBox, the first intersection? result of the selection box.
Is it possible to get this?
I do a FOR loop to get all the elements in the Paper.js selectedItems array which returns all the selected items on the canvas.
I've tried this:
var selected = paper.project.selectedItems;
var firstSelected = selected[0];
but this doesn't return what i need.
The above code snippet fetches an array that is agnostic to which element was selected first. It simply orders the selectedItems in the array starting from the ''oldest drawn path''.
What i need is a way to find out which is the 1st element that was selected.
Either the 1st that get's ''touched(intersected)'' with the selection
rectangle
Or the first that was clicked while in Shift+Click
functionality(Select more than one element with click).
The reason for this is that i would like to add to my editor, align-relative-to functionality.
In order to have a correct UX, the user must have the ability to align an element relative to another that he sets as the ''reference item''. Therefore i need to know the 1st element selected relative to others in order to use it as the ''reference item''.
Any ideas ?
Here is a working example of what I understood you want to achieve for the selection (without the align-relative-to functionality).
And here is the code (under SelectPaperJS) https://c9.io/arthursw/oiio/
It should not be too hard to make something similar on Stylii (since you're using it).
You can have an array to keep track of the order of selection of your items. For example in the mousedown function of the direct select tool (from line 789 of editor.js) you can add the newly selected element to this array (line 800). Same thing when you select with the rectangular selection tool.

Categories

Resources