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.
Related
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.
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...
I am trying to figure out how to check whether or not a layer in KineticJS is visible. I need this in order to appropriately toggle the visibility of any given layer when the user clicks a button. If it's visible, I want to hide it when they click the button. If it isn't visible, then I want to show it. Thoughts? I saw that there is a isVisible function, but nothing at all happens when I try to use it on a layer. The below code doesn't error, but it isn't doing anything. This is written in KineticJS on Angular. In my tests, I found that this event is appropriately getting triggered, so it's not that. I also found that the draw function is appropriately firing.
scope.$on('layertoggle', function(event){
var layerShapes = scope.kineticStageObj.get('#layer1');
if(!layerShapes.isVisible()){
layerShapes.hide();
}
else{
layerShapes.show();
}
scope.kineticStageObj.draw();
});
Try this:
var layerShapes = scope.kineticStageObj.get('#layer1')[0];
get returns a collection of shapes that match that criteria. Despite id being unique, you still have to access the first position of the array to access the desired shape.
I am building a table where when cell is clicked high charts is shown in its place(same way as flip cards). And when highchart is clicked a cell is reverted back it is original state.
However, after creating a chart dynamically all my click functions on a parent stop working when clicking on a chart directly.
I have created this small jsFiddle to demonstrate my problem:
http://jsfiddle.net/2j4qQ/2/
Code:$('#contentDiv').on('click', '.homepageChart', function() {});
$('#contentDiv').on('click', '.homepageChart', function() {});
This function does not fire when clicking directly on a chart. Why? and how can it be
Thanks in advance.
Have a look at this: jsfiddle.net/cssimsek/4Wa32/1. Since you were appending the Highcharts <div> with each click I added the .detach() method to the callback function of the .hide()method, in order to remove the <div> on secondary clicks. It seems to be working ok now.
I have added an overlay with z-index:1; to my highcharts which seems to solve the problem. However, this seems incorrect, since i should be able to listen to dynamically created highcharts events. If anyone has some info on this please share.
Here is updated fiddle:
http://jsfiddle.net/2j4qQ/5/
I have a Protovis graph that responds to pan/zoom events like the sample on the website, which covers the Panel that holds the graph with an empty one. Unfortunately it captures all Events like mouseover and mouseout which my underlying graph usually responds to.
This is because you have to set the Panel to accept all events. According to the docs the only valid params for this are 'all', 'painted' and 'none'
vis.add(pv.Panel)
.events("all")
How can I prevent the zoom Panel from capturing these events? Or how can I pass them through to the Panel below it?
I don't think this is necessarily the answer you want, but as far as I can tell there's no easy way to pass events through to lower elements. However, if your graph is similar to the example, you can simply change the order of the invisible Panel and the marks that should receive events, from:
vis.add(pv.Dot)
.event('click', function() { alert("clicked") })
// ... etc
vis.add(pv.Panel)
.events("all")
// ... etc
to:
vis.add(pv.Panel)
.events("all")
// ... etc
vis.add(pv.Dot)
.event('click', function() { alert("clicked") })
// ... etc
This will change the z-order of the marks, so that the dots receive click events before the panel. It's a little less plug-and-play, as you have to insert the panel at the correct point in your existing graph, but it should work.
You can see a jsFiddle based on the example here: http://jsfiddle.net/nrabinowitz/Ctxrr/
EDIT: Per the comment below, this approach can be a problem for zoom events. The better approach, shown in this updated fiddle, is to make the invisible Panel the parent of the marks in question - events will automatically bubble up from child to parent, and if the child doesn't set a listener for an event, it won't interfere with the parent. So as long as all foreground marks that need to receive events are children of the pan/zoom Panel, this should work.