Updatable chord diagram - javascript

I am working on a D3 chord diagram and want to have an update function.
This is the code I have at the moment
// Genres, check de readme daar staat visueel hoe je dit uitleest.
var data = [
[9962, 1196, 94, 93, 18],
[1196, 9102, 11, 343, 169],
[94, 11, 7143, 138, 32],
[93, 343, 138, 6440, 75],
[18, 169, 32, 75, 4886]
]
var genres = ["Psychologischverhaal", "Thriller", "Detective", "Romantischverhaal", "Sciencefiction"]
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
outerRadius = Math.min(width, height) * 0.5 - 40,
innerRadius = outerRadius - 30;
// Zet getallen naar 1K ipv 1000
var formatValue = d3.formatPrefix(",.0", 1e3);
var chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.ascending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon()
.radius(innerRadius);
var color = d3.scaleOrdinal()
.range(["#ed0b0b", "#03aa24", "#f2ae04", "#1f03f1", "#e1ed04"]);
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.datum(chord(data));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("id", function(d, i) { return "group" + d.index; })
.attr("d", arc)
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
group.append("title").text(function(d) {
return groupTip(d);
});
group.append("text")
.attr("x", 6)
.attr("dy", 15)
.append("textPath")
.attr("xlink:href", function(d) { return "#group" + d.index; })
.text(function(chords, i){return genres[i];})
.style("fill", "black");
var groupTick = group.selectAll(".group-tick")
.data(function(d) { return groupTicks(d, 1e3); })
.enter().append("g")
.attr("class", "group-tick")
.attr("transform", function(d) { return "rotate(" + (d.angle * 180 / Math.PI - 90) + ") translate(" + outerRadius + ",0)"; });
groupTick.append("line")
.attr("x1", 1)
.attr("y1", 0)
.attr("x2", 5)
.attr("y2", 0)
.style("stroke", "#000")
groupTick
.filter(function(d) { return d.value % 1e3 === 0; })
.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI ? "rotate(180) translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.text(function(d) { return formatValue(d.value); });
var ribbons = g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) { return chords; })
.enter().append("path")
.attr("d", ribbon)
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); })
ribbons.append("title").
text(function(d){return chordTip(d);});
// Returns an array of tick angles and values for a given group and step.
function groupTicks(d, step) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, step).map(function(value) {
return {value: value, angle: value * k + d.startAngle};
});
}
function fade(opacity) {
return function(d, i) {
ribbons
.filter(function(d) {
return d.source.index != i && d.target.index != i;
})
.transition()
.style("opacity", opacity);
};
}
function chordTip(d){
var j = d3.formatPrefix(",.0", 1e1)
return "Aantal boeken met genres:\n"
+ genres[d.target.index] + " en " + genres[d.source.index] + ": " + j(d.source.value)
}
function groupTip(d) {
var j = d3.formatPrefix(",.0", 1e1)
return "Totaal aantal boeken met het genre " + genres[d.index] + ":\n" + j(d.value)
}
and
<body>
<h1>Boeken met enkele & dubbele genres</h1>
<button id="doubleGenre">Alleen dubbele genres</button>
<button id="reset">Reset</button>
<svg width="960" height="900"></svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="assets/index.js"></script>
This is the result what I have now :
I want to update the chord when a user clicks on the button Alleen dubbele genres so it becomes like this :
So I want to delete the chords to it self so the data looks like :
var data = [
[1196, 94, 93, 18],
[1196, 11, 343, 169],
[94, 11, 138, 32],
[93, 343, 138, 75],
[18, 169, 32, 75]
]
And if a user clicks on the button reset I want to go back to the original view. Is there anyone who can help me with this?

Here is a link to the simplified version of your example with transitions: https://stackblitz.com/edit/q53412789
If you want to remove chords to self, you should replace values on diagonal to zeros (not just delete them: matrix must remain square):
const data2 = [
[0, 1196, 94, 93, 18],
[1196, 0, 11, 343, 169],
[94, 11, 0, 138, 32],
[93, 343, 138, 0, 75],
[18, 169, 32, 75, 0]
]
As #rioV8 suggested, the first step is to wrap code for drawing and updating the chart into a function (I've ommited code for ticks and labels for brevity, the principle is the same for them):
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
var ribbons = g.append("g");
function update(data) {
const chords = chord(data);
const ribbonsUpdate = ribbons.selectAll("path")
.data(chords, ({source, target}) => source.index + '-' + target.index)
const duration = 3000;
ribbonsUpdate
.transition()
.duration(duration)
.attr("d", ribbon)
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); })
ribbonsUpdate
.enter()
.append("path")
.attr("opacity", 0)
.attr("d", ribbon)
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); })
.transition()
.duration(duration)
.attr('opacity', 1)
ribbonsUpdate
.exit()
.transition()
.duration(duration)
.attr("opacity", 0)
.remove();
}
update(data1);
I've replaced combination of .datum(val) and .data(fun) in your code to single .data(vals). It is not required, but my opinion is that the latter is more common in d3 community.
The second argument to .data is the key function. It ensures, that during transition each path maps to itself in the new data (the number of chords is not equal: we removed chords to itself).
If you do not need animated transitions, the code is even simplier:
function simpleUpdate(data) {
const chords = chord(data);
const ribbonsUpdate = ribbons.selectAll("path")
.data(chords, ({source, target}) => source.index + '-' + target.index)
ribbonsUpdate
.enter().append("path")
.merge(ribbonsUpdate)
.attr("d", ribbon)
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); })
ribbonsUpdate.exit().remove();
}

Related

Insert text inside Circle in D3 chart

I want to insert some text inside my Circle which is plot in bubble chart using D3.js.
I am able to draw circle in svg as per the data provided to it, but facing a problem while append text to it.
below is my code:
<script type="text/javascript">
var sampleData = [{"x": 8,"y": 1}, {"x": 2,"y": 1}, {"x": 4,"y": 1},{"x": 5,"y": 1}];
// {"x": 6,"y": 40}, {"x": 8,"y": 100}, {"x": 10,"y": 60}];
$(function() {
InitChart();
});
function InitChart() {
// Chart creation code goes here
var vis = d3.select("#svgVisualize");
var xRange = d3.scale.linear().range([40, 400]).domain([0,10]);
var yRange = d3.scale.linear().range([200, 40]).domain([0,2]);
/* var xRange = d3.scale.linear().range([40, 400]).domain([d3.min(sampleData, function(d) {
return (d.x);
}), d3.max(sampleData, function(d) {
return d.x;
})]);
var yRange = d3.scale.linear().range([400, 40]).domain([d3.min(sampleData, function(d) {
return d.y;
}), d3.max(sampleData, function(d) {
return d.y;
})]); */
var xAxis = d3.svg.axis().scale(xRange).ticks(2);
var yAxis = d3.svg.axis().scale(yRange).ticks(2).orient("left");
vis.append("svg:g").call(xAxis).attr("transform", "translate(0,200)");
vis.append("svg:g").call(yAxis).attr("transform", "translate(40,0)");
var circles = vis.selectAll("circle").data(sampleData);
circles
.enter()
.insert("circle")
.attr("cx", function(d) { return xRange (d.x); })
//.attr("cy", function(d) { return yRange (d.y); })
.attr("cy", function(d) { return yRange (d.y); })
.attr("r", function(d) { return Math.log(d.x) * 30; })
.attr("stroke","black")
.style("fill", "yellow");
var text = vis.selectAll("text")
.data(sampleData)
.enter()
.insert("text");
//Add SVG Text Element Attributes
var textLabels = text
.attr("x", function(d) { return d.cx; })
.attr("y", function(d) { return d.cy; })
.text( function (d) { return "( " + d.cx + ", " + d.cy +" )"; })
.attr("font-family", "sans-serif")
.attr("font-size", "20px")
.attr("fill", "red");
}
</script>
<body>
<svg id="svgVisualize" width="500" height="250" style="border:1px solid Red;"></svg>
</body>
Can anyone suggest what is the problem with above code?
Thanks
When you do this:
var text = vis.selectAll("text")
.data(sampleData)
.enter()
.insert("text");
You are selecting <text> elements that already exist in that SVG (in your case, the axes' ticks). Because of that, your "enter" selection is empty.
Solution: select something that doesn't exist, like null:
var text = vis.selectAll(null)
.data(sampleData)
.enter()
.insert("text");
Here is the updated code:
var sampleData = [{
"x": 8,
"y": 1
}, {
"x": 2,
"y": 1
}, {
"x": 4,
"y": 1
}, {
"x": 5,
"y": 1
}];
var vis = d3.select("svg");
var xRange = d3.scale.linear().range([40, 400]).domain([0, 10]);
var yRange = d3.scale.linear().range([200, 40]).domain([0, 2]);
var xAxis = d3.svg.axis().scale(xRange).ticks(2);
var yAxis = d3.svg.axis().scale(yRange).ticks(2).orient("left");
vis.append("svg:g").call(xAxis).attr("transform", "translate(0,200)");
vis.append("svg:g").call(yAxis).attr("transform", "translate(40,0)");
var circles = vis.selectAll("circle").data(sampleData);
circles
.enter()
.append("circle")
.attr("cx", function(d) {
return xRange(d.x);
})
//.attr("cy", function(d) { return yRange (d.y); })
.attr("cy", function(d) {
return yRange(d.y);
})
.attr("r", function(d) {
return Math.log(d.x) * 30;
})
.attr("stroke", "black")
.style("fill", "yellow");
var text = vis.selectAll(null)
.data(sampleData)
.enter()
.append("text");
var textLabels = text
.attr("x", function(d) {
return xRange(d.x);
})
.attr("text-anchor", "middle")
.attr("y", function(d) {
return yRange(d.y);
})
.text(function(d) {
return "( " + d.x + ", " + d.y + " )";
})
.attr("font-family", "sans-serif")
.attr("font-size", "10px")
.attr("fill", "red");
line, path{
fill: none;
stroke: black;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<svg width="400" height="220"></svg>
PS: Don't use insert, use append instead.
A better way of doing this is to use svg groups, then you can position both the circles and the text together:
var join = vis.selectAll(".points").data(sampleData);
var groups = join
.enter()
.append("g")
.attr("transform", function(d) { return "translate(" + [d.x, d.y] + ")"; });
.attr("cx", function(d) { return xRange (d.x); })
groups.append("circle")
.attr("r", function(d) { return Math.log(d.x) * 30; })
.attr("stroke","black")
.style("fill", "yellow");
groups.append("text")
.data(sampleData)
.text( function (d) { return "( " + d.cx + ", " + d.cy +" )"; })
.attr("font-family", "sans-serif")
.attr("font-size", "20px")
.attr("fill", "red");

How to make a clickable transition bar graph in d3 v4?

How to make a clickable transition bar graph in d3 v4?
Current code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: A bar chart that transitions to new data!</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<p>Click on this text to update the chart with new data values (once).</p>
<script type="text/javascript">
//Width and height
var w = 600;
var h = 250;
var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
var xScale = d3.scaleBand()
.rangeRound([0, w])
.padding(0.05);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset)])
.range([0, h]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create bars
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d * 10) + ")";
});
//Create labels
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(i) + xScale.bandwidth() / 2;
})
.attr("y", function(d) {
return h - yScale(d) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white");
//On click, update with new data
d3.select("p")
.on("click", function() {
//New values for dataset
dataset = [ 11, 12, 15, 20, 18, 17, 16, 18, 23, 25,
5, 10, 13, 19, 21, 25, 22, 18, 15, 13 ];
//Update all rects
svg.selectAll("rect")
.data(dataset)
.transition() // <-- This makes it a smooth transition!
.attr("y", function(d) {
return h - yScale(d);
})
.attr("height", function(d) {
return yScale(d);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d * 10) + ")";
});
//Update all labels
svg.selectAll("text")
.data(dataset)
.text(function(d) {
return d;
})
.attr("x", function(d, i) {
return xScale(i) + xScale.band() / 2;
})
.attr("y", function(d) {
return h - yScale(d) + 14;
});
});
</script>
</body>
</html>
Code above from:
https://github.com/alignedleft/d3-book/blob/master/chapter_09/05_transition.html
http://examples.oreilly.com/0636920026938/chapter_09/05_transition.html
I am getting errors after switching the code to v4. I fixed the errors I knew about but now I am getting these one errors in the JavaScript console:
Error: attribute x: Expected length, "NaN".
You are not setting the domain of the x scale:
var xScale = d3.scaleBand()
.domain(d3.range(dataset.lengh))
.rangeRound([0, w])
.padding(0.1);
Also, pay attention to xScale.band(), which doesn't exist: it should be xScale.bandwidth() instead.
Here is a working code, with the domain:
var w = 600;
var h = 250;
var dataset = [5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25
];
var xScale = d3.scaleBand()
.domain(d3.range(dataset.length))
.rangeRound([0, w])
.padding(0.1);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset)])
.range([0, h]);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create bars
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d);
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d * 10) + ")";
});
//Create labels
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(i) + xScale.bandwidth() / 2;
})
.attr("y", function(d) {
return h - yScale(d) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white");
//On click, update with new data
d3.select("p")
.on("click", function() {
//New values for dataset
dataset = [11, 12, 15, 20, 18, 17, 16, 18, 23, 25,
5, 10, 13, 19, 21, 25, 22, 18, 15, 13
];
//Update all rects
svg.selectAll("rect")
.data(dataset)
.transition() // <-- This makes it a smooth transition!
.attr("y", function(d) {
return h - yScale(d);
})
.attr("height", function(d) {
return yScale(d);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d * 10) + ")";
});
//Update all labels
svg.selectAll("text")
.data(dataset)
.text(function(d) {
return d;
})
.attr("y", function(d) {
return h - yScale(d) + 14;
});
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<p>Click on this text to update the chart with new data values (once).</p>

D3.JS: How to animate lines

Relatively new to D3, an have a question regarding the translation (animation) of lines. I animate circles using the following code:
var data = d3.range(100).map(function() {
return new agent(
0,
0,
(Math.random()-0.5)*.05,
(Math.random()-0.5)*.05,
'rgb(255, 0, 213)');
});
var circles = canvas.selectAll('circle')
.data(data)
.enter().append('circle')
.attr('cx', function(d) {
return d.x;
})
.attr('cy', function(d) {
return d.y;
})
.attr('r', 5)
.attr('fill', function(d) {
return d.color;
});
circles.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
});
The last 3 lines in particular are of interest to me - is there an equivalent translate for lines?
There are several possible options to animate lines in D3, e.g.
Changing the underlying data
svg.select(".line")
.duration(animationLength)
.attr("d", valueline(lineData))
valueLine is a d3.svg.line() function.
Filling the line from start to end via stroke-dashoffset
var lineGraph = svg.append("path")
.attr("class", "line")
.attr("d", lineFunction(lineData))
.attr("stroke-dasharray", 200 + " " + 200)
.attr("stroke-dashoffset", 200)
.attr("fill", "none")
.transition()
.duration(animationLength)
.ease("linear")
.attr("stroke-dashoffset", 0);
Using transform to move the line
svg.select(".line")
.duration(animationLength)
.attr("transform", "translate(" + 100 * Math.random() + "," + 100 * Math.random() + ")");
var animationLength = 2000;
var lineData = [{
"x": 1,
"y": 5
}, {
"x": 20,
"y": 20
}, {
"x": 40,
"y": 10
}, {
"x": 60,
"y": 40
}, {
"x": 80,
"y": 5
}, {
"x": 100,
"y": 60
}];
var lineFunction = d3.svg.line()
.x(function (d) {
return d.x;
})
.y(function (d) {
return d.y;
})
.interpolate("linear");
var valueline = d3.svg.line()
.x(function (d) {
return d.x * (Math.random() + 0.5);
})
.y(function (d) {
return d.y * (Math.random() + 0.5);
});
var svg = d3.select("#line")
.append("svg")
.attr("width", 200)
.attr("height", 200);
var lineGraph = svg.append("path")
.attr("class", "line")
.attr("d", lineFunction(lineData))
.attr("stroke", "blue")
.attr("stroke-width", 2)
.attr("stroke-dasharray", 200 + " " + 200)
.attr("stroke-dashoffset", 200)
.attr("fill", "none")
.transition()
.duration(animationLength)
.ease("linear")
.attr("stroke-dashoffset", 0);
svg = d3.select("body").transition();
svg.select(".line")
.delay(animationLength)
.duration(animationLength)
.attr("d", valueline(lineData))
.attr("transform", "translate(" + 100 * Math.random() + "," + 100 * Math.random() + ")");
<script src="https://d3js.org/d3.v3.min.js"></script>
<div id="line"></div>

Change single chord color in chord diagram using D3.js

D3 and Javascript newbie here. I'd like to change the color of a single chord in a chord diagram that is rendered with D3. Ideally, this color can be arbitrary, with no relationship to the source/destination entities of the chord.
How do I identify a single chord so I can later access it to fill it?
Here's an image (poorly edited with an image editor) with the desired effect (green chord).
var matrix = [
[11975, 5871, 8916, 2868],
[ 1951, 10048, 2060, 6171],
[ 8010, 16145, 8090, 8045],
[ 1013, 990, 940, 6907]
];
var chord = d3.layout.chord()
.padding(.05)
.sortSubgroups(d3.descending)
.matrix(matrix);
var width = 960,
height = 500,
innerRadius = Math.min(width, height) * .41,
outerRadius = innerRadius * 1.1;
var fill = d3.scale.ordinal()
.domain(d3.range(4))
.range(["#000000", "#FFDD89", "#957244", "#F26223"]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
svg.append("g").selectAll("path")
.data(chord.groups)
.enter().append("path")
.style("fill", function(d) { return fill(d.index); })
.style("stroke", function(d) { return fill(d.index); })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
var ticks = svg.append("g").selectAll("g")
.data(chord.groups)
.enter().append("g").selectAll("g")
.data(groupTicks)
.enter().append("g")
.attr("transform", function(d) {
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + outerRadius + ",0)";
});
ticks.append("line")
.attr("x1", 1)
.attr("y1", 0)
.attr("x2", 5)
.attr("y2", 0)
.style("stroke", "#000");
ticks.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI ? "rotate(180)translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.text(function(d) { return d.label; });
svg.append("g")
.attr("class", "chord")
.selectAll("path")
.data(chord.chords)
.enter().append("path")
.attr("d", d3.svg.chord().radius(innerRadius))
.style("fill", function(d) { return fill(d.target.index); })
.style("opacity", 1)
.on("mouseover", function(){
d3.select(this).style("opacity", 0.3);
})
.on("mouseout", function(){
d3.select(this).style("opacity", 1);
});
// Returns an array of tick angles and labels, given a group.
function groupTicks(d) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, 1000).map(function(v, i) {
return {
angle: v * k + d.startAngle,
label: i % 5 ? null : v / 1000 + "k"
};
});
}
// Returns an event handler for fading a given chord group.
function fade(opacity) {
return function(g, i) {
svg.selectAll(".chord path")
.filter(function(d) { return d.source.index != i && d.target.index != i; })
.transition()
.style("opacity", opacity);
};
}
body {
font: 10px sans-serif;
}
.chord path {
fill-opacity: .67;
stroke: #000;
stroke-width: .5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I've just added functionality for mouse over and mouse out,
svg.append("g")
.attr("class", "chord")
.selectAll("path")
.data(chord.chords)
.enter().append("path")
.attr("d", d3.svg.chord().radius(innerRadius))
.style("fill", function(d) { return fill(d.target.index); })
.style("opacity", 1)
.on("mouseover", function(){
d3.select(this).style("opacity", 0.3);
})
.on("mouseout", function(){
d3.select(this).style("opacity", 1);
});
In the above code see the mouseover and mouseout callbacks,
Here I'm just changing the opacity, if you want to change the color, use fill attribute to fill the color.
Hope you are looking for this.
If not ask me for more.
:D

Displaying total value for each item in a chord chart

I was working on the chord diagram and I am unable to show the total value for each product. I want it to display the total count for each category when I hover over the radial arc for a particular category. The example is taken from http://bl.ocks.org/mbostock/4062006. Any prompt help would be greatly appreciated. Thank you :)
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.chord path {
fill-opacity: .67;
stroke: #000;
stroke-width: .5px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// From http://mkweb.bcgsc.ca/circos/guide/tables/
var matrix = [
[11975, 5871, 8916, 2868],
[ 1951, 10048, 2060, 6171],
[ 8010, 16145, 8090, 8045],
[ 1013, 990, 940, 6907]
];
var chord = d3.layout.chord()
.padding(.05)
.sortSubgroups(d3.descending)
.matrix(matrix);
var width = 960,
height = 500,
innerRadius = Math.min(width, height) * .41,
outerRadius = innerRadius * 1.1;
var fill = d3.scale.ordinal()
.domain(d3.range(4))
.range(["#000000", "#FFDD89", "#957244", "#F26223"]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
svg.append("g").selectAll("path")
.data(chord.groups)
.enter().append("path")
.style("fill", function(d) { return fill(d.index); })
.style("stroke", function(d) { return fill(d.index); })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
var ticks = svg.append("g").selectAll("g")
.data(chord.groups)
.enter().append("g").selectAll("g")
.data(groupTicks)
.enter().append("g")
.attr("transform", function(d) {
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + outerRadius + ",0)";
});
ticks.append("line")
.attr("x1", 1)
.attr("y1", 0)
.attr("x2", 5)
.attr("y2", 0)
.style("stroke", "#000");
ticks.append("text")
.attr("x", 8)
.attr("dy", ".35em")
.attr("transform", function(d) { return d.angle > Math.PI ? "rotate(180)translate(-16)" : null; })
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.text(function(d) { return d.label; });
svg.append("g")
.attr("class", "chord")
.selectAll("path")
.data(chord.chords)
.enter().append("path")
.attr("d", d3.svg.chord().radius(innerRadius))
.style("fill", function(d) { return fill(d.target.index); })
.style("opacity", 1)
.append("svg:title").text(function(d, i) { return "Value : " + d.source.value });;
// Returns an array of tick angles and labels, given a group.
function groupTicks(d) {
var k = (d.endAngle - d.startAngle) / d.value;
return d3.range(0, d.value, 1000).map(function(v, i) {
return {
angle: v * k + d.startAngle,
label: i % 5 ? null : v / 1000 + "k"
};
});
}
// Returns an event handler for fading a given chord group.
function fade(opacity) {
return function(g, i) {
svg.selectAll(".chord path")
.filter(function(d) { return d.source.index != i && d.target.index != i; })
.transition()
.style("opacity", opacity);
};
}
</script>
`

Categories