I'm setting a Icicle graph on a old angularjs application. I decided to try d3 graphs and doing some tests... So basically two questions, for two different codes:
Question 1: Initially i used this example: https://bl.ocks.org/lorenzopub/c4a226f9c29a20dd0cc152e212a70c9a
I realized that when you zoom in certain areas of the graph, it returns " attribute width: A negative value is not valid. ("-2428.9156626506024")" and even if it makes the zoom it doesnt show the text. Any idea why this happens?
Question 2: Later i tried to make my own structure, using the same json as the previous example. The main difference was that i created a "g" and inside it i placed the "rec" and the "foreignObject", to make it more organized in terms of structure. Code below
I placed the below code in an angularjs directive.
I'm using V4 of d3 "//d3js.org/d3.v4.min.js"
var totalSize = 0;
var width = 960, height = 500;
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([0, height]);
var color = d3.scaleOrdinal(d3.schemeCategory20c);
var partition = d3.partition()
.size([width, height])
.padding(0)
.round(true);
var svg = d3.select("#pleaseWork") //.append("svg")
.attr("width", width)
.attr("height", height);
var groups = svg.selectAll("g");
d3.json("graphs/dataD3.json", function (error, root) {
//d3.json("graphs/newData.json", function (error, root) {
if (error) throw error;
root = d3.hierarchy(d3.entries(root)[0], function (d) {
return d3.entries(d.value)
})
.sum(function (d) {
return d.value
})
.sort(function (a, b) {
return b.value - a.value;
});
partition(root);
groups = groups
.data(root.descendants())
.enter().append("g")
.attr("fill", function (d) {
return color((d.children ? d : d.parent).data.key);
})
.on("click", clicked);
//get total size from rect
totalSize = groups.node().__data__.value;
console.log(groups.node().__data__.value);
groups.append('rect')
.attr("x", function (d) {
return d.x0;
})
.attr("y", function (d) {
return d.y0;
})
.attr("width", function (d) {
return d.x1 - d.x0;
})
.attr("height", function (d) {
return d.y1 - d.y0;
});
groups.append('foreignObject')
.text(function (d) {
//return d.data.key + '-' + d.value;
return d.data.key + ' - ' + (100 * d.value / totalSize).toPrecision(3) + '%';
})
.attr("x", function (d) {
return d.x0;
})
.attr("y", function (d) {
return d.y0;
})
.attr("width", function (d) {
return d.x1 - d.x0;
})
.attr("height", function (d) {
return d.y1 - d.y0;
});
});
function clicked(d) {
console.log(d);
x.domain([d.x0, d.x1]);
y.domain([d.y0, height]).range([d.depth ? 20 : 0, height]);
groups.transition()
.duration(750)
.attr("x", function (d) {
return x(d.x0);
})
.attr("y", function (d) {
return y(d.y0);
})
.attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr("height", function (d) {
return y(d.y1) - y(d.y0);
});
}
}
When i click on a item to zoom, it enter in the function "clicked" but nothing happens, i wanted to achieve something similar as the first example, where it zooms to that element level. Thanks in advance for the support
Solved the first question with replacing the code from the fo.transition() to:
.attr("x", function (d) {
return d.x0;
})
.attr("y", function (d) {
return d.y0;
})
.attr("width", function (d) {
return d.x1 - d.x0;
})
.attr("height", function (d) {
return d.y1 - d.y0;
})
The second question, i solved like this:
var width = 500,
height = 300;
var partitionLayout = d3.partition().size([width, height]);
//needed for zoom ?
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([0, height]);
//needed to fill the colour
var colour = d3.scaleOrdinal(d3.schemeCategory20c);
d3.json("graphs/newstructure.json", function (data) {
var rootNode = d3.hierarchy(data);
rootNode.sum(function (d) {
return d.value;
});
// structure the data for the graph
partitionLayout(rootNode);
var group = d3.select('#new')
.selectAll('g')
.data(rootNode.descendants())
.enter()
.append('g')
.attr("fill", function (d) {
return colour(d.data.colour);
})
.on("click", clicked);
group.append('rect')
.attr('x', function (d) {
console.log(d);
return d.x0;
})
.attr('y', function (d) {
return d.y0;
})
.attr('width', function (d) {
return d.x1 - d.x0;
})
.attr('height', function (d) {
return d.y1 - d.y0;
})
.attr('fill', function (d) {
return d.data.colour;
});
group
.append('foreignObject')
.text(function (d) {
console.log(d);
return d.data.name + ' - ' + d.value;
})
.attr("x", function (d) {
return d.x0;
})
.attr("y", function (d) {
return d.y0;
})
.attr("width", function (d) {
return d.x1 - d.x0;
})
.attr("height", function (d) {
return d.y1 - d.y0;
});
function clicked(d) {
x.domain([d.x0, d.x1]);
y.domain([d.y0, height]).range([d.depth ? 20 : 0, height]);
group.transition()
.duration(750)
.attr("x", function (d) {
return x(d.x0);
})
.attr("y", function (d) {
return y(d.y0);
})
.attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr("height", function (d) {
return y(d.y1) - y(d.y0);
});
var rects = d3.select('#new')
.selectAll('g rect');
rects.transition()
.duration(750)
.attr("x", function (d) {
return x(d.x0);
})
.attr("y", function (d) {
return y(d.y0);
})
.attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr("height", function (d) {
return y(d.y1) - y(d.y0);
});
var rects = d3.select('#new')
.selectAll('g foreignObject');
rects.transition()
.duration(750)
.attr("x", function (d) {
return x(d.x0);
})
.attr("y", function (d) {
return y(d.y0);
})
.attr("width", function (d) {
return x(d.x1) - x(d.x0);
})
.attr("height", function (d) {
return y(d.y1) - y(d.y0);
});
}
});