How to create stretchable svg shapes - svg

How to create workflow components with stretchable feature of different shapes like in this link http://rigrr.rapilabs.com/
I have implement a sample using d3 such as draggable circle but I don't know how to achieve stretching of shapes
var boxWidth = 600;
var boxHeight = 400;
var box = d3.select('body')
.append('svg')
.attr('class', 'box')
.attr('width', boxWidth)
.attr('height', boxHeight);
var drag = d3.behavior.drag()
.on('dragstart', function() {
circle.style('fill', 'red');
})
.on('drag', function() {
circle.attr('cx', d3.event.x)
.attr('cy', d3.event.y);
})
.on('dragend', function() {
circle.style('fill', 'black');
});
var circle = box.selectAll('.draggableCircle')
.data([{
x: (boxWidth / 2),
y: (boxHeight / 2),
r: 25
}])
.enter()
.append('svg:circle')
.attr('class', 'draggableCircle')
.attr('cx', function(d) {
return d.x;
})
.attr('cy', function(d) {
return d.y;
})
.attr('r', function(d) {
return d.r;
})
.call(drag)
.style('fill', 'black');
.box {
border: 1px solid black;
border-radius: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>

Here is one way to do it - add a group and add the element and a ghost of the element behind the element but with a slightly bigger size. This element can be used for resizing.
I've added this to your circle move code in the below snippet
var boxWidth = 600;
var boxHeight = 400;
var box = d3.select('body')
.append('svg')
.attr('class', 'box')
.attr('width', boxWidth)
.attr('height', boxHeight);
var drag = d3.behavior.drag()
.on('drag', function() {
g.selectAll('*')
.attr('cx', d3.event.x)
.attr('cy', d3.event.y);
})
var resize = d3.behavior.drag()
.on('drag', function() {
g.selectAll('.resizingContainer')
.attr('r', function(c) {
return Math.pow(Math.pow(this.attributes.cx.value - d3.event.x, 2) + Math.pow(this.attributes.cy.value - d3.event.y, 2), 0.5) + 6;
});
g.selectAll('.draggableCircle')
.attr('r', function(c) {
return Math.pow(Math.pow(this.attributes.cx.value - d3.event.x, 2) + Math.pow(this.attributes.cy.value - d3.event.y, 2), 0.5);
});
})
var g = box.selectAll('.draggableGroup')
.data([{
x: (boxWidth / 2),
y: (boxHeight / 2),
r: 25
}])
.enter()
.append('g')
g
.append('svg:circle')
.attr('class', 'resizingContainer')
.attr('cx', function(d) {
return d.x;
})
.attr('cy', function(d) {
return d.y;
})
.attr('r', function(d) {
return d.r + 6;
})
.style('fill', '#999')
.call(resize);
g
.append('svg:circle')
.attr('class', 'draggableCircle')
.attr('cx', function(d) {
return d.x;
})
.attr('cy', function(d) {
return d.y;
})
.attr('r', function(d) {
return d.r;
})
.call(drag)
.style('fill', 'black')
.box {
border: 1px solid black;
border-radius: 10px;
}
.resizingContainer {
cursor: nesw-resize;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Not sure what your idea of "streching" is but you can look at transforms such as scale and skew.
transform="skewX(50)"
transform="skewY(50)"

Related

How to append a list of text on graph dot labels

mya I ask how to label each dot on a line graph with their unified label? For example, in this example https://datawanderings.com/2019/11/01/tutorial-making-an-interactive-line-chart-in-d3-js-v-5/
I modified the code to add a text label "a" on top of each circle, by adding the code in line 136 as below:
var label = lines.selectAll("circles")
.data(function(d) { return(d.values); } )
.enter()
label.append("text")
.attr("text-anchor", "bottom")
.attr("dx", function(d) { return xScale(d.date); })
.attr("dy", function(d) { return yScale(d.measurement); })
.text("a")
My output is like this
However, my real desired output is to add this existing list to label each three lines:
existing_list = [['a1','a2','a3','a4','a5','a6','a7','a8','a9','a10','a11','a12','a13','a14'],['b1','b2','b3','b4','b5','b6','b7','b8','b9','b10','b11','b12','b13','b14'],['c1','c2','c3','c4','c5','c6','c7','c8','c9','c10','c11','c12','c13','c14']]
That's said, each label is different and the 5th label on line B should be labeled as 'b5'. May I ask how to achieve this?
The complete code is as below:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>Multi Line Chart</title>
<script type="text/javascript" src="https://d3js.org/d3.v5.min.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
<style></style>
</head>
<body>
<div id="container" class="svg-container"></div>
<script>
//------------------------1. PREPARATION------------------------//
//-----------------------------SVG------------------------------//
const width = 960;
const height = 500;
const margin = 5;
const padding = 5;
const adj = 30;
// we are appending SVG first
const svg = d3.select("div#container").append("svg")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "-"
+ adj + " -"
+ adj + " "
+ (width + adj *3) + " "
+ (height + adj*3))
.style("padding", padding)
.style("margin", margin)
.classed("svg-content", true);
//-----------------------------DATA-----------------------------//
const timeConv = d3.timeParse("%d-%b-%Y");
const dataset = d3.csv("data.csv");
dataset.then(function(data) {
var slices = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d){
return {
date: timeConv(d.date),
measurement: +d[id]
};
})
};
});
//----------------------------SCALES----------------------------//
const xScale = d3.scaleTime().range([0,width]);
const yScale = d3.scaleLinear().rangeRound([height, 0]);
xScale.domain(d3.extent(data, function(d){
return timeConv(d.date)}));
yScale.domain([(0), d3.max(slices, function(c) {
return d3.max(c.values, function(d) {
return d.measurement + 4; });
})
]);
//-----------------------------AXES-----------------------------//
const yaxis = d3.axisLeft()
.ticks((slices[0].values).length)
.scale(yScale);
const xaxis = d3.axisBottom()
.ticks(d3.timeDay.every(1))
.tickFormat(d3.timeFormat('%b %d'))
.scale(xScale);
//----------------------------LINES-----------------------------//
const line = d3.line()
.x(function(d) { return xScale(d.date); })
.y(function(d) { return yScale(d.measurement); });
let id = 0;
const ids = function () {
return "line-"+id++;
}
//---------------------------TOOLTIP----------------------------//
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute");
//-------------------------2. DRAWING---------------------------//
//-----------------------------AXES-----------------------------//
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(xaxis);
svg.append("g")
.attr("class", "axis")
.call(yaxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("dy", ".75em")
.attr("y", 6)
.style("text-anchor", "end")
.text("Frequency");
//----------------------------LINES-----------------------------//
const lines = svg.selectAll("lines")
.data(slices)
.enter()
.append("g");
lines.append("path")
.attr("class", ids)
.attr("d", function(d) { return line(d.values); });
lines.append("text")
.attr("class","serie_label")
.datum(function(d) {
return {
id: d.id,
value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) {
return "translate(" + (xScale(d.value.date) + 10)
+ "," + (yScale(d.value.measurement) + 5 )+ ")"; })
.attr("x", 5)
.text(function(d) { return ("Serie ") + d.id; });
//---------------------------POINTS-----------------------------//
lines.selectAll("points")
.data(function(d) {return d.values})
.enter()
.append("circle")
.attr("cx", function(d) { return xScale(d.date); })
.attr("cy", function(d) { return yScale(d.measurement); })
.attr("r", 1)
.attr("class","point")
.style("opacity", 1);
var list = [['a1','a2','a3','a4','a5','a6','a7','a8','a9','a10','a11','a12','a13','a14'],
['b1','b2','b3','b4','b5','b6','b7','b8','b9','b10','b11','b12','b13','b14'],
['c1','c2','c3','c4','c5','c6','c7','c8','c9','c10','c11','c12','c13','c14']]
console.log(list)
//---------------------------EVENTS-----------------------------//
var label = lines.selectAll("circles")
.data(function(d) { return(d.values); } )
.enter()
label.append("text")
.attr("text-anchor", "bottom")
.attr("dx", function(d) { return xScale(d.date); })
.attr("dy", function(d) { return yScale(d.measurement); })
.text("a")
label.append("circle")
.attr("cx", function(d) { return xScale(d.date); })
.attr("cy", function(d) { return yScale(d.measurement); })
.attr('r', 10)
.style("opacity", 0)
.on('mouseover', function(d) {
tooltip.transition()
.delay(30)
.duration(200)
.style("opacity", 1);
tooltip.html(d.measurement)
.style("left", (d3.event.pageX + 25) + "px")
.style("top", (d3.event.pageY) + "px");
const selection = d3.select(this).raise();
selection
.transition()
.delay("20")
.duration("200")
.attr("r", 6)
.style("opacity", 1)
.style("fill","#ed3700");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(100)
.style("opacity", 0);
const selection = d3.select(this);
selection
.transition()
.delay("20")
.duration("200")
.attr("r", 10)
.style("opacity", 0);
});
});
</script>
</body>

Viewbox positioning trouble, svg moves top left

I m having trouble to position my svg in the middle of the viewbox. I tried to change the coordinate in the transform, however, if I resize the browser, the svg does not stick in the middle.
Below is my code and screenshot of the problem:
function BuildVerticaLTree(treeData, treeContainerDom) {
var contextMenuList = [
{
title: 'Remove Node',
action: function(elm, d, i) {
if (d.parent && d.parent.children){
var nodeToDelete = _.where(d.parent.children, {name: d.name});
if (nodeToDelete){
d.parent.children = _.without(d.parent.children, nodeToDelete[0]);
}
update(d);
}
}
},
{
title: 'Synopsis',
action: function(elm, d, i) {
console.log("Option 2 clicked");
console.log("Node Name: "+ d.name);
setNodeTopic(d.name);
}
}
];
var margin = {top: 40, right: 120, bottom: 20, left: 600},
width = 960 - margin.right - margin.left,
height = 900 - margin.top - margin.bottom;
var i = 0;
var tree = d3.layout.tree()
.size([height, width])
.nodeSize([80,80])
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, d.y]; });
var svg = d3.select(treeContainerDom)
.append("div")
.classed("svg-container", true) //container class to make it responsive
.append("svg")
//responsive SVG needs these 2 attributes and no width and height attr
.attr("preserveAspectRatio", "xMidYMin meet")
.attr("viewBox", "0 0 1200 1200")
//.attr("viewBox", "0 0 "+width+" "+height)
//class to make it responsive
.classed("svg-content-responsive", true)
//.call(zm = d3.behavior.zoom().scaleExtent([0.5,2]).on("zoom", redraw)).append("g")
//.attr("transform","translate("+"0"+","+"0"+")");
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var root = treeData;
update(root);
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 100; });
// Declare the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; });
nodeEnter.append("circle")
.attr("r", 30)
.attr("stroke","steelblue")
.attr("stroke-width","5px")
.style("fill", "#fff");
nodeEnter.append("text")
.attr("y", function(d) {
return -10;
})
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; })
.style("fill-opacity", 1);
// Declare the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", diagonal);
}
}
BuildVerticaLTree(that.objectList, "#tree");

Connected link line animation when mouse over on the node in force layout d3

I want to make line animation like stroke-dash running when mouse over on the node. This animation should stop when mouse out.
As i searched i got a code.
var totalLength = path.node().getTotalLength();path
.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
How come i make the animation till mouse over and stop when mouse out.
var graph = {
"nodes": [{
"name": "1",
"rating": 90,
"id": 2951,
"x": 90,
"y": 50,
"fixed": true
}, {
"name": "2",
"rating": 80,
"id": 654654,
"x": 50,
"y": 50,
"fixed": true
}, {
"name": "3",
"rating": 80,
"id": 6546544,
"x": 50,
"y": 90,
"fixed": true
},
],
"links": [{
"source": 1,
"target": 0,
"value": 6,
"label": "publishedOn"
}, {
"source": 1,
"target": 2,
"value": 6,
"label": "publishedOn"
}, {
"source": 1,
"target": 0,
"value": 4,
"label": "containsKeyword"
},
]
}
var margin = {
top: -5,
right: -5,
bottom: -5,
left: -5
};
var width = 500 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var color = d3.scale.category20();
var force = d3.layout.force()
.charge(-200)
.linkDistance(50)
.size([width + margin.left + margin.right, height + margin.top + margin.bottom]);
var zoom = d3.behavior.zoom()
.scaleExtent([.1, 1])
.on("zoom", zoomed);
var drag = d3.behavior.drag()
.origin(function(d) {
return d;
})
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
var svg = d3.select("#map").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")").call(zoom);
var rect = svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all");
var container = svg.append("g");
//d3.json('http://blt909.free.fr/wd/map2.json', function(error, graph) {
force
.nodes(graph.nodes)
.links(graph.links)
.start();
var movement = 200;
var link = container.append("g")
// .attr("class", "links")
.selectAll(".link")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) {
return Math.sqrt(d.value);
})
//.attr("transform", function(d) {
// return "translate(" + movement + "," + 0 + ")";
//})
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; })
;
var node = container
.selectAll(".node").append("g")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.call(drag)
;
node.append("circle")
.attr("r", function(d) {
return d.weight * 2 + 12;
})
.style("fill", function(d) {
return color(1 / d.rating);
})
//.attr("transform", function(d) {
// return "translate(" + movement + "," + 0 + ")";
//})
//.call(drag)
; //Here you move the nodes
force.on("tick", tick);
function tick(){
//force.on("tick", function() {
link.attr("x1", function(d) {
return d.source.x;
})
.attr("y1", function(d) {
return d.source.y;
})
.attr("x2", function(d) {
return d.target.x;
})
.attr("y2", function(d) {
return d.target.y;
});
node.attr("transform", function(d) {
//Here i create a node radius so it doesnt go offscreen
var nodeRadius = d.weight * 2 + 12
//here I do checks to see if it goes offscreen
if(d.x<= nodeRadius){
d.x = nodeRadius;
}
if(d.y<= nodeRadius){
d.y = nodeRadius;
}7
if(d.x>width - nodeRadius){
d.x = width - nodeRadius;
}
if(d.y>height - nodeRadius){
d.y = height - nodeRadius;
}
return "translate(" + d.x + "," + d.y + ")";
});
}
var linkedByIndex = {};
graph.links.forEach(function(d) {
linkedByIndex[d.source.index + "," + d.target.index] = 1;
});
function isConnected(a, b) {
return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index];
}
node.on("mouseover", function(d) {
link.attr("stroke-dasharray", 10 + " " + 10)
.attr("stroke-dashoffset", 500)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
node.classed("node-active", function(o) {
thisOpacity = isConnected(d, o) ? true : false;
this.setAttribute('fill-opacity', thisOpacity);
return thisOpacity;
});
link.classed("link-active", function(o) {
return o.source === d || o.target === d ? true : false;
});
d3.select(this).classed("node-active", true);
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", (d.weight * 2 + 12) * 1.5);
})
.on("mouseout", function(d) {
link.attr("stroke-dasharray", 0).attr("stroke-dashoffset", 0);
node.classed("node-active", false);
link.classed("link-active", false);
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", d.weight * 2 + 12);
});
function dottype(d) {
d.x = +d.x;
d.y = +d.y;
return d;
}
function zoomed() {
container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
force.start();
}
function dragged(d) {
force.stop();
d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
tick();
}
function dragended(d) {
d.fixed = true;
//d3.select(this).classed("dragging", false);
tick();
}
.node {
stroke: #fff;
stroke-width: 1.5px;
}
.node-active{
stroke: #555;
stroke-width: 1.5px;
}
.link {
stroke: #555;
stroke-opacity: .3;
}
.link-active {
stroke-opacity: 1;
}
.overlay {
fill: none;
pointer-events: all;
}
#map{
border: 2px #555 dashed;
width:500px;
height:400px;
}
<link href="https://code.jquery.com/ui/1.10.4/themes/black-tie/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="map"></div>
Hope you are looking for this,
Description for the code
In mouse over function I've added below lines of code
link.attr("stroke-dasharray", 10 + " " + 10)
.attr("stroke-dashoffset", 500)
.transition()
.duration(2000)
.ease("linear")
.attr("stroke-dashoffset", 0);
above I'm setting stroke-dasharray attribute with "10 10" this will make line to be displayed in dashed style like - - - -, next
setting stroke-dashoffset with 500 this value makes the dashes to move faster means value changes 0 to 500 in the time span of 2000 milliseconds which is mentioned in duration(2000) of transition above you can see that.
After completion of transition I'm changing stroke-dashoffset to 0 to make it as line,
And also in mouseout function I've added below line
link.attr("stroke-dasharray", 0).attr("stroke-dashoffset", 0);
This will make the lines again from dashed to single line.
And For more observation
Once you mouseover to any circle the animation will started and it'll continued for 2seconds, but within 2seconds if you mouseover to the circle you can see the animation which is activated previously and still running. So that is left for your choice whether to play the animation for 2seconds or not, hope you understood where to change the value for this,
And one more thing is when you want to make it as a single line,
immediately when the mouseout is fired or after the animation is completed.
These two things need to be observed.
Hope you understood every thing, If not ask me.
Okay.I might have done this yesterday, due to time and system availability.

d3 treemap rect orientation error when updating

I wrote a d3.js treemap that updates and re-renders when I receive new data. When I do graph the maps, the rects sometimes shift positions, and it seems like the orientation of the elements is messed up because they move outside the chart or overlap with another element, leaving whitespace in the throughout the graph, but after re-rendering the graph usually corrects itself, and then messes up again. I think the problem comes about because the graph is resizing itself with regards to absolute positions, but rects in certain positions from the previous render are messing things up. Any clue how to stop this intermediate phase of having a messed up graph before being able to re-render? Thanks.
This is the code I use to initially draw the d3 regraph.
function drawTreeMap(array1,array2, colorArray)
{
console.log("got to drawing");
var cellMargin=5;
this.marginTree = {top:20, right:20, bottom:20, left:20};
var coloring = d3.scale.linear()
.range(['lightblue', 'green']) // or use hex values
.domain([this.getMinOfThisArray(colorArray), this.getMaxOfThisArray(colorArray)]);
this.nestedJson = this.createObj(array1, array2, colorArray);
this.w = 1700 - 80,
this.h = 980 - 180,
this.x = d3.scale.linear().range([0, this.w]),
this.y = d3.scale.linear().range([0, this.h]),
this.root,
this.node;
this.treemap = d3.layout.treemap()
.round(false)
.size([this.w, this.h])
.sticky(true)
.padding([this.marginTree.bottom, this.marginTree.right, this.marginTree.top, this.marginTree.left])
.sort(function(a,b) {
return a.value - b.value;
})
.value(function(d) { return d.size; });
this.svg = d3.select("#body").append("div")
.attr("class", "chart")
.style("position", "relative")
.style("width", (this.w) + "px")
.style("height", (this.h ) + "px")
.style("left", this.marginTree.left +"px")
.style("top", this.marginTree.top + "px")
.append("svg:svg")
.attr("width", this.w)
.attr("height", this.h)
.append("svg:g")
.attr("transform", "translate(.5,.5)");
this.node = this.root = this.nestedJson;
var nodes = this.treemap.nodes(this.root)
.filter(function(d) { return !d.children; });
this.tip = d3.tip()
.attr('class', 'd3-tip')
.html(function(d) {
return "<span style='color:white'>" + (d.name+",\n "+d.size) + "</span>";
})
this.svg.call(this.tip);
var cell = this.svg.selectAll("g")
.data(nodes)
.enter().append("svg:g")
.attr("class", "cell")
.call(this.position)
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.on("click", function(d) { return this.zoom(this.node == d.parent ? this.root : d.parent); });
var borderPath = this.svg.append("rect")
.attr("class", "border")
.attr("x", this.marginTree.left)
.attr("y", this.marginTree.top)
.attr("height", this.h - this.marginTree.top - this.marginTree.bottom )
.attr("width", this.w - this.marginTree.left - this.marginTree.right)
.style("stroke", 'darkgrey')
.style("fill", "none")
.style("stroke-width", '3px');
cell.append("svg:rect")
.attr("id", function(d,i) { return "rect-" + (i+1); })
.attr("class","highlighting2 cell-rects")
.attr("title", function(d) {return (d.name+", "+d.size);})
.attr("data-original-title", function(d) {return (d.name+",\n "+d.size);})
.attr("width", function(d) { return d.dx ; })
.attr("height", function(d) { return d.dy ; })
.on('mouseover', this.tip.show)
.on('mouseout', this.tip.hide)
.style("fill", function(d) {return coloring(d.color);});
cell.append("svg:text")
.attr("class", "treemap-text nameTexts")
.attr("id", function(d,i) { return "name-" + (i+1); })
.attr("x", cellMargin)
.attr("y", function(d) { return parseInt($('.treemap-text').css('font-size'))+cellMargin; })
.text(function(d) {return (d.name);});
cell.append("svg:text")
.attr("class", "treemap-text sizeTexts")
.attr("id", function(d,i) { return "size-" + (i+1); })
.attr("x", cellMargin)
.attr("y", function(d) { return 2*parseInt($('.treemap-text').css('font-size'))+2*cellMargin; })
.text(function(d) {return (d.size);});
// d3.selectAll("svg:rect")
// .style("stroke-width", 2)
// .style("stroke", function(d){ return this.LightenDarkenColor(coloring(d.color), -5);});
this.treeMapping = true;
$(document).ready(function(){
for (var i =1 ; i<graphObj.rc.positions[graphObj.currentVpName].SetSize; i++){
var obj = "rect-"+i;
var size = "size-"+i;
var name = "name-"+i;
graphObj.formatNumbers(size);
graphObj.placeTextWithEllipsis(obj, size);
graphObj.placeTextWithEllipsis(obj, name);
}
d3.selectAll(".nameTexts")
.style("fill", "#333333");
d3.selectAll(".sizeTexts")
.style("fill","#383838");
});
}
This is the file I use to re-render the treemap when I receive new data.
function redrawGraph(array1, array2, colorArray)
{
this.nestedJson = this.createObj(array1, array2, colorArray);
var coloring = d3.scale.linear()
.range(['lightblue', 'green']) // or use hex values
.domain([this.getMinOfThisArray(colorArray), this.getMaxOfThisArray(colorArray)]);
var cellMargin = 5;
this.svg = d3.select("#body").append("div")
this.treemap
.mode("squarify")
.round(false)
.size([this.w,this.h])
.sticky(true)
.value(function(d) { return d.size; });
// Draw the graph
this.node = this.root = this.nestedJson;
var nodes = this.treemap.nodes(this.root)
.filter(function(d) { return !d.children; });
var rect = d3.select("#body").selectAll(".cell-rects")
.data(nodes);
rect.exit().remove();
rect.enter().append("rect");
rect
.transition()
.attr("width", function(d) { return d.dx ; })
.attr("height", function(d) { return d.dy ; })
.attr("title", function(d) {return (d.name+", "+d.size);})
.attr("data-original-title", function(d) {return (d.name+",\n "+d.size);})
.style("fill", function(d) { return coloring(d.color)})
.call(this.position);
var text = d3.select("#body").selectAll(".nameTexts")
.data(nodes);
text.exit().remove();
text.enter().append("text");
text
.attr("class", "treemap-text nameTexts")
.attr("x", cellMargin)
.attr("y", function(d) { return parseInt($('.treemap-text').css('font-size'))+cellMargin; })
.text(function(d) { return (d.name); });
var text2 = d3.select("#body").selectAll(".sizeTexts")
.data(nodes);
text2.exit().remove();
text2.enter().append("text");
text2
.attr("class", "treemap-text sizeTexts")
.attr("x", cellMargin)
.attr("y", function(d) { return 2*parseInt($('.treemap-text').css('font-size'))+2*cellMargin; })
.text(function(d) { return (d.size); });
var cell = this.svg.selectAll("g")
cell.append("svg:rect")
cell.append("svg:text");
// var border = this.svg.append("rect")
// .attr("x", this.marginTree.left)
// .attr("y", this.marginTree.top)
// .attr("height", this.h - this.marginTree.top - this.marginTree.bottom )
// .attr("width", this.w - this.marginTree.left - this.marginTree.right)
// .style("stroke", 'darkgrey')
// .style("fill", "none")
// .style("stroke-width", '3px');
// d3.select(window).on("click", function() {
// this.zoom(this.root); });
// d3.select("select").on("change", function()
// {
// this.treemap.value(this.value == "size" ? this.size : this.count).nodes(this.root);
// this.zoom(this.node);
// });
d3.selectAll(".nameTexts")
.style("fill", "#333333");
d3.selectAll(".sizeTexts")
.style("fill","#383838");
$(document).ready(function(){
for (var i =1 ; i<graphObj.rc.positions[graphObj.currentVpName].SetSize; i++){
var obj = "rect-"+i;
var size = "size-"+i;
var name = "name-"+i;
graphObj.formatNumbers(size);
graphObj.placeTextWithEllipsis(obj, size);
graphObj.placeTextWithEllipsis(obj, name);
}
});
}
function position()
{
this.style("left", function(d) { return d.x + "px"; })
.style("top", function(d) { return d.y + "px"; })
.style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; })
.style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; });
}
Also by white space I mean this.
Image is linked here. [http://i.stack.imgur.com/LTLk6.png][1]

d3 pie charts innerRadius and outerRadius acting funky

The pie charts' arcs each seem to have their own radius behaviors, when i want them to all share the radius of the highest value passed in. here's the relevant code.
var pie = d3.layout.pie()
.value(function(d) {
return d;
}).sort(null);
var arc = d3.svg.arc()
.innerRadius(function(d, i) { console.log(d, i); return (d.value * .6) })
.outerRadius(function(d) { return d.value; });
var fill = d3.scale.linear()
.domain([0, 2])
.range(["red", "blue"]);
var force = d3.layout.force()
.nodes(data)
.size([width + 250, height + 50])
.on("tick", tick)
.charge(charge)
.gravity(.15);
force.start();
function charge(d) {
return d.rank * d.rank * -.25;
}
var svg = d3.select("body").append("svg")
.attr("width", width + 250)
.attr("height", height + 50);
var nodes = svg.selectAll(".node")
.data(data)
.enter()
.append("g")
.attr("class", "node");
// .attr("cx", function(d) { return d.x; })
// .attr("cy", function(d) { return d.y; })
// .attr("r", function(d) { return d.rank; })
nodes.selectAll("path")
.data(function(d) {
var ar = [];
ar.push(prostitution_scale(d.prostitution));
ar.push(cigarette_scale(d.cigarettes));
ar.push(alcohol_scale(d.alcohol));
return pie(ar);
})
.enter()
.append("svg:path")
.attr("d", arc)
.style("fill", function(d, i) { return fill(i); })
.style("stroke", function(d, i) { return d3.rgb(fill(d.value)).darker(2); })
.call(force.drag);
You're passing functions to the accessors for the radii:
.innerRadius(function(d, i) { console.log(d, i); return (d.value * .6) })
.outerRadius(function(d) { return d.value; });
So D3 is going to call these functions for every data element and use the value it gets from that. If you want something constant, specify a single number, e.g.
.innerRadius(30)
.outerRadius(50);
To get use the maximum value for each arc, you could do something like this.
nodes.selectAll("path")
.data(function(d) {
var ar = [];
ar.push(prostitution_scale(d.prostitution));
ar.push(cigarette_scale(d.cigarettes));
ar.push(alcohol_scale(d.alcohol));
var segments = pie(ar),
maxValue = d3.max(segments, function(d) { return d.value; });
pie.forEach(function(d) { d.maxVal = maxValue; });
return segments;
})
.enter()
.append("svg:path")
.attr("d", arc.innerRadius(function(d) { return d.maxVal * 0.6; })
.outerRadius(function(d) { return d.maxVal; }))
// etc

Resources