D3 self linking edges - d3.js

I have the following code I got from the net. I am trying to build a graph that has self linking nodes.
After much struggle I was able to do it for edges linking to other nodes. Can someone plz help me to create a self linking edge?
I tried integrating the example D3 Force Layout Graph - Self linking node
But could not suceed. Please help.
And thanks in advance
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Force Layout with labels on edges</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
var w = 1400;
var h = 600;
//distance between nodes
var linkDistance=200;
var colors = d3.scale.category10();
var dataset = {
nodes: [
{name: "Car"},
{name: "Jeep"}
],
edges: [
{source: 0, target: 0}
],
methlbl: [
{name:"add(int, int)"}
]
};
var svg = d3.select("body").append("svg").attr({"width":w,"height":h});
var force = d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.size([w,h])
.linkDistance([linkDistance])
.charge([-500])
.theta(0.1)
.gravity(0.05)
.start();
var edges = svg.selectAll("line")
.data(dataset.edges)
.enter()
.append("line")
.attr("id",function(d,i) {return 'edge'+i})
.attr('marker-end','url(#arrowhead)')
.style("stroke","#ccc")
.style("pointer-events", "none");
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
.attr({"r":15})
.style("fill",function(d,i){return colors(4);})
.call(force.drag)
var nodelabels = svg.selectAll(".nodelabel")
.data(dataset.nodes)
.enter()
.append("text")
.attr({"x":function(d){return d.x;},
"y":function(d){return d.y;},
"class":"nodelabel",
"stroke":"black"})
.text(function(d){return d.name;});
var edgepaths = svg.selectAll(".edgepath")
.data(dataset.edges)
.enter()
.append('path')
.attr({'d': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y},
'class':'edgepath',
'fill-opacity':0,
'stroke-opacity':0,
'fill':'blue',
'stroke':'red',
'id':function(d,i) {return 'edgepath'+i}})
.style("pointer-events", "none");
var edgelabels = svg.selectAll(".edgelabel")
.data(dataset.edges)
.enter()
.append('text')
.style("pointer-events", "none")
.attr({'class':'edgelabel',
'id':function(d,i){return 'edgelabel'+i},
'dx':40,
'dy':-10,
'font-size':20,
'fill':'#aaa'});
edgelabels.append('textPath')
.attr('xlink:href',function(d,i) {return '#edgepath'+i})
.style("pointer-events", "none")
.text(function(d,i){return dataset.methlbl[i].name});
svg.append('defs').append('marker')
.attr({'id':'arrowhead',
'viewBox':'-0 -5 10 10',
'refX':25,
'refY':0,
//'markerUnits':'strokeWidth',
'orient':'auto',
'markerWidth':10,
'markerHeight':10,
'xoverflow':'visible'})
.append('svg:path')
.attr('d', 'M 0,-5 L 10 ,0 L 0,5')
.attr('fill', '#ccc')
.attr('stroke','#ccc');
force.on("tick", function(){
edges.attr({"x1": function(d){return d.source.x;},
"y1": function(d){return d.source.y;},
"x2": function(d){return d.target.x;},
"y2": function(d){return d.target.y;}
});
nodes.attr({"cx":function(d){return d.x;},
"cy":function(d){return d.y;}
});
nodelabels.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; });
edgepaths.attr('d', function(d) { var path='M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y;
//console.log(d)
return path});
edgelabels.attr('transform',function(d,i){
if (d.target.x<d.source.x){
bbox = this.getBBox();
rx = bbox.x+bbox.width/2;
ry = bbox.y+bbox.height/2;
return 'rotate(180 '+rx+' '+ry+')';
}
else {
return 'rotate(0)';
}
});
});
</script>
</body>
</html>

Removed unnecessary code and made some improvements. Hope following code snippet helps.
var w = 800;
var h = 400;
//distance between nodes
var linkDistance = 200;
var colors = d3.scale.category10();
var dataset = {
nodes: [{
name: "Car"
},
{
name: "Jeep"
}
],
edges: [{
source: 0,
target: 0
}],
methlbl: [{
name: "add(int, int)"
}]
};
var svg = d3.select("body").append("svg").attr({
"width": w,
"height": h
});
var force = d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.size([w, h])
.linkDistance([linkDistance])
.charge([-500])
.theta(0.1)
.gravity(0.05)
.start();
var edges = svg.selectAll("path")
.data(dataset.edges)
.enter()
.append("path")
.style("fill","none")
.attr("id", function(d, i) {
return 'edge' + i
})
.attr('marker-end', function(d) {
return d.source == d.target ? '' : 'url(#arrowhead)'
})
.style("stroke", "#ccc")
.style("pointer-events", "none");
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
.attr({
"r": 15
})
.style("fill", function(d, i) {
return colors(4);
})
.call(force.drag)
var nodelabels = svg.selectAll(".nodelabel")
.data(dataset.nodes)
.enter()
.append("text")
.attr({
"x": function(d) {
return d.x;
},
"y": function(d) {
return d.y;
},
"class": "nodelabel",
"stroke": "black"
})
.text(function(d) {
return d.name;
});
var edgelabels = svg.selectAll(".edgelabel")
.data(dataset.edges)
.enter()
.append('text')
.style("pointer-events", "none")
.attr({
'class': 'edgelabel',
'id': function(d, i) {
return 'edgelabel' + i
},
'font-size': 20,
'fill': '#aaa'
})
edgelabels.append("textPath")
.attr("xlink:href", function(d, i) {
return '#edge' + i;
})
.style("pointer-events", "none")
.text(function(d, i) {
return dataset.methlbl[i].name
});
svg.append('defs').append('marker')
.attr({
'id': 'arrowhead',
'viewBox': '-0 -5 10 10',
'refX': 25,
'refY': 0,
'orient': 'auto',
'markerWidth': 10,
'markerHeight': 10,
'xoverflow': 'visible'
})
.append('svg:path')
.attr('d', 'M 0,-5 L 10 ,0 L 0,5')
.attr('fill', '#ccc')
.attr('stroke', '#ccc');
force.on("tick", function() {
edges.attr("d", function(d) {
var x1 = d.source.x,
y1 = d.source.y,
x2 = d.target.x,
y2 = d.target.y,
dx = x2 - x1,
dy = y2 - y1,
dr = Math.sqrt(dx * dx + dy * dy),
// Defaults for normal edge.
drx = dr,
dry = dr,
xRotation = 0, // degrees
largeArc = 0, // 1 or 0
sweep = 1; // 1 or 0
// Self edge.
if (x1 === x2 && y1 === y2) {
// Fiddle with this angle to get loop oriented.
xRotation = -45;
// Needs to be 1.
largeArc = 1;
// Change sweep to change orientation of loop.
//sweep = 0;
// Make drx and dry different to get an ellipse
// instead of a circle.
drx = 30;
dry = 20;
// For whatever reason the arc collapses to a point if the beginning
// and ending points of the arc are the same, so kludge it.
x2 = x2 + 1;
y2 = y2 + 1;
}
return "M" + x1 + "," + y1 + "A" + drx + "," + dry + " " + xRotation + "," + largeArc + "," + sweep + " " + x2 + "," + y2;
});
nodes.attr({
"cx": function(d) {
return d.x;
},
"cy": function(d) {
return d.y;
}
});
edgelabels.selectAll("textPath")
.attr("xlink:href", function(d, i) {
return '#edge' + i;
})
.attr("startOffset", function(d, i) {
var arcLength = d3.select("#edge" + i).node().getTotalLength();
var textLength = d3.select("#edgelabel" + i).node().getComputedTextLength();
var offset = (arcLength - textLength) / 2;
return offset;
});
nodelabels.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
});
});
<script src="https://d3js.org/d3.v3.min.js"></script>

Related

drag grouped elements move not continuous

I try move a grouped element but after click and drag, the elements jumped away.
demo()
function demo() {
var tooltip = d3.select('body')
.append('div')
.attr('id','tooltip')
.style('position','absolute')
.style('opacity',0)
.style('background','lightsteelblue')
var svg = d3.select("body")
.append("svg")
.attr("width", 300)
.attr("height", 200)
.style("background", "#ececec")
add_grid(svg);
var data = [
{
text: "O",
x: 50,
y: 50
},
];
var g = svg.append('g')
var fontsize = 20;
var box = g.selectAll(".box")
.data(data)
.join('g')
.attr('class','box')
.attr("pointer-events", "all")
box.call(
d3.drag()
.on("start",function(event,d) {
d3.select(this).raise().classed("active", true);
d3.select('#tooltip')
.transition().duration(100)
.style('opacity', 1)
})
.on("drag",function(event,d) {
d.x = event.x
d.y = event.y
d3.select(this).attr('transform',`translate(${d.x},${d.y})`)
var desc = "(" + d.x.toFixed(1) +"," + d.y.toFixed(1) + ")"
d3.select('#tooltip')
.style('left', (event.x+2) + 'px')
.style('top', (event.y-2) + 'px')
.text(desc)
})
.on("end", function dragEnd(event,d) {
d3.select(this).classed("active", false);
d3.select('#tooltip').style('opacity', 0)}
))
.on('mouseover', function(event,d) {
})
.on('mouseout', function(event,d) {
})
.on('mousemove', function(event,d) {
})
.on("mousedown", function(){
})
.on("mouseup", function(){
});
var txt = box.append("text")
.attr("text-anchor", "middle")
.attr("dominant-baseline",'text-before-edge')//'central')//text-bottom
.attr("font-size", fontsize)
.attr("x", (d) => d.x)
.attr("y", (d) => d.y)
var tspan = txt.selectAll(".tspan")
.data((d) => d.text.split("\n"))
.join("tspan")
.attr("class", "tspan")
.attr("x", function (d) {
let x = +d3.select(this.parentNode).attr("x");
return x;
})
.attr("y", function (d,i) {
let y = +d3.select(this.parentNode).attr("y");
return y + i*fontsize * .9;
})
.text((d) => d);
box.each((d,i,n) => {
var bbox = d3.select(n[i]).node().getBBox()
var padding = 2
bbox.x -= padding
bbox.y -= padding
bbox.width += 2*padding
bbox.height += 2*padding
d.bbox = bbox
})
.attr('transform',d => `translate(${0},${-d.bbox.height/2})`)
.append('rect')
.attr('x',d => d.bbox.x)
.attr('y',d => d.bbox.y)
.attr('width', d => d.bbox.width)
.attr('height',d => d.bbox.height)
.attr('stroke','red')
.attr('fill','none')
add_dots(svg,data)
function add_dots(svg,data) {
svg.selectAll('.dots')
.data(data)
.join('circle')
.attr('class','dots')
.attr('r',2)
.attr('cx',d => d.x)
.attr('cy',d => d.y)
.attr('fill','red')
}
function add_grid(svg) {
var w = +svg.attr("width");
var step = 10;
var mygrid = function (d) {
return `M 0,${d} l ${w},0 M ${d},0 l 0,${w}`;
};
var grid = [];
for (var i = 0; i < w; i += step) {
grid.push(i);
}
svg
.append("g")
.selectAll(null)
.data(grid)
.enter()
.append("path")
.attr("d", (d) => mygrid(d))
.attr("fill", "none")
.attr("stroke", "green")
.attr("stroke-width", 0.5);
}
}
<script src="https://unpkg.com/d3#7.0.4/dist/d3.min.js"></script>

Add moving circles to transitioning nested paths in d3.js

I want to add circles to an svg for each path created by the nest so that the circles lead the drawing of the paths. Similar to this fiddle, but with nested data.
Here is some reproducible example code in d3.v4 and a runnable snippet of the paths I would like to add circles to:
var data=[{group:1,x:6,y:8},
{group:1,x:4,y:4},
{group:1,x:1,y:2},
{group:2,x:8,y:3},
{group:2,x:1,y:6},
{group:2,x:7,y:5},
{group:3,x:7,y:1},
{group:3,x:6,y:6},
{group:3,x:3,y:2}];
var height = 600
var width = 800
var svg = d3.select("body")
.append("svg")
.attr("height", "100%")
.attr("width", "100%");
var colours = ["#0000FF",
"#FF0000",
"#00FF00"
];
var line = d3.line()
.x(function(d, i) {
return d.x * 20;
})
.y(function(d, i) {
return d.y * 20;
})
.curve(d3.curveNatural);
function tweenDash() {
var l = this.getTotalLength(),
i = d3.interpolateString("0," + l, l + "," + l);
return function(t) {
return i(t);
};
}
function transition(selection) {
selection.each(function() {
d3.select(this).transition()
.duration(5000)
.attrTween("stroke-dasharray", tweenDash)
.ease(d3.easeLinear);
})
}
var dataGroup = d3.nest()
.key(function(d) {
return d.group;
})
.entries(data);
dataGroup.forEach(function(d, i) {
var path = svg.append("path")
.attr("d", line(d.values))
.attr("stroke", colours[i])
.attr("stroke-width", 1)
.attr("fill", "none");
transition(d3.selectAll("path"))
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
Using this example, I've added circles to your paths. Note that they do not follow the path perfectly, but this is covered by increasing their radius.
A couple of times, you use .forEach() or .each() to iterate over the data or the selection, but you don't need to. d3 is made to work with arrays of data at once, so you can easily apply one transformation to multiple elements, each using their own data. Getting used to that can drastically improve your developer experience.
var data = [{
group: 1,
x: 6,
y: 8
},
{
group: 1,
x: 4,
y: 4
},
{
group: 1,
x: 1,
y: 2
},
{
group: 2,
x: 8,
y: 3
},
{
group: 2,
x: 1,
y: 6
},
{
group: 2,
x: 7,
y: 5
},
{
group: 3,
x: 7,
y: 1
},
{
group: 3,
x: 6,
y: 6
},
{
group: 3,
x: 3,
y: 2
}
];
var height = 600
var width = 800
var svg = d3.select("body")
.append("svg")
.attr("height", "100%")
.attr("width", "100%");
var colours = ["#0000FF",
"#FF0000",
"#00FF00"
];
var line = d3.line()
.x(function(d, i) {
return d.x * 20;
})
.y(function(d, i) {
return d.y * 20;
})
.curve(d3.curveNatural);
function tweenDash() {
var l = this.getTotalLength(),
i = d3.interpolateString("0," + l, l + "," + l);
return function(t) {
return i(t);
};
}
function tweenCircle(i, paths) {
var path = paths
.filter(function(_, j) { return i === j; })
.node();
var l = path.getTotalLength();
return function(t) {
var p = path.getPointAtLength(t * l);
return "translate(" + [p.x, p.y] + ")";
};
}
function transition(path, circle) {
path.transition()
.duration(2000)
.attrTween("stroke-dasharray", tweenDash)
.ease(d3.easeLinear);
circle.transition()
.duration(2000)
.attrTween("transform", function(d, i) { return tweenCircle(i, path); })
.ease(d3.easeLinear);
}
var dataGroup = d3.nest()
.key(function(d) {
return d.group;
})
.entries(data);
var path = svg.selectAll('path')
.data(dataGroup)
.enter()
.append("path")
.attr("d", function(d) { return line(d.values); })
.attr("stroke", function(d, i) { return colours[i]; })
.attr("stroke-width", 1)
.attr("fill", "none");
var circle = svg.selectAll('circle')
.data(dataGroup)
.enter()
.append("circle")
.attr("fill", function(d, i) { return colours[i]; })
.attr("transform", function(d) {
const start = d.values[0];
return "translate(" + [start.x, start.y] + ")"; })
.attr("r", 8);
transition(path, circle);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>

How can I refactor a d3 pie to accept more or less data points?

I have a project that almost works the way I want. When a smaller dataset is added, slices are removed. It fails when a larger dataset is added. The space for the arc is added but no label or color is added for it.
This is my enter() code:
newArcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
What am I doing wrong?
I've fixed the code such that it works now:
// Tween Function
var arcTween = function(a) {
var i = d3.interpolate(this.current || {}, a);
this.current = i(0);
return function(t) {
return arc(i(t));
};
};
// Setup all the constants
var duration = 500;
var width = 500
var height = 300
var radius = Math.floor(Math.min(width / 2, height / 2) * 0.9);
var colors = ["#d62728", "#ff9900", "#004963", "#3497D3"];
// Test Data
var d2 = [{
label: 'apples',
value: 20
}, {
label: 'oranges',
value: 50
}, {
label: 'pears',
value: 100
}];
var d1 = [{
label: 'apples',
value: 100
}, {
label: 'oranges',
value: 20
}, {
label: 'pears',
value: 20
}, {
label: 'grapes',
value: 20
}];
// Set the initial data
var data = d1
var updateChart = function(dataset) {
arcs = arcs.data(donut(dataset), function(d) { return d.data.label });
arcs.exit().remove();
arcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
arcs.transition()
.duration(duration)
.attrTween("d", arcTween);
sliceLabel = sliceLabel.data(donut(dataset), function(d) { return d.data.label });
sliceLabel.exit().remove();
sliceLabel.enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
})
.text(function(d) {
return d.data.label;
});
sliceLabel.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
});
};
var color = d3.scale.category20();
var donut = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.innerRadius(radius * .4)
.outerRadius(radius);
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var arc_grp = svg.append("g")
.attr("class", "arcGrp")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var label_group = svg.append("g")
.attr("class", "lblGroup")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var arcs = arc_grp.selectAll("path");
var sliceLabel = label_group.selectAll("text");
updateChart(data);
// returns random integer between min and max number
function getRand() {
var min = 1,
max = 2;
var res = Math.floor(Math.random() * (max - min + 1) + min);
//console.log(res);
return res;
}
// Update the data
setInterval(function(model) {
var r = getRand();
return updateChart(r == 1 ? d1 : d2);
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Dots are not appending to right graph?

I am having a problem with my code where the circle nodes that I have created do not seem to be appending themselves to the graph. The debugger isn't pulling up any errors, so it seems like it's a logic issue.
Here's what is looks like:
(dot)
|
|
|
|
|
| <--(where dot should be)
|
__________________________________________
^
|
graph
And here's my code:
<script>
var slider = $("#myRange").val();;
var xtwo;
var xone;
var xzero;
var firstx = -1;
var firsty = 1;
var secondx = 2;
var secondy = 4;
var lineData = [];
var nodes = [];
//updates coefficients
function updateXs() {
xtwo = (75 - slider) / 50;
xone = (slider - 25) / 50;
xzero = (slider - 25) / 25;
}
//gets corresponding y from x and coefficients
function getY(xval) {
return (xval * xval * xtwo + xval * xone + xzero);
}
function displayVals() {
document.getElementById("demo").innerHTML = slider + " " + xtwo + " " + xone + " " + xzero + " " + lineData;
}
function updateLineData() {
//resets and fills points
lineData = [];
for (i = (firstx - 1); i < (secondx + 2); i++) {
lineData.push({
x: i,
y: getY(i)
});
}
}
//makes dots for static points
function makeDots(xvalue, xvalue2) {
nodes = [{
x: xvalue,
y: getY(xvalue)
}, {
x: xvalue2,
y: getY(xvalue2)
}]
}
function makeLine() {}
$(document).ready(function() {
updateXs();
updateLineData();
displayVals();
var vis = d3.select('#visual'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function(d) {
return d.x;
}), d3.max(lineData, function(d) {
return d.x;
})]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function(d) {
return d.y;
}), d3.max(lineData, function(d) {
return d.y;
})]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient("left")
.tickSubdivide(true);
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.call(yAxis);
var lineFunc = d3.svg.line()
.x(function(d) {
return xRange(d.x);
})
.y(function(d) {
return yRange(d.y);
})
.interpolate('basis');
vis.append("svg:path")
.attr("d", lineFunc(lineData))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("fill", "none");
makeDots(firstx, secondx);
//puts in dots
vis.selectAll("circle.nodes")
.data(nodes)
.enter()
.append("circle")
.attr("cx", function(d) {
console.log(d.x)
return 200;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", "10px")
.attr("fill", "black")
//updates when slider changes
$("#myRange").change(function() {
slider = $("#myRange").val();
updateXs();
updateLineData();
displayVals();
});
});
</script>
Please help and thanks in advance. Also, I was wondering if I could get some tips on how to make the line move using the .change function
You haven't applied your scale function to your dots:
vis.selectAll(".nodes")
.data(nodes)
.enter().append("circle")
.attr("class", "nodes")
.attr("cx", function (d) {
return xRange(d.x); //<-- convert from user space to pixel space
})
.attr("cy", function (d) {
return yRange(d.y); //<-- convert from user space to pixel space
});
To make your line update, you need to select it and change the d attribute:
d3.select(".myLine") //<-- select it by some unique class
.attr("d", lineFunc(lineData)); //<-- update the d attribute
To get a smooth curve without interpolation, just supply more points. See udpated fiddle.
Fiddle here.

D3.js stacked Barchart Error

I Need your help... why is this Chart not running.. Error in Console (d3.v2.js Zeile 2396):
TypeError: string.substring is not a function
var n = d3_time_numberRe.exec(string.substring(i, i + 2));
Could anybody help me please?
<script type="text/javascript">
var w = 960,
h = 500,
p = [20, 50, 30, 20],
x = d3.scale.ordinal().rangeRoundBands([0, w - p[1] - p[3]]),
y = d3.scale.linear().range([0, h - p[0] - p[2]]),
z = d3.scale.ordinal().range(["lightpink", "darkgray", "lightblue"]),
parse = d3.time.format("%m/%Y").parse,
format = d3.time.format("%b");
var data = [
[
new Date('1991-01-18T00:00:00'),
52.380001068115234,
28.56999969482422,
10.0
],
[
new Date('1994-11-17T00:00:00'),
57.88999938964844,
21.049999237060547,
10.0
]
];
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
// Transpose the data into layers by cause.
var causes = d3.layout.stack()([data[1], data[2], data[3]].map(function(cause) {
return data.map(function(d) {
return {x: parse(d[0]), y: +d[cause]};
});
}));
// Compute the x-domain (by date) and y-domain (by top).
x.domain(causes[0].map(function(d) { return d.x; }));
y.domain([0, d3.max(causes[causes.length - 1], function(d) { return d.y0 + d.y; })]);
// Add a group for each cause.
var cause = svg.selectAll("g.cause")
.data(causes)
.enter().append("svg:g")
.attr("class", "cause")
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// Add a rect for each date.
var rect = cause.selectAll("rect")
.data(Object)
.enter().append("svg:rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand());
// Add a label per date.
var label = svg.selectAll("text")
.data(x.domain())
.enter().append("svg:text")
.attr("x", function(d) { return x(d) + x.rangeBand() / 2; })
.attr("y", 6)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(format);
// Add y-axis rules.
var rule = svg.selectAll("g.rule")
.data(y.ticks(5))
.enter().append("svg:g")
.attr("class", "rule")
.attr("transform", function(d) { return "translate(0," + -y(d) + ")"; });
rule.append("svg:line")
.attr("x2", w - p[1] - p[3])
.style("stroke", function(d) { return d ? "#fff" : "#000"; })
.style("stroke-opacity", function(d) { return d ? .7 : null; });
rule.append("svg:text")
.attr("x", w - p[1] - p[3] + 6)
.attr("dy", ".35em")
.text(d3.format(",d"));
</script>
The problem is here:
var causes = d3.layout.stack()([data[1], data[2], data[3]].map(function(cause) {
return data.map(function(d) {
return {x: parse(d[0]), y: +d[cause]};
});
}));
d[0] is already a date object - new Date('1991-01-18T00:00:00') - and parse is expecting a string.
Instead, pass d[0] directly:
return {x: d[0], y: +d[cause]};
Sidenote: check out the debugging tools for chrome. Most of the error messages you get working with d3 will not give very useful messages (like "TypeError: string.substring is not a function") and being able to look through the stack is extremely helpful.

Resources