The d3 force layout central node positioning - javascript

I have use the d3.js to visualize my data. And the result like this.
PIC_1
PIC_2
My question is how can I make the data present like PIC_1,the center point local in the fixed position,and the other points (children points) around the center point like a circle.
Now,when I refresh the page the data will reload in the brower and all the points' position will randomly change as well.
So which d3's api or tricks can be used to this purpose. :)

Take a look at this example:
link to jsfiddle
If you exampne the code, and play with layout, you'll see that the root node has special treatment that makes it always remain in the center of the graph (unless you drag it, but even that you can prevent if you want).
On initialization, its property fixed is set to true, so that d3 force layout simulation doesn't move it. Also, it is placed in the center of rectangle containing layout:
root.fixed = true;
root.x = width / 2;
root.y = height / 2;
You ofcourse need to change or add some code in order to integrate this feature to your example, but the core idea is really clear from the example I linked.
Hope this helps. Let me know if you have a question, need a clarification, etc.

Related

Cytoscape for Angular (Node) - Horizontal Scaling Issues

I am new to this forum and Cytoscape.JS in general - please bear with me!
I have an application I am developing inside of Angular using the Node Cytoscape.JS package. The cy graph is rendered within an angular card - the card is 50% of the width of the screen, but the Cytoscape element inside is allowed to take up the entirety of the card contents.
I have a dataset with a few hundred nodes using the "cose" layout. The issue we have is the rendered graph only shows up as a column inside the center of the card, taking maybe 50% of the available space (center justified). If I grab the graph render and slide it, it'll move into the open space, so I know that Cy is able to access it.
The hope is to get the graph to spread itself, widthwise, to fill the entire space it is allowed - then from there span down past the lower boundaries of the card (into the scroll area). Doing some research, I found that the "spread" layout may be a better direction to go, but after installing the package and setting up the required elements, I was met with nothing but errors. If anyone can help me with that, I'm open as well!
Currently we are trying to manipulate the layout object to fit 100% width - that object is below. Nothing in CSS or JS has made a difference. If anyone has ideas please let me know! Thank you!
cy = cytoscape({
container: cy_container,
elements: this.elements,
layout: {
name: 'cose',
// rankDir: 'LR',
directed: true,
padding: 0
},
style: this.styleSheet,
});

How do I prevent nodes from overlapping

How do I prevent nodes in a graph from stacking on each other? I want there to be a minimum distance between nodes and if someone was to drag a node over another the graph throws an error to the user. I saw this solution and tried it but it doesnt work Prevent node overlap in JGraphX
I'll appreciate any ideas.
For rearranging your diagram automatically with some distance between them you can try to use something like this:
let layout = new mxHierarchicalLayout(this.graph, mxConstants.DIRECTION_WEST);
layout.intraCellSpacing = 50; //horizontal
layout.interRankCellSpacing = 200; //vertical
layout.execute(this.parent);
The mxHierarchicalLayout method will automatically rearrange your current nodes. The other two settings will give spacing between them ( horizontally and vertically )
Also, run this before rendering the screen or if you want to change after the display has already rendered, just this.graph.refresh() if needed

Is it possible to avoid the shrinking of Chart.js pie charts when accompanied by labels?

To get labels on Chart.js Pie and Doughnut charts, there are plugins to do so, like: chartjs-plugin-labels but after doing so I noticed a big problem for my UI design:
The size of the actual chart shrinks so that the labels fit within the canvas. It makes sense that the labels need to be able to fit within the canvas they're rendered on, and thus the shrinking of the chart. But sometimes I may use labels, and other times not, and I need my pie charts to render the same size regardless.
Is there a solution in the settings of either Chart.js (the label plugin I'm using is compatible with < 3.0, I'm using 2.9) or chartjs-plugin-labels to maintain consistent chart size, regardless of whether labels are applied?
I tried applying an empty label to every chart, but the size of the chart actually shrinks based on the specific size of the labels being rendered, so aside from being a hacky solution, it doesn't consistently solve the uniformity problem.
For example maybe a way to make charts start off taking 50% of the canvas?
Yes, this is fairly simple actually. The chartjs-plugin-labels.js file contains several lines which force the chart to become smaller when the label settings set the position to either "border" or "outside". Download the script to your own server, comment out the lines below, and everything should work as expected. CodePen demo
Comment/remove these lines:
if (this.options.position === 'border') {
offset = (lines.length - 1) * this.options.fontSize / 2;
}
if (label.options.position === 'outside') {
someOutside = true;
var padding = label.options.fontSize * 1.5 + label.options.outsidePadding;
if (padding > maxPadding) {
maxPadding = padding;
}
}
Here is the updated JS file you can use: https://pastebin.com/raw/gSffqqKu
Just download it as chartjs-plugin-labels.js and use it in your project instead of the original plugin file.

Create dynamic vertical rule in d3

I want to create a vertical rule like the one shown at http://bost.ocks.org/mike/cubism/intro/demo-stocks.html that updates its value dynamically according to the user's mouse.
This demo uses cubism.js but I'd like to use d3 and/or jQuery to achieve the same effect.
Any suggestions?
EDIT: I've tried creating rules according to the ones in this thread (How to make a vertical line in HTML), but I don't know how to position it and move it according to the user's mouse position.
You need to update your question to include more detail about what you actually want, but here's one implementation using d3: http://jsfiddle.net/q3P4v/
d3.select('html').on('mousemove', function() {
var xpos = d3.event.pageX;
var rule = d3.select('body').selectAll('div.rule')
.data([0]);
rule.enter().append('div')
.attr('class', 'rule')
.append('span');
rule.style('left', xpos + 'px');
rule.select('span').text(xpos);
});
Note that this depends on some associated CSS, as shown in the fiddle.

Tracking mouse position of a jqplot vertical line chart

I want to create a jqPlot line chart which has the ability to change orientation between vertical and horizontal orientation. I was able to achieve this using CSS rules, by rotating the div element containing the chart.
My work up to now: http://jsfiddle.net/GayashanNA/A4V4y/14/
But the problem is I also want to track the mouse-pointer and mouse clicks on points on chart after the orientation is flipped because i want to annotate those points. I am unable to do this when the chart is in vertical orientation. Can anyone suggest a method to do this? Or am i approaching the problem in a wrong way?
(Note: I am able to do this in horizontal orientation, you can observe it if you try to click on a point on the above chart.)
Thanks and help is much appreciated.
I've never used jqPlot, but I guess your problem is trying to use css rotate(), since the cursor plugin is using the mouse position to determine where to draw the lines, and element's size doesn't change when transformed by rotate(), it still have the same width and height values.
If you take a look at the code, you will see:
if (c.showVerticalLine) {
c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]);
}
if (c.showHorizontalLine) {
c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]);
}
So it seems like the library is always drawing the lines based on mouse position over the original element, which of course, won't match the position after being transformed by rotate(), and XY coordinates are going to be transformed to YX after rotate().
I would try to change the size of your original element, though I don't know if the library lets you specify in which sides are the labels going to be drawn.
I finally found a solution for the problem. But i had to change jqPlot library to achieve this. To help anyone else who run in to the same problem, i'll put my solution here.
First i had to insert the following code in to the jqPlot class of the jquery.jqplot.js file, which is the core library.
function jqPlot() {
//add the following code segment
var verticallyOriented = false;
this.setVertical = function(state){
verticallyOriented = state;
}
//don't change other code that isn't mentioned here
//now you have to change the logic in the getEventPosition function
//to make sure the new orientation is detected
function getEventPosition(ev) {
//change the line starting with var gridPos = ...
//to the following code segment
//depending on the orientation the event position calculating algorithm is changed
if(verticallyOriented){
var gridPos = {x:ev.pageY - go.top , y:plot.eventCanvas._elem.height() - ev.pageX + go.left};
} else {
var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top};
}
//no change to other code is needed
}
}
You can view a working example here: http://jsfiddle.net/GayashanNA/yZwxu/
Gist for the changed library file: https://gist.github.com/3755694
Please correct me if i have done something wrong.
Thanks.

Categories

Resources