d3.js path and tooltip issue - svg

im new to this d3.js stuff and i'm willing to learn it, i'm doing a site and i need my path to be open at the end and i want to add some tooltips to it, i've done read a few documents over the web and none made sense in my code, can anyone shed some light into it please, thanks in advance!! :)
my code is the following, it generates two graphics:
function getDateX(day2)
{
day = new String(day2);
return new Date(day.substring(0, 4) + '-' + day.substring(4, 6) + '-' + day.substring(6, 8));
}
function plotData(id, data, type)
{
var margin = {top: 40, right: 15, bottom: 30, left: 55},
width = 455,
height = 270 - margin.top - margin.bottom;
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(data.length < 7 ? data.length : (data.length > 14 ? data.length / 5 : data.length / 3) ).tickFormat(d3.time.format("%d/%m"));
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);
var area = d3.svg.area()
.x(function(d) { return x(getDateX(d.day)); })
.y0(height)
.y1(function(d) { return y( type == 'score' ? parseFloat(d.score) : d.good + d.neutral + d.bad)});
var svg = d3.select("#" + id)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.data(data);
x.domain(d3.extent(data, function(d) { return getDateX(d.day); }));
var min = d3.min(data, function(d) { return parseFloat(d.score); });
if(min > 6)
min = 6;
else if(min > 1)
min--;
if(type == 'score')
y.domain([min, 10]);
else
y.domain([0, d3.max(data, function(d) { return d.good + d.neutral + d.bad; })]);
svg.append("path").datum(data).attr("class", "area").attr("d", area);
svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);
svg.append("g").attr("class", "y axis").call(yAxis);
}
var scores =
[
<%
boolean appendComma = false;
for(MovieGrade grade : info.getGrades())
{
if(appendComma)
out.print(",");
else
appendComma = true;
out.print("{\"day\":" + grade.getDay() + ", \"good\":" + grade.getGood() + ", \"neutral\":" + grade.getNeutral() + ", \"bad\":" + grade.getBad() + ", \"score\":\"" + grade.getScore() + "\"}");
}
%>
];
plotData('evolucao-score', scores, 'score');
plotData('evolucao-comments', scores, 'comments');

Related

D3.js curved node label

I want to exchange the current node label with a curved label, placed above the node. I miss knowledge regarding, how to use paths proper and how to append a text to a path. Maybe you guys could enlight me.
The text should have the same curve as the node itself.
UPDATE
I implemented the solution but it seems either the path or textPath is to short. Its possible to adjust the innerRadius, outerRadius as well as the startAngle and endAngle. I guess the startAngle and endAngle define the length of the arc. No matter which value I test, the full label isn´t shown.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Curved Text</title>
<!-- Script Import -->
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<style>
body {
background: white;
overflow: hidden;
margin: 0px;
}
circle {
fill: whitesmoke;
stroke-width: 2;
stroke: black;
transform: scale(1);
transition: all 200ms ease-in-out;
}
circle:hover {
transform: scale(1.5)
}
</style>
<body>
<svg id="svg"></svg>
<script>
var width = window.innerWidth,
height = window.innerHeight,
radius = 40, // circle radius
offset = 35; // arrow offset
const svg = d3.select('svg')
.attr("width", width)
.attr("height", height)
.call(d3.zoom().on("zoom", function (event) {
svg.attr("transform", event.transform)
}))
.append("g")
var graph = {
"nodes": [
{ "id": "Stackoverflow" },
{ "id": "Reddit" },
{ "id": "Google" }
],
"links": [
{ "source": "Stackoverflow", "target": "Reddit"},
{ "source": "Reddit", "target": "Google"},
{ "source": "Google", "target": "Stackoverflow"},
]
}
const arc = d3.arc()
.innerRadius(radius + 5)
.outerRadius(radius + 5)
.startAngle(-Math.PI / 15)
.endAngle(Math.PI / 2 )
svg.append("defs")
.append("path")
.attr("id", "curvedLabelPath")
.attr("d", arc())
svg.append('defs').append('marker')
.attr('id', 'arrowhead')
.attr('viewBox', '-0 -5 10 10')
.attr('refX', 0)
.attr('refY', 0)
.attr('orient', 'auto')
.attr('markerWidth', 10)
.attr('markerHeight', 10)
.attr('xoverflow', 'visible')
.append('svg:path')
.attr('d', 'M 0,-5 L 10 ,0 L 0,5')
.attr('fill', '#999')
.style('stroke', 'none');
var linksContainer = svg.append("g").attr("class", "linksContainer")
var nodesContainer = svg.append("g").attr("class", "nodesContainer")
const simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) { return d.id }).distance(250))
.force("charge", d3.forceManyBody().strength(-1000))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collision", d3.forceCollide().radius(radius))
link = linksContainer.selectAll("g")
.data(graph.links)
.join("g")
.attr("curcor", "pointer")
link = linksContainer.selectAll("path")
.data(graph.links)
.join("path")
.attr("id", function (_, i) {
return "path" + i
})
.attr("stroke", "#000000")
.attr("opacity", 0.75)
.attr("stroke-width", 3)
.attr("fill", "transparent")
.attr("marker-end", "url(#arrowhead)")
node = nodesContainer.selectAll(".node")
.data(graph.nodes, d => d.id)
.join("g")
.attr("cursor", "pointer")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("mouseenter", function (d) {
d3.select(this).select("text").attr("font-size", 15)
})
node.selectAll("circle")
.data(d => [d])
.join("circle")
.attr("r", radius)
node.append("text")
.append("textPath")
.attr("href", "#curvedLabelPath")
.attr("text-anchor", "middle")
.attr("startoffset", "5%")
.text(function (d) {
return d.id
})
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation
.force("link")
.links(graph.links);
function ticked() {
link.attr("d", function (d) {
var dx = (d.target.x - d.source.x),
dy = (d.target.y - d.source.y),
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
// Neuberechnung der Distanz
link.attr("d", function (d) {
// Länge des aktuellen Paths
var pl = this.getTotalLength(),
// Kreis Radius und Distanzwert
r = radius + offset,
// Umlaufposition wo der Path den Kreis berührt
m = this.getPointAtLength(pl - r);
var dx = m.x - d.source.x,
dy = m.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + m.x + "," + m.y;
});
node
.attr("transform", d => `translate(${d.x}, ${d.y})`);
}
function dragstarted(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragended(event, d) {
if (!event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
dataFlow()
function dataFlow() {
var lines = linksContainer.selectAll("path")
dataflow = window.setInterval(function () {
lines.style("stroke-dashoffset", offset)
.style("stroke", "black")
.style("stroke-dasharray", 5)
.style("opacity", 0.5)
offset -= 1
}, 40)
var offset = 1;
}
</script>
</body>
</html>
Here's an example for one circle and label that uses a <textPath>.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<body>
<div id="chart"></div>
<script>
// set up
const width = 200;
const height = 200;
const svg = d3.select('#chart')
.append('svg')
.attr('width', width)
.attr('height', height);
// radius of the circle that the label is above
const radius = 50;
// arc generator for the curved path
const arc = d3.arc()
// add a bit of space so that the label
// won't be right on the circle
.innerRadius(radius + 5)
.outerRadius(radius + 5)
.startAngle(-Math.PI / 2)
.endAngle(Math.PI / 2);
// add the path that the label will follow to <defs>
svg.append('defs')
.append('path')
.attr('id', 'curvedLabelPath')
.attr('d', arc());
// create a group for the circle and label
const g = svg.append('g')
.attr('transform', `translate(${width / 2},${height / 2})`);
// draw the circle
g.append('circle')
.attr('stroke', 'black')
.attr('fill', '#d3d3d3')
.attr('r', radius);
// draw the label
g.append('text')
.append('textPath')
.attr('href', '#curvedLabelPath')
// these two lines center along the arc.
// the offset is 25% instead of 50% because d3.arc() creates
// an arc that has an outer and inner part. in this case,
// each parth is ~50% of the path, so the middle of the
// outer arc is 25%
.attr('text-anchor', 'middle')
.attr('startOffset', '25%')
.text('stackoverflow');
</script>
</body>
</html>
Here are the changes to your updated code to make the labels not get cutoff, as explained in my comment below:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Curved Text</title>
<!-- Script Import -->
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<style>
body {
background: white;
overflow: hidden;
margin: 0px;
}
circle {
fill: whitesmoke;
stroke-width: 2;
stroke: black;
transform: scale(1);
transition: all 200ms ease-in-out;
}
circle:hover {
transform: scale(1.5)
}
</style>
<body>
<svg id="svg"></svg>
<script>
var width = window.innerWidth,
height = window.innerHeight,
radius = 40, // circle radius
offset = 35; // arrow offset
const svg = d3.select('svg')
.attr("width", width)
.attr("height", height)
.call(d3.zoom().on("zoom", function (event) {
svg.attr("transform", event.transform)
}))
.append("g")
var graph = {
"nodes": [
{ "id": "Stackoverflow" },
{ "id": "Reddit" },
{ "id": "Google" }
],
"links": [
{ "source": "Stackoverflow", "target": "Reddit"},
{ "source": "Reddit", "target": "Google"},
{ "source": "Google", "target": "Stackoverflow"},
]
}
const arc = d3.arc()
.innerRadius(radius + 5)
.outerRadius(radius + 5)
.startAngle(-Math.PI / 2)
.endAngle(Math.PI / 2 )
svg.append("defs")
.append("path")
.attr("id", "curvedLabelPath")
.attr("d", arc())
svg.append('defs').append('marker')
.attr('id', 'arrowhead')
.attr('viewBox', '-0 -5 10 10')
.attr('refX', 0)
.attr('refY', 0)
.attr('orient', 'auto')
.attr('markerWidth', 10)
.attr('markerHeight', 10)
.attr('xoverflow', 'visible')
.append('svg:path')
.attr('d', 'M 0,-5 L 10 ,0 L 0,5')
.attr('fill', '#999')
.style('stroke', 'none');
var linksContainer = svg.append("g").attr("class", "linksContainer")
var nodesContainer = svg.append("g").attr("class", "nodesContainer")
const simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) { return d.id }).distance(250))
.force("charge", d3.forceManyBody().strength(-1000))
.force("center", d3.forceCenter(width / 2, height / 2))
.force("collision", d3.forceCollide().radius(radius))
link = linksContainer.selectAll("g")
.data(graph.links)
.join("g")
.attr("curcor", "pointer")
link = linksContainer.selectAll("path")
.data(graph.links)
.join("path")
.attr("id", function (_, i) {
return "path" + i
})
.attr("stroke", "#000000")
.attr("opacity", 0.75)
.attr("stroke-width", 3)
.attr("fill", "transparent")
.attr("marker-end", "url(#arrowhead)")
node = nodesContainer.selectAll(".node")
.data(graph.nodes, d => d.id)
.join("g")
.attr("cursor", "pointer")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("mouseenter", function (d) {
d3.select(this).select("text").attr("font-size", 15)
})
node.selectAll("circle")
.data(d => [d])
.join("circle")
.attr("r", radius)
node.append("text")
.append("textPath")
.attr("href", "#curvedLabelPath")
.attr("text-anchor", "middle")
.attr("startOffset", "25%")
.text(function (d) {
return d.id
})
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation
.force("link")
.links(graph.links);
function ticked() {
link.attr("d", function (d) {
var dx = (d.target.x - d.source.x),
dy = (d.target.y - d.source.y),
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
// Neuberechnung der Distanz
link.attr("d", function (d) {
// Länge des aktuellen Paths
var pl = this.getTotalLength(),
// Kreis Radius und Distanzwert
r = radius + offset,
// Umlaufposition wo der Path den Kreis berührt
m = this.getPointAtLength(pl - r);
var dx = m.x - d.source.x,
dy = m.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + m.x + "," + m.y;
});
node
.attr("transform", d => `translate(${d.x}, ${d.y})`);
}
function dragstarted(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragended(event, d) {
if (!event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
dataFlow()
function dataFlow() {
var lines = linksContainer.selectAll("path")
dataflow = window.setInterval(function () {
lines.style("stroke-dashoffset", offset)
.style("stroke", "black")
.style("stroke-dasharray", 5)
.style("opacity", 0.5)
offset -= 1
}, 40)
var offset = 1;
}
</script>
</body>
</html>

Setting up a click event in d3 that hides all other elements

I am fairly new to using d3, but what I am trying to do is make a chord diagram of some site traffic, and I am trying to make it interactive by changing the color of the paths when a user clicks on the group for a certain site.here is the style and script section of my code:
<style type="text/css">
.group text {
font: 11px sans-serif;
pointer-events: none;
}
#circle circle {
fill: none;
pointer-events: all;
}
.group path {
stroke: #000;
fill-opacity: .5;
}
path.chord {
stroke-width: .75;
fill-opacity: .75;
}
#circle:hover path.fade {
display: none;
}
</style>
</head>
<body>
<script type="text/javascript">
// Chart dimensions.
var w = 600,
h = 700,
r1 = Math.min(w, h) / 2 - 4,
r0 = r1 - 20,
format = d3.format(",.3r");
// Square matrices, asynchronously loaded; credits is the transpose of sitename.
var sitename = [];
// The chord layout, for computing the angles of chords and groups.
var layout = d3.layout.chord()
.sortGroups(d3.descending)
.sortSubgroups(d3.descending)
.sortChords(d3.descending)
.padding(.04);
// The color scale, for different categories of "worrisome" risk.
var fill = d3.scale.ordinal();
// The arc generator, for the groups.
var arc = d3.svg.arc()
.innerRadius(r0)
.outerRadius(r1);
// The chord generator (quadratic Bézier), for the chords.
var chord = d3.svg.chord()
.radius(r0);
// Add an SVG element for each diagram, and translate the origin to the center.
var svg = d3.select("body").selectAll("div")
.data([sitename])
.enter().append("div")
.style("display", "inline-block")
.style("width", w + "px")
.style("height", h + "px")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
// Load our data file…
d3.csv("data2.csv", function(data) {
var uniqueids = {},
array = [],
n = 0;
// Compute a unique id for each site.
data.forEach(function(d) {
d.siteid1 = uniqueIDMaker(d.siteid1);
d.siteid2 = uniqueIDMaker(d.siteid2);
d.valueOf = value; // convert object to number implicitly
});
// Initialize a square matrix of sitename and users
for (var i = 0; i < n; i++) {
sitename[i] = [];
for (var j = 0; j < n; j++) {
sitename[i][j] = 0;
}
}
// Populate the matrices, and stash a map from id to site.
data.forEach(function(d) {
sitename[d.siteid1.id][d.siteid2.id] = d;
array[d.siteid1.id] = d.siteid1;
array[d.siteid2.id] = d.siteid2;
});
// For each diagram…
svg.each(function(matrix, j) {
var svg = d3.select(this);
// Compute the chord layout.
layout.matrix(matrix);
// Add chords.
svg.selectAll(".chord")
.data(layout.chords)
.enter().append("svg:path")
.attr("class", "chord")
.style("fill", function(d) { return fill(d.source.value); })
.style("stroke", function(d) { return d3.rgb(fill(d.source.value)).darker(); })
.attr("d", chord)
.on("dblclick",function(){
d3.select(this)
.style("fill","red")
.style("stroke","yellow")
})
.append("svg:title")
.text(function(d) { return "site " + d.source.value.siteid2.name + " and site " + d.source.value.siteid1.name + " have " + format(d.source.value) + " common users"; })
;
// Add groups.
var g = svg.selectAll("g.group")
.data(layout.groups)
.enter().append("svg:g")
.attr("class", "group");
// Add the group arc.
g.append("svg:path")
.style("fill", function(d) { return fill(array[d.index]); })
.attr("id", function(d, i) { return "group" + d.index + "-" + j; })
.attr("d", arc)
.append("svg:title")
.text(function(d) { return "site " + array[d.index].name + " has " + format(d.value) + "users"; });
g.append("svg:text")
.attr("x", 6)
.attr("dy", 15)
.filter(function(d) { return d.value > 110; })
.append("svg:textPath")
.attr("xlink:href", function(d) { return "#group" + d.index + "-" + j; })
.text(function(d) { return array[d.index].name; });
});
function uniqueIDMaker(d) {
return uniqueids[d] || (uniqueids[d] = {
name: d,
id: n++
});
}
function value() {
return +this.count;
}});
</script>
any help would be greatly appreciated
http://jsfiddle.net/Rw3aK/2/ is a jsFiddle of the script, not sure how to make it read from a file, so here is the contents of data2.csv:
siteid1,siteid2,count,pubid1,pubid2
8,94,11132,57141,57141
201,94,10035,57141,57141
201,8,9873,57141,57141
0,94,8488,45020,57141
0,8,8258,45020,57141
0,201,7644,45020,57141
0,1,6973,45020,45020
94,1,5719,57141,45020
8,1,5670,57141,45020
1,201,5410,57141,45020
I forked your jsfiddle and converted your CSV data to JSON, now in a variable data: http://jsfiddle.net/mdml/K6FHW/.
I also modified your code slightly so that when you click on a group, all outgoing chords are highlighted red. When you click on a group again, the chords change back to their original color. Here're the relevant snippets:
When adding the chords, label each chord with a class according to the chord's source
svg.selectAll(".chord")
.data(layout.chords)
.enter().append("svg:path")
.attr("class", function(d){ return "chord chord-" + d.source.index; })
...
When clicking a group, check if that group's chords are highlighted.
If so, fill the chords with their default color
If not, fill the chords red
Then record whether or not the group's chords are highlighted in a variable d.chordHighlighted
g.append("svg:path")
...
.attr("id", function (d, i) {
return "group" + d.index + "-" + j;
})
...
.on("click", function(d){
if (d.chordHighlighted)
d3.selectAll(".chord-" + d.index)
.style("fill", fill(d.value));
else{
d3.selectAll(".chord-" + d.index)
.style("fill", "red");
}
d.chordHighlighted = d.chordHighlighted ? false : true;
})

add images to bubble layout in D3.js

Unable to add images to bubble layout in D3.js . I am trying to append images to the circles in bubble layout but it doesnt works out . the image is not getting transformed.
I want to have look and feel of this:-
http://www.cloudshapes.co.uk/labs/attention-hungry-cabinet-ministers/
here is the fiddle link for what I have been trying to do:
http://jsfiddle.net/Ankitb/eYGCY/4/
var force = d3.layout.force()
.charge(-300)
.size([w, h])
.nodes(nodes)
.on("tick", tick)
.start();
function tick() {
svg.selectAll("circle")
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; });
}
var interval = setInterval(function () {
var d = {
x: w / 4 + 2 *( Math.random() - 1),
y: h / 4 + 2 *( Math.random() - 1)
};
var personDot = svg.append("g")
.attr("class", "g-person-dots")
.selectAll("g")
.data([d])
.enter().append("g")
.attr("transform", function (d) { return "translate(" + d.x+ "," + d.y + ")"; });
personDot.append("circle")
.data([d]).attr("r", 40)
//.attr("r", 1e-6)
.attr("cx",0).attr("cy",0)
.transition().style("stroke", "gray").style("fill","white")
.ease(Math.sqrt);
personDot.append("image").data([d])
.attr("xlink:href", "PeopleProfilePicture.jpg")
// .attr("x", function (d, i) { return -mugDiameter / 2 - mugDiameter * (i % 9); })
//.attr("y", function (d, i) { return -mugDiameter / 2 - mugDiameter * (i / 9 | 0); })
.attr("width", 80)
.attr("height", 80)
.attr("transform", function (d) { return "translate(" + -d.x / 10 + "," + -d.y / 10 + ")"; });
if (nodes.push(d) > 10) clearInterval(interval);
else { force.start(); }
}, 30);
The translation of an element is relative to its parent element. That is, by default the element will be in the same position as its parent. Therefore, the translation you need to do does not depend on the dynamic data that you pass in, but only on the dimensions of the image. You need to set transform as follows.
.attr("transform", "translate(-40,-40)");
You may also want to make the background of your images transparent such that you can still see the circle.

d3 Gives a 406 Error when trying to run d3js example on IIS

I have setup a basic IIS server and am trying to demonstrate a d3js example. First I create an html page with the example code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(d3.format(".2s"));
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("data.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Population");
var state = svg.selectAll(".state")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.State) + ",0)"; });
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { return d; });
});
</script>
and then i create the data.csv file:
State,Under 5 Years,5 to 13 Years,14 to 17 Years,18 to 24 Years,25 to 44 Years,45 to 64 Years,65 Years and Over
AL,310504,552339,259034,450818,1231572,1215966,641667
AK,52083,85640,42153,74257,198724,183159,50277
AZ,515910,828669,362642,601943,1804762,1523681,862573
AR,202070,343207,157204,264160,754420,727124,407205
CA,2704659,4499890,2159981,3853788,10604510,8819342,4114496
CO,358280,587154,261701,466194,1464939,1290094,511094
CT,211637,403658,196918,325110,916955,968967,478007
DE,59319,99496,47414,84464,230183,230528,121688
DC,36352,50439,25225,75569,193557,140043,70648
FL,1140516,1938695,925060,1607297,4782119,4746856,3187797
GA,740521,1250460,557860,919876,2846985,2389018,981024
HI,87207,134025,64011,124834,356237,331817,190067
ID,121746,201192,89702,147606,406247,375173,182150
IL,894368,1558919,725973,1311479,3596343,3239173,1575308
IN,443089,780199,361393,605863,1724528,1647881,813839
IA,201321,345409,165883,306398,750505,788485,444554
KS,202529,342134,155822,293114,728166,713663,366706
KY,284601,493536,229927,381394,1179637,1134283,565867
LA,310716,542341,254916,471275,1162463,1128771,540314
ME,71459,133656,69752,112682,331809,397911,199187
MD,371787,651923,316873,543470,1556225,1513754,679565
MA,383568,701752,341713,665879,1782449,1751508,871098
MI,625526,1179503,585169,974480,2628322,2706100,1304322
MN,358471,606802,289371,507289,1416063,1391878,650519
MS,220813,371502,174405,305964,764203,730133,371598
MO,399450,690476,331543,560463,1569626,1554812,805235
MT,61114,106088,53156,95232,236297,278241,137312
NE,132092,215265,99638,186657,457177,451756,240847
NV,199175,325650,142976,212379,769913,653357,296717
NH,75297,144235,73826,119114,345109,388250,169978
NJ,557421,1011656,478505,769321,2379649,2335168,1150941
NM,148323,241326,112801,203097,517154,501604,260051
NY,1208495,2141490,1058031,1999120,5355235,5120254,2607672
NC,652823,1097890,492964,883397,2575603,2380685,1139052
ND,41896,67358,33794,82629,154913,166615,94276
OH,743750,1340492,646135,1081734,3019147,3083815,1570837
OK,266547,438926,200562,369916,957085,918688,490637
OR,243483,424167,199925,338162,1044056,1036269,503998
PA,737462,1345341,679201,1203944,3157759,3414001,1910571
RI,60934,111408,56198,114502,277779,282321,147646
SC,303024,517803,245400,438147,1193112,1186019,596295
SD,58566,94438,45305,82869,196738,210178,116100
TN,416334,725948,336312,550612,1719433,1646623,819626
TX,2027307,3277946,1420518,2454721,7017731,5656528,2472223
UT,268916,413034,167685,329585,772024,538978,246202
VT,32635,62538,33757,61679,155419,188593,86649
VA,522672,887525,413004,768475,2203286,2033550,940577
WA,433119,750274,357782,610378,1850983,1762811,783877
WV,105435,189649,91074,157989,470749,514505,285067
WI,362277,640286,311849,553914,1487457,1522038,750146
WY,38253,60890,29314,53980,137338,147279,65614
When I access the page, nothing displays...A quick look through fiddler shows the html content downloads fine (you can also see it in show source). You can also look at the data.csv file directly by accessing it from the url
http://localhost/data.csv
The problem shown in fiddler is a 406 error when d3js attempts to load the CSV file. Any ideas?
Thanks
What does your HTTP Request's Accept header contain? Apache is probably configured in such a way so as to return a 406 because the value in the Accept header does not include whatever MIME type your CSV is returning.
See
http://blogs.msdn.com/b/ieinternals/archive/2011/03/27/http-406-not-acceptable-php-ie9-standards-mode-accepts-only-text_2f00_css-for-stylesheets.aspx for a similar problem sometimes seen in browsers.
Change the build action for the csv file to "Resource" in the file's properties using your Visual Studio.

create balloons based on my click and animate to top of the screen ( random positions of X-axis) using Raphael.js

using this code i can able to create a circle with line( like as balloon) based on my click and animate to center position of the rectangle, while animating line is not going along with circle like as balloon and how to move the of the screen ( random positions of X-axis) insted of center position.
Code:
$(document).ready(function () {
var canvas = Raphael(0, 0, 920, 940);
var backboard = canvas.rect(0, 0, 920, 940).attr({ fill: 'white', stroke: 'none' });
backboard.click(function (event, x, y) {
var bbox = backboard.getBBox();
var x_ratio = x / bbox.width;
var y_ratio = y / bbox.height;
var color = 'rgb(' + Math.floor(x_ratio * 255) + ',0,' + Math.floor(y_ratio * 255) + ")";
// Circle
var transient_circle = canvas.circle(x, y, 25).attr({ fill: color, stroke: 'black', 'stroke-width': 1 });
transient_circle.animate({ cx: bbox.width / 2, cy: bbox.width / 3, 'fill-opacity': 0.25 }, 3000, ">",
function () {
transient_circle.animate({ 'stroke-opacity': 0, 'fill-opacity': 0 }, 2500, function () { transient_circle.remove(); });
});
// Line
var transient_pathline = canvas.path("M" + x + " " + (y + 25) + "C" + (x - 80) + " " + (y + 200) + " " + (x + 100) + " " + (y + 400) + " " + (x - 100) + " " + (y + 120)).attr({ fill: '#fff', stroke: color, 'stroke-width': 1 });
var _transformedPath = Raphael.transformPath('M' + (bbox.width / 2) + " " + (bbox.width / 3) + "C" + (x - 80) + " " + (y + 200) + " " + (x + 100) + " " + (y + 400) + " " + (x - 100) + " " + (y + 120), 'T300,0');
transient_pathline.animate({ path: _transformedPath }, 1000);} }); });
please help me how to move the circle along with line to top of the screen like as a balloon.
Code for creating balloons based on user click
function derivateElement(element) {
var movAmplitude = 236
var nx = -movAmplitude * .5 + Math.random() * movAmplitude
var ny = -movAmplitude * .5 + Math.random() * movAmplitude
var timing = 800 + Math.random() * 400
element.animate({ transform: "T" + nx + ", " + ny }, timing, "easeInOut", function () { derivateElement(element) });
}
var canvas = Raphael(0, 0, 920, 940);
var backboard = canvas.rect(0, 0, 920, 940).attr({ fill: 'white', stroke: 'none' });
var index = 0;
backboard.click(function (event, x, y) {
var bbox = backboard.getBBox();
var x_ratio = x / bbox.width;
var y_ratio = y / bbox.height;
var color = 'rgb(' + Math.floor(x_ratio * 255) + ',0,' + Math.floor(y_ratio * 255) + ")";
// Circle
var _circle = canvas.circle(x, y, 25).attr({ fill: color, stroke: 'black', 'stroke-width': 1 });
//path
var _pathline = canvas.path("M" + x + " " + (y + 25) + "C" + (x - 80) + " " + (y + 200) + " " + (x + 100) + " " + (y + 400) + " " + (x - 100) + " " + (y + 120)).attr({ fill: '#fff', stroke: color, 'stroke-width': 1 });
_circle.connections = [];
_pathline.startElement = _circle;
_circle.connections.push(_pathline);
_circle.connected = true;
var CircleSet = []
CircleSet[index] = canvas.set();
CircleSet[index].push(_circle, _pathline);
derivateElement(CircleSet[index]);
index++;
});

Resources