I have a D3.js chart similar to this. As the user drills down into the chart I utilize the bootstrap tooltip to display the nodes name. I am currently tracking the node by call the tooltip show method over and over which cause the tooltip to re-render at the new location.
setInterval(function(){
$(node).tooltip('show');
}, 100)
My concern is that calling this function like this will cause performance issues. Can anyone suggest a better way to accomplish this or give me some insights on to performance issues when using the setInterval function this way?
From your description it sounds like what you are trying to do would be better accomplished by listening for discrete changes in state rather than time. I haven't worked with D3.js, but even something as simple as listening for clicks on <circle> elements would be a ton more efficient.
JS
$('svg').on('click', 'circle', function () {
$(node).tooltip('show')
})
It looks like D3.js has it's own event framework, but I'm not sure if it supports delegation. Someone more familiar could probably provide a better suggestion to that end.
Finally, depending on how many nodes you show at once, calling tooltip show on all of them could itself generate a performance hit. Tracking which ones open and close each time by storing references could be more efficient. Again, there might be something already in D3.js to handle this, but it's not something I know.
Related
It is possible to customise nodes on a ThreeForceGraph, using APIs provided at https://github.com/vasturiano/three-forcegraph, using the method ThreeForceGraph.nodeThreeObject(...). The ... here can be a THREE.Sprite instance, and we can render any svg picture to THREE.Sprite.
However, I wish to have something more than a picture. I wish to add two clickable buttons to each node of the graph. I can do Sprite.addEventListener(...) to detect mouse click, but this is not quite the same as a button. It would be really nice if I can make each node on the graph into a React component (that would be the ideal situation).
After looking around, I haven't found any ways to implement this. Is there any ways to achieve what I described? (Of course, it does not need to be a method of Three.js.) Any examples/references are greatly appreciated.
So, apologies if this is too much of an open and beginner-like question.
I am trying to build a single page app, in which one can control a variable in two ways:
by dragging the corresponding datapoint on a D3 scatterplot chart
by setting its value with a slider
I would like the chart to update when the slider gets moved, and the slider to move when the chart is updated by dragging the data on the chart.
I have thought of handling this through:
a spaghetti tangle of events
a proxy object mediating the changes
However I'm asking myself (and the illustrious SO community) is there a better way to handle this?
The keyword for solving this is 'data binding'. There are several frameworks out there, which are able to solve this. That means, that you have a javascript model, which holds the value, you want to work with and something like a proxy, which handles changes and stuff and applies the changes to the view or respectively to the mode..
In case you might need this more often, which usually applies to single page apps, I would recommend you to use some framework, which does the work for you instead of reinventing the wheel.
If you want to stay with client based Javascript, you might take a look into Angular.js (never used it, but maaaany people do and really do like it) or Knockout.js (I work with it, but there are no more further developments).
Within the last years and now many peoply switched to Node.js and Angular2 (a further development of Angular.js) or React.js or Vue.js. You might also take a look into it, but going into detail would blow up the answer. Moreover I only know some basics right now and other people can do better and already did better.
I'm trying to do a menu of sorts with a d3.js treemap. It mostly works, but I'm having a few glitches that I can't pinpoint.
Basically, sometimes my chart doesn't zoom correctly and instead of seeing the children take the whole SVG area, they show up "unzoomed".
I suspect it must have something to do with the animation's timing vs. some data manipulation for hiding/showing the different nodes, but can't actually figure it out. Other thing I thought might be borking up the behavior relates to the click events being registered by both "parent" and "children" nodes.
I have a similar example setup in JSBIN.
So, I was wondering how I could register/unregister click events in the parent/child nodes on zoom - if that's even the problem - and also if there was a simpler or less-error prone way to change the nodes' visibility.
Any help is welcome!
Well, this might be a bit unorthodox, but I found a way to overcome this.
Basically, instead of trying to mess around with event registering/unregistering, I simply ran the zoom only if the click wasn't from the node at the current zoom level.
So, in my zoom function, I wrapped the zoom handling in an if check:
function zoom(d) {
if(node!=d){
// the rest remains the same
}
}
Either way, I still think that this was happening due to the source elements where the click events were coming from being overlapped in the SVG area - simply put, the click event was being triggered by several overlapping elements, being the first (topmost) in the SVG tree order triggered inadvertently.
Here's a working version.
Hope this helps someone else!
EDIT: This solution isn't perfect, though. Now sometimes the click just doesn't do anything - But it's better than borking the UI. If anyone has other ideas, they're welcome.
Here is my requirement:
I need to create a visualization of links between different representations of a person. The image below I think indicates that fairly clearly.
Additionally, those rectangles would also contain some data about that representation of a person (such as demographics and the place). I also need to be able to handle events when clicking on the boxes or the links between them, as a sort of management tool (so, for example, double clicking a link to delete it, or something along those lines). Just as importantly, since the number of people and links will varies, I need it to be displayed by spacing out the people in a roughly equidistant fashion like the image shows.
What would be a javascript library that could accomplish this? I have done some research and have yet not found something that can cleanly do this but I'm hardly an expert in those libraries.
Here are the ones I've looked at:
Arbor js: Can dynamically create the spacing and links of the graph but I'm responsible for rendering all the visuals and there's really no hooks for things like clicking the links.
jsPlumb: Easily create connections between elements and draws them nicely enough but doesn't seem to address any layout issues. Since I don't know how many people will be on the screen, I have to be able to space them out equidistant and that doesn't seem to be a concern of jsPlumb.
D3.js: This creates a good visualization with the spacing I need but I don't see how I can show the data inside each node or do things like like mouse events on the links or box.
I'm feeling a bit lost so I'm hoping someone could point me to something that could help me or maybe point me to an example from one of these libraries that shows me that what I want is possible.
I ended up using Arbor with Raphael as my rendering library and it's worked out very well.
Take a look at Dracula Graph Library. It's a simple library that seems to do both layout as well as rendering graphs (using Raphael under the hood). It's a bit underdeveloped however.
I'm trying to figure out how to highlight a line (series) in Highcharts from an element that's not related to the Chart object in any way.
I went through the documentation, and don't really see a way of achieving this. I can get into the series elements using the series.get(id).
Seems like there are no methods that can be helpful - http://www.highcharts.com/ref/#series-object
Any ideas if that's even possible?
After a lot of digging and testing, I've managed to get this working - still not sure if this is the best way (probably not).
Chart.series.get(someId).graph.attr('stroke-width', '5')
Unfortunately, this is just getting into the actual DOM element and changing the value of the property of a single element, so if you need to change the stroke width, and the styles of the markers on this line, you'd have to loop through all elements, and apply changes manually.
UPDATE: Ok, there's a better way
But this is using the private API, so if the library changes thins, your code will not work:
Chart.series.get(someId).onMouseOver() and Chart.series.get(someId).onMouseOut().
This actually fires the defined hover-state.