I am new to D3, so my project of D3 is a rough problem to me and I really do need some help, I have been search solutions for days.
The problem is, I want to draw a Hierarchical Bar Chart, every time one clicks a bar, the sub layout of that bar is shown, just like this one http://bl.ocks.org/mbostock/1283663, however, the value of parent node is the sum value of its children node. I want to set the parent value by myself and keep the layout. The json file is:
{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
I want to edit the parent value, so I edit the file as :
{
"name": "flare",
"children": [
{
"name": "analytics",size:555555 //I want to set value by myself rather than the sum of children value
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
However, it does not work. Does anyone knows how to set parent's value? I searched for days and got nothing, hope you can help me, and I am appreciate your help!
Is your issue with using the parent element sizes to draw the bars? If so, you should scale everything (to say 0 to 100) and then multiply this by a constant to get the appropriate parent value. After all, if you edit each parent value, they won't necessarily be proportional.
Here's an example of a scale:
edit: (fixed the domain)
var myscale = d3.scale.linear()
.domain([0, maxParentWidth])
.range([0,y]); // .range([0,1]) is the default range
This will scale all the "parents" on the domain 0 to the largest parent value to a range of [0,y], where y is whatever you want (i.e., 100). Let's say you want the largest parent bar to be 300px. Now, all you have to do is multiply this scaled value by a constant, in this case, 3.
Related
I took this code off the web and it works correctly. I need to load the data from a json instead of the data being coded into the page. Being new to this, I decide to first simply take the original data and put it in a json file and call the file. I can't seem to get it to work. I get a blank section where the graph would go and all I get from debugger is "mutating the prototype of an object will cause you code to run slowly", which I get with the original code so that's not it.
Here is the section of the original code
function loadImage(){
if(LoadData){
root = {
"name": "Daniel Vinod", "imageURL":"images/root.png","id":"1",
"children": [
{"name": "Abraham Aaron", "imageURL":"images/user1.png","id":"2",
"children":[{"name": "Joseph Titus", "imageURL":"images/user3.png","id":"3"},
{"name": "Herold Enoch", "imageURL":"images/user4.png","id":"4"}]},
{"name": "Samuel Goliatf", "imageURL":"images/user7.png","id":"5",
"children":[{"name": "Enoch Titus", "imageURL":"images/user2.png","id":"6"},
{"name": "Quintus Titus", "imageURL":"images/user5.png","id":"7"}]},
{"name": "Absalom Dauid", "imageURL":"images/user2.png","id":"8" ,
"children":[{"name": "Abraham Shalom", "imageURL":"images/user4.png","id":"9"},
{"name": "Elisha Titus", "imageURL":"images/user6.png","id":"10"}]},
{"name": "Daniel Goliatf", "imageURL":"images/user3.png","id":"12",
"children":[{"name": "Quintus Titus", "imageURL":"images/user5.png","id":"13"},
{"name": "Enoch Titus", "imageURL":"images/user1.png","id":"14"},
{"name": "Elisha Titus", "imageURL":"images/user6.png","id":"15",
"children":[ {"name": "Enoch Absalom", "imageURL":"images/user1.png","id":"11"}]}]},
{"name": "Enoch Shalom", "imageURL":"images/user5.png","id":"16",
"children":[{"name": "Absalom Joseph", "imageURL":"images/user7.png","id":"17"},
{"name": "Shalom Joseph", "imageURL":"images/user4.png","id":"18"},
{"name": "Quintus Titus", "imageURL":"images/user5.png","id":"7"}]}
]
};
force = d3.layout.force()
.on("tick", tick)
.size([w, h]);
vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h);
update();
LoadData = false;
}
}
I swapped the data for this
function loadImage(){
if(LoadData){
root = d3.json("data2.json", function(error, graph) {
if (error) throw error;
force = d3.layout.force()
.on("tick", tick)
.size([w, h]);
vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h);
update();
LoadData = false;
});
}
}
And created a data2.json file:
{
"name": "Daniel Vinod", "imageURL":"images/root.png","id":"1",
"children": [
{"name": "Abraham Aaron", "imageURL":"images/user1.png","id":"2",
"children":[{"name": "Joseph Titus", "imageURL":"images/user3.png","id":"3"},
{"name": "Herold Enoch", "imageURL":"images/user4.png","id":"4"}]},
{"name": "Samuel Goliatf", "imageURL":"images/user7.png","id":"5",
"children":[{"name": "Enoch Titus", "imageURL":"images/user2.png","id":"6"},
{"name": "Quintus Titus", "imageURL":"images/user5.png","id":"7"}]},
{"name": "Absalom Dauid", "imageURL":"images/user2.png","id":"8" ,
"children":[{"name": "Abraham Shalom", "imageURL":"images/user4.png","id":"9"},
{"name": "Elisha Titus", "imageURL":"images/user6.png","id":"10"}]},
{"name": "Daniel Goliatf", "imageURL":"images/user3.png","id":"12",
"children":[{"name": "Quintus Titus", "imageURL":"images/user5.png","id":"13"},
{"name": "Enoch Titus", "imageURL":"images/user1.png","id":"14"},
{"name": "Elisha Titus", "imageURL":"images/user6.png","id":"15",
"children":[ {"name": "Enoch Absalom", "imageURL":"images/user1.png","id":"11"}]}]},
{"name": "Enoch Shalom", "imageURL":"images/user5.png","id":"16",
"children":[{"name": "Absalom Joseph", "imageURL":"images/user7.png","id":"17"},
{"name": "Shalom Joseph", "imageURL":"images/user4.png","id":"18"},
{"name": "Quintus Titus", "imageURL":"images/user5.png","id":"7"}]}
]
}
Note, no brackets, so it's not a true json but it doesn't work with the brackets either. Again, no error, just a white space where the graph should be. Thanks for the help in advance.
root is a variable in the original which points to the json object, which I suspect gets picked up and used in the update() function. In your 2nd example, you've defined root so it points to the json loading function, whereas graph is the pointer to the loaded json object. Rename root as jsonFunc and set root = graph; within the json loading function in your 2nd example, see if that works. If not, it's make a jsfiddle time.
Got a question regarding AngularJS and a carousel menu. I've made an array and I have trouble inserting the data in my View.
Controller:
gameApp.controller('homeController', function($scope) {
// Gamemodelist is static. Put all the corresponding gamemodes in an array
$scope.gameModeList = [
{"name": "Waterworld", "contents": [
{"name": "Classic", "contents": [
{"name": "Level 1", "contents": [{"name": "beginner"}, {"name": "easy"},{"name": "intermediate"}, {"name": "ultimate"}]},
{"name": "Level 2", "contents": [{"name": "easy"}]}
]},
{"name": "Firemode", "contents": [
{"name": "Level 3", "contents": [{"name": "beginner"}]}
]},
{"name": "Watermode", "contents":[
{"name": "Level 4", "contents": [{"name": "introduction"}]}
]}
]},
{"name": "Fireworld", "contents": [
{"name": "Classic", "contents": [
{"name": "Level 1", "contents": [{"name": "Intro"}, {"name": "Beginner"}, {"name": "Intermediate"}]},
{"name": "Level 2", "contents": [{"name": "Beginner"}, {"name":"Intermediate"}]}
]},
{"name": "Fireworld", "contents": [
{"name": "Level 3", "contents": [{"name": "Beginner"}, {"name": "Intermediate"}]}
]}
]},
{"name": "Tutorial", "contents": [
{"name": "Basic Tutorial"}, {"name": "Battle Training"}
]}];
}
This array is basicly the menu itself. You see the first items in the array are the first items in the menu. And every array in the contents is the submenu and if there is a subsubmenu.
This is my controller. Now I'm new to Angular, and I've already mate routing and templating work. Got different controllers for the login screen and the options screen. But now I'm working on the homescreen, which features a menu and I'm quite uncertain what's my best step here. I've already decided that I don't want to use different pages like I'm doing with my login and options screen, because I feel that an array is more convenient, because it already features the ordering of the items and it's (imo) a bit more managable.
To the view then. I've already checked and I think I need to use ng-if to check if there are submenu's in the array and if so use ng-repeat to display the menu. But. I come from jQuery background, so my instinct was to display the list and make it work with CSS and jQuery to manipulate the DOM so the items are shown which I want them to show, I know (for sure) that thats how things work in Angular. I guess I need to check with the controller which items need to display?
<ul>
<li class="animate-repeat" ng-repeat="mode in gameModeList">
{{ mode.name }}
</li>
</ul>
Now I only get the first items in the list obviously. I guess I now have to get the contents of the item I click in the view?
I am using this:
http://mbostock.github.io/d3/talk/20111018/partition.html
instead of d3.json("flare.json", function(root) {
how do i make it use the json file within the html, like say i have
var json = [{
"name": "flare",
"children": [
{"name": "analytics",
"children": [
{"name": "cluster","children": [{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
and i want to use this instead of an external json file, how do i achieve this?
Link to json file: http://mbostock.github.io/d3/talk/20111018/flare.json
Any JSFiddle example please?
Thank you.
You will achieve this by two method:
1.you can assign the JSON data to variable name then You can build any layout
2.use one function to get the JSON data
Fiddle for 1 solution
var root = json;
Fiddle for 2 solution
var root = getData();
var g = vis.selectAll("g")
.data(partition.nodes(root))
.enter().append("svg:g")
.attr("transform", function(d) { return "translate(" + x(d.y) + "," + y(d.x) + ")"; })
.on("click", click);
As mentioned above i'm trying out the plot a chart using d3 where in i'd require the data to be in Parent Child relationship but i couldn't figure it out how to convert the MySQL query result to JSON parent child format.
Help provided will be very thankful.
I'm trying to replicate the chart in the below URL :
Zoomable Partition Layout (click on the partitions to zoom up or down the tree)
Data in MySQL :
Column1 Column2 Column3
First Top - 1500
First Child First Top 500
Second Child First Top 500
Third Child First Top 500
First Sub-Child First Child 250
First Sub-Child First Child 250
Second Sub-Child Second Child 250
Second Sub-Child Second Child 250
Third Sub-Child Third Child 250
Third Sub-Child Third Child 250
Desired Data Format :
{
"name": "First Top",
"children": [
{
"name": "First Child",
"children": [
{"name": "First Sub-Child", "size": 250},
{"name": "First Sub-Child", "size": 250}
]
},
{
"name": "Second Child",
"children": [
{"name": "Second Sub-Child", "size": 250},
{"name": "Second Sub-Child", "size": 250}
]
},
{
"name": "Third Child",
"children": [
{"name": "Third Sub-Child", "size": 250},
{"name": "Third Sub-Child", "size": 250}
]
}
]
}
Here's some pseudo-code, assuming one level of hierarchy:
get the parent/child rows from the database (select t1.parent, t1.item, size from tree t1, tree t2 where t1.parent=t2.item)
loop through the rows:
if parent is different than previous parent and previous parent is set:
push object onto array
start a new object
add child and size to object
push last object onto array
get root object (where parent is null)
encode object as json with root object; see Create JSON-object the correct way
output json
Using D3 Javascript and JSON, I need to create something very similar to:
http://bl.ocks.org/mbostock/4063550
The JSON file (copied from website) looks something like:
{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
Now instead of the "size" in the code above, I have "score" (i.e. "score": 3).
What I want to achieve is the diagram similar to the website, but the difference is that is the score is over a certain threshold (e.g >5), I want the small blue circle to be of a certain color (i.e. red).
I know this needs to be updated in the index.html file, but I just don't know how to get around to doing that. Any pointers would be appreciated!
Thanks!
All you need to do this is to slightly modify the code that appends the circles. You need to change the snippet
node.append("circle")
.attr("r", 4.5);
to
node.append("circle")
.style("stroke", function(d) { return d.score > 5 ? "red" : "steelblue"; })
.attr("r", 4.5);
You can obviously apply something like this to e.g. the fill colour in the same way. If you have a larger number of different colours and thresholds, it might be worth investigating using a scale instead of a conditional statement.
Change your JSON like so:
{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "score": 3938},
{"name": "CommunityStructure", "score": 3812},
{"name": "HierarchicalCluster", "score": 6714},
{"name": "MergeEdge", "score": 743}
]
},
Now use a function to check for the condition in the data and set the style for the circle:
node.append("circle")
.attr("r", 4.5)
.style("fill",function(d){
return ((d.score > 5)?"red":"blue");
});