I would like to be able to click on a circle (coordinate points); bring the marker to the position of the circle and pause at the position of the circle and then resume again along the path.
In addition I would like to activate a circle when marker is paused on them - they are clicked (or their Voronoi cell is clicked). My intention is to have an on click function to an href for the circle coordinates eventually.
I think I need to pass the index of the path coordinates into the translateAlong function instead of the time variables but can't work out how to do this.
I’m not sure if the Voronoi cells are necessary - I tried to add this thinking I could pause my transition and activate my circles with the Voronoi cells. In any case I can’t activate the circle with the Voronoi cell.
I was helped considerably recently on Stackoverflow d3 on click on circle pause and resume transition of marker along line
and I am hoping for assistance again
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>basic_animateBetweenCircles</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
path {
stroke: #848484;
fill: none;
}
circle {
fill: steelblue;
stroke: steelblue;
stroke-width: 3px;
}
.line {
fill: none;
stroke: #FE642E;
stroke-width: 4;
stroke-dasharray: 4px, 8px;
}
.point{
fill:#DF013A;
}
</style>
</head>
<body>
<script>
var width = 960,
height = 500;
var data = [
[480, 200],
[580, 400],
[680, 100],
[780, 300],
[180, 300],
[280, 100],
[380, 400]
];
//check index of path data
for (var i = 0; i < data.length; i++) {
var coordindex = i + " " + data[i];
console.log("Coordindex: " + coordindex);
//return coordindex;
};
var duration = 20000;
var line = d3.line()
.x(function(d) {return (d)[0];})
.y(function(d) {return (d)[1];});
var voronoi = d3.voronoi()
.extent([[0, 0], [width, height]]);
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
//path to animate - marker transitions along this path
var path = svg.append("path")
.data([data])
.attr("d", line)
.attr('class', 'line')
.attr("d", function(d) {
return line(d)
});
//voronoi
var voronoiPath = svg.append("g")
.selectAll("path")
.data(voronoi.polygons(data))
.enter().append("path")
.attr("d", polygon)
.on("touchmove mousemove", function() {
d3.select(this)
.style("fill", "purple");
});
//Want to activate circles when marker paused on them / in voronoi cell - intention is to have on click to href
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("r", 10)
.attr("transform", function(d) { return "translate(" + d + ")"; })
.on('click', function(d, i) {
d3.select(this)
.style("fill", "green");
if (d3.active(this)) {
marker.transition();
setTimeout(function() {
pauseValues.lastTime = pauseValues.currentTime;
//console.log(pauseValues);
}, 100);
} else {
transition();
}
});
var pauseValues = {
lastTime: 0,
currentTime: 0
};
//marker to transition along path
var marker = svg.append("circle")
.attr("r", 19)
.attr("transform", "translate(" + (data[0]) + ")")
.on('click', function(d, i) {
if (d3.active(this)) {
marker.transition();
setTimeout(function() {
pauseValues.lastTime = pauseValues.currentTime;
//console.log(pauseValues);
}, 100);
} else {
transition();
}
});
function transition() {
marker.transition()
.duration(duration - (duration * pauseValues.lastTime))
.attrTween("transform", translateAlong(path.node()))
.on("end", function() {
pauseValues = {
lastTime: 0,
currentTime: 0
};
transition()
});
}
function translateAlong(path) {
var l = path.getTotalLength();
return function(d, i, a) {
return function(t) {
t += pauseValues.lastTime;
var p = path.getPointAtLength(t * l);
pauseValues.currentTime = t;
return "translate(" + p.x + "," + p.y + ")";
};
};
}
function polygon(d) {
return "M" + d.join("L") + "Z";
}
</script>
</body>
If you want to pause at points, I would not run one transition across the entire path. Instead, I would break it up into N transitions, moving from point to point. Before starting the circle on it's next leg, you can pause it for a time. To do this, I would just transition along each line segment with a little algebra:
// copy our data
transData = data.slice();
function transition() {
marker.transition()
.ease(d3.easeLinear)
.duration(duration)
.attrTween("transform", function(){
// get our two points
// slope between them
// and intercetp
var p0 = transData.shift(),
p1 = transData[0];
m = (p0[1] - p1[1]) / (p0[0] - p1[0]),
b = p0[1] - (m * p0[0]),
i = d3.interpolateNumber(p0[0], p1[0]);
// move the point along the line
return function(t){
var x = i(t),
y = m*x + b;
return "translate(" + x + "," + y + ")";
}
})
// one line segment is complete
.on("end", function(){
// if no more movements, stop
if (transData.length <= 1) return;
iter++;
// determine if this is a "pause"
setTimeout(transition, pausePoints.indexOf(iter) !== -1 ? pauseTime : 0);
});
Running code, click a dot to start you can pause a multiple points:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>basic_animateBetweenCircles</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
path {
stroke: #848484;
fill: none;
}
circle {
fill: steelblue;
stroke: steelblue;
stroke-width: 3px;
}
.line {
fill: none;
stroke: #FE642E;
stroke-width: 4;
stroke-dasharray: 4px, 8px;
}
.point {
fill: #DF013A;
}
</style>
</head>
<body>
<script>
var width = 960,
height = 500;
var data = [
[480, 200],
[580, 400],
[680, 100],
[780, 300],
[180, 300],
[280, 100],
[380, 400]
];
var duration = 20000/data.length,
pauseTime = 2000;
var line = d3.line()
.x(function(d) {
return (d)[0];
})
.y(function(d) {
return (d)[1];
});
var voronoi = d3.voronoi()
.extent([
[0, 0],
[width, height]
]);
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
//path to animate - marker transitions along this path
var path = svg.append("path")
.data([data])
.attr("d", line)
.attr('class', 'line')
.attr("d", function(d) {
return line(d)
});
//voronoi
var voronoiPath = svg.append("g")
.selectAll("path")
.data(voronoi.polygons(data))
.enter().append("path")
.attr("d", polygon);
//Want to activate circles when marker paused on them / in voronoi cell - intention is to have on click to href
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("r", 10)
.attr("transform", function(d) {
return "translate(" + d + ")";
})
.on('click', function(d, i) {
d3.select(this)
.style("fill", "green");
pausePoints.push(i);
if (pausePoints.length === 1)
transition();
});
//marker to transition along path
var marker = svg.append("circle")
.attr("r", 19)
.attr("transform", "translate(" + (data[0]) + ")");
var pausePoints = [],
iter = 0,
transData = data.slice();
function transition() {
marker.transition()
.ease(d3.easeLinear)
.duration(duration)
.attrTween("transform", function(){
var p0 = transData.shift(),
p1 = transData[0];
m = (p0[1] - p1[1]) / (p0[0] - p1[0]),
b = p0[1] - (m * p0[0]),
i = d3.interpolateNumber(p0[0], p1[0]);
return function(t){
var x = i(t),
y = m*x + b;
return "translate(" + x + "," + y + ")";
}
})
.on("end", function(){
if (transData.length <= 1) return;
iter++;
setTimeout(transition, pausePoints.indexOf(iter) !== -1 ? pauseTime : 0);
});
}
function polygon(d) {
return "M" + d.join("L") + "Z";
}
</script>
</body>
Related
On a d3 v4 chart, I have arcs drawn for multiple coordinates. All is well there. Now I would like to draw the lines from a json request. Any new lines would be drawn, whilst existing lines would remain. As I understand, each line would require its own transition....
If I understand correctly, the iteration of coordinates begins at
line.attr("d", function(c) {...}
Which iterates over each set of coordinates, and then internally groups them so that they are all 'triggered' at the same time, as the one event. Any explanation on this gratefully received.
Plunker: https://plnkr.co/edit/Ax4Tby47lFlryzVWCHi2?p=preview
Kev
Not sure I'm reading your question correctly, but it sounds like you want your animations to start one after another. This can be accomplished with a .delay:
.attr("stroke-dasharray", "0, 1000") //<-- hide the line
.transition()
.delay(function(d, i) {
return 5000 * i; //<-- i is the index of the line, so stagger the animation start by index * duration
})
.duration(5000)
.attrTween("stroke-dasharray", function() {
var len = this.getTotalLength();
return function(t) {
return (d3.interpolateString("0," + len, len + ",0"))(t)
};
})
Full Code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<style>
.stroke {
fill: none;
stroke: #000;
stroke-width: 3px;
}
.fill{
fill: #fff;
}
.graticule {
fill: none;
stroke: #777;
stroke-width: 0.5px;
stroke-opacity: 0.5;
}
/* the color of land in countries */
.land {
fill: #222;
}
/* the color of borders */
.boundary {
fill: none;
stroke: #fff;
stroke-width: 0.5px;
}
</style>
<svg width="800" height="600"></svg>
<script src="//d3js.org/d3.v4.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var projection = d3.geoMercator()
.scale((width - 3) / (2 * Math.PI))
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
var graticule = d3.geoGraticule();
svg.append("defs").append("path")
.datum({
type: "Sphere"
})
.attr("id", "sphere")
.attr("d", path);
svg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
svg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
d3.json("https://rawgit.com/mbostock/topojson/master/examples/world-50m.json", function(error, world) {
if (error) throw error;
d3.json("https://jsonblob.com/api/5806b733e4b0bcac9f817223", function(coord){
svg.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
svg.insert("path", ".graticule")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) {
return a !== b;
}))
.attr("class", "boundary")
.attr("d", path);
var line = svg.selectAll(".paths")
.data(coord)
.enter()
.append("path");
line.attr("d", function(c) {
console.log(c);
var d = {
source: projection(c.source),
target: projection(c.destination)
};
var dx = d.target[0] - d.source[0],
dy = d.target[1] - d.source[1],
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source[0] + "," + d.source[1] + "A" + dr + "," + dr +
" 0 0,1 " + d.target[0] + "," + d.target[1];
})
.style("stroke", "red") // color of the arc line
.style("stroke-width", 5)
.style("fill", "none")
.attr("stroke-dasharray", "0, 1000")
.transition()
.delay(function(d, i) {
return 5000 * i;
})
.duration(5000)
.attrTween("stroke-dasharray", function() {
var len = this.getTotalLength();
return function(t) {
return (d3.interpolateString("0," + len, len + ",0"))(t)
};
})
.on('end', function(d) {
var c = projection(d.destination);
svg.append('circle')
.attr('cx', c[0])
.attr('cy', c[1])
.attr('r', 0)
.style('fill', 'white') // color of the cirle
.style('fill-opacity', '0.5')
.transition()
.duration(2000)
.attr('r', 50)
.on('end', function(d) {
d3.select(this)
.transition()
.duration(2000)
.attr('r', 10);
});
});
});
});
</script>
</body>
</html>
I need to animate pie chart into a donut chart (or ring chart).
Here is my code:
var arc = d3.svg.arc().outerRadius(radius-margin).innerRadius(0)
var arc2 = d3.svg.arc().outerRadius(radius-margin).innerRadius(60)
var path = pie_chart.selectAll('path')
.data(pie(data))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color_scale(d.data.device)
})
.transition().attr('d', arc2)
Some times it's working but sometimes it is not. I have tried to apply transition to arc but not working.
var arc2 = d3.svg.arc().outerRadius(radius-margin).innerRadius(0).transition().innerRadius(60)
I would write my own arcTween function for this to take complete control of the transition:
function arcTween(d) {
var i = d3.interpolateNumber(0, radius-70); //<-- radius of 0 to donut
return function(t) {
var r = i(t),
arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(r); //<-- create arc
return arc(d); //<-- return arc path
};
}
Full code:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.arc text {
font: 10px sans-serif;
text-anchor: middle;
}
.arc path {
stroke: #fff;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 500,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.category10();
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var data = [10, 20, 30, 40];
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d, i) {
return color(i);
})
.transition()
.delay(100)
.duration(5000)
.attrTween("d", arcTween);
function arcTween(d) {
var i = d3.interpolateNumber(0, radius-70);
return function(t) {
var r = i(t),
arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(r);
return arc(d);
};
}
</script>
</body>
Or just give someone a headache:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.arc text {
font: 10px sans-serif;
text-anchor: middle;
}
.arc path {
stroke: #fff;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var width = 500,
height = 500,
radius = Math.min(width, height) / 2;
var color = d3.scale.category10();
var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d;
});
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var data = [10, 20, 30, 40];
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
var arcs = g.append("path")
.attr("d", arc)
.style("fill", function(d, i) {
return color(i);
});
(function repeat() {
arcs.transition()
.duration(500)
.attrTween("d", arcTweenOut)
.transition()
.duration(500)
.attrTween("d", arcTweenIn)
.each('end', repeat)
})();
function arcTweenOut(d) {
var i = d3.interpolateNumber(0, radius-70);
return function(t) {
var r = i(t),
arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(r);
return arc(d);
};
}
function arcTweenIn(d) {
var i = d3.interpolateNumber(radius-70, 0);
return function(t) {
var r = i(t),
arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(r);
return arc(d);
};
}
</script>
</body>
i have a problem when i do a zoom in my map because the labels appears duplicate. I know that my problem appears because in my zoom i dont delete the label. I know where is the problem, i need to delete the oldest label when i do a zoom but i dont know how and where to solve this.
Any idea? Ty for all.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
margin: 0;
}
path {
fill: none;
stroke: green;
stroke-linejoin: round;
stroke-width: 1.5px;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="d3.geo.tile.min.js"></script>
<script>
var width = Math.max(960, window.innerWidth),
height = Math.max(600, window.innerHeight);
var tile = d3.geo.tile()
.size([width, height]);
var projection = d3.geo.mercator()
.scale((3 << 12) / 2 / Math.PI)
.translate([width / 2, height / 2]);
var center = projection([-3, 36]);
var path = d3.geo.path()
.projection(projection);
var zoom = d3.behavior.zoom()
.scale(projection.scale() * 2 * Math.PI)
.translate([width - center[0], height - center[1]])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var raster = svg.append("g");
var g = svg.append("g");
var vector = svg.append("path");
d3.json("es.json", function(error, es) {
if (error) throw error;
svg.call(zoom);
vector.datum(topojson.mesh(es, es.objects.provinces));
zoomed();
});
function zoomed() {
d3.csv("data/country-capitals.csv", function(err, capitals) {
capitals.forEach(function(i){
addpoint(i.CapitalLongitude, i.CapitalLatitude, i.CapitalName );
});
});
var tiles = tile
.scale(zoom.scale())
.translate(zoom.translate())
();
projection
.scale(zoom.scale() / 2 / Math.PI)
.translate(zoom.translate());
vector
.attr("d", path);
var image = raster
.attr("transform", "scale(" + tiles.scale + ")translate(" + tiles.translate + ")")
.selectAll("image")
.data(tiles, function(d) { return d; });
image.exit()
.remove();
image.enter().append("image")
.attr("xlink:href", function(d) { return "http://" + ["a", "b", "c"][Math.random() * 3 | 0] + ".tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; })
.attr("width", 1)
.attr("height", 1)
.attr("x", function(d) { return d[0]; })
.attr("y", function(d) { return d[1]; });
}
function addpoint(lat,lon,text) {
var gpoint = g.append("g").attr("class", "gpoint");
var x = projection([lat,lon])[0];
var y = projection([lat,lon])[1];
gpoint.append("svg:circle")
.attr("cx", x)
.attr("cy", y)
.attr("class","point")
.attr("r", 1.5);
//conditional in case a point has no associated text
if(text.length>0){
gpoint.append("text")
.attr("x", x+2)
.attr("y", y+2)
.attr("class","text")
.text(text);
}
}
</script>
CSV is here:
CountryName,CapitalName,CapitalLatitude,CapitalLongitude,CountryCode,ContinentName
Brazil,Brasilia,-15.783333333333333,-47.916667,BR,South America
Colombia,Bogota,4.6,-74.083333,CO,South America
Egypt,Cairo,30.05,31.250000,EG,Africa
France,Paris,48.86666666666667,2.333333,FR,Europe
Iraq,Baghdad,33.333333333333336,44.400000,IQ,Asia
South Korea,Seoul,37.55,126.983333,KR,Asia
Kosovo,Pristina,42.666666666666664,21.166667,KO,Europe
Mexico,Mexico City,19.433333333333334,-99.133333,MX,Central America
Before you zoom you can remove all the group containing text and circle like this:
function zoomed() {
d3.selectAll(".gpoint").remove();
d3.csv("my.csv", function(err, capitals) {
capitals.forEach(function(i){
addpoint(i.CapitalLongitude, i.CapitalLatitude, i.CapitalName );
});
});
//your code
Working code here
I was trying to draw curves between two nodes using d3.js.
<meta charset="utf-8">
<!-- ----------------- -->
<!-- THIS PART IS CSS -->
<!-- ----------------- -->
<style>
body
{
background: lightskyblue;
}
.node {
stroke: black;
stroke-width: 4.0px;
}
.link {
stroke: slategray;
stroke-opacity: 0.6;
}
</style>
</head>
<body>
<!-- ------------------------ -->
<!-- THIS PART IS JAVASCRIPT -->
<!-- ------------------------ -->
<script src="d3.v3.js"></script>
<script>
////////////////////////////////////////////////////////////////
// Function to prepare topology background
////////////////////////////////////////////////////////////////
var width = 1280, height = 630;
var color = d3.scale.category20();
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("border","7px solid black")
;
var nodes = [], links = [];
var graph = test_case();
nodes = graph.nodes;
links = graph.links;
for(var i = 0; i < nodes.length; i++)
{
element = nodes[i];
if(element.group == 0)
{
element.x = width/2;
element.y = height/2;
element.fixed = true;
}
}
var force = d3.layout.force()
.charge(-400)
.linkDistance(300)
.size([width, height])
.links(links)
.nodes(nodes)
.on("tick", tick);
var node = svg.selectAll(".node"),
link = svg.selectAll(".link");
drawGraph();
function test_case()
{
graph =
{
"nodes":[
{"name":0,"group":0,"pos":[216,140]},
{"name":1,"group":1,"pos":[350,200]},
{"name":2,"group":1,"pos":[478,438]},
{"name":3,"group":1,"pos":[596,498]},
{"name":4,"group":1,"pos":[422,295]},
{"name":5,"group":1,"pos":[597,357]},
{"name":6,"group":1,"pos":[530,238]},
{"name":7,"group":1,"pos":[506,100]},
{"name":8,"group":1,"pos":[793,265]},
{"name":9,"group":1,"pos":[972,228]}
],
"links":[
{"source":1,"target":2,"rssi":25,"lqi":25,"lr":120},
{"source":2,"target":0,"rssi":50,"lqi":50,"lr":80},
{"source":3,"target":0,"rssi":12,"lqi":12,"lr":200},
{"source":3,"target":2,"rssi":65,"lqi":65,"lr":40},
{"source":4,"target":0,"rssi":80,"lqi":80,"lr":170},
{"source":5,"target":0,"rssi":60,"lqi":60,"lr":110},
{"source":6,"target":7,"rssi":30,"lqi":30,"lr":64},
{"source":7,"target":0,"rssi":21,"lqi":21,"lr":97},
{"source":8,"target":3,"rssi":57,"lqi":57,"lr":190},
{"source":9,"target":0,"rssi":72,"lqi":72,"lr":12}
]
};
return graph;
}
////////////////////////////////////////////////////////////////
// Function to draw topology, including nodes and links
////////////////////////////////////////////////////////////////
function drawGraph()
{
//Add links
link = link.data(force.links());
link.enter()
.append("path")
// .insert("line", ".gnode")
.attr("class", "link")
// .style("stroke", function(d) {
// if(d.rssi<=25) return "crimson";
// else if(d.rssi<=50) return "orange";
// else if(d.rssi<=75) return "royalblue";
// else return "green"; })
//.style("stroke-dasharray" ,function(d) { if(d.target==0) return "10,10"; else return "";})
// .style("stroke-width", function(d) { return d.lqi/20 + 5; })
// .style("stroke-opacity", function(d) { return (d.lr/51)*0.1 + 0.5; });
link.exit().remove();
//Add nodes with texts in them
node = node.data(force.nodes());
node.enter().append("g").attr("class", "gnode").call(force.drag);
node.append("circle")
.attr("class", function(d) { return "node group" + d.group })
.attr("r", 25)
.style("fill", function(d) { if(d.group==0) return "mediumaquamarine"; else return "beige" });
node.append("text")
.attr("text-anchor", "middle")
.attr("dy", "+7")
.text(function(d) { return d.name; })
.attr("font-size", "22px")
.attr("font-weight", "bold")
.style("fill", "black");
node.exit().remove();
force.start();
}
function tick()
{
node.attr("transform", function(d) { return "translate(" + d.pos + ")";});
link.attr("d", function(d) {
var dx = d.target.pos[0] - d.source.pos[0],
dy = d.target.pos[1] - d.source.pos[1],
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.pos[0] + "," + d.source.pos[1] + "A" + dr + "," + dr + " 0 0,1 " + d.target.pos[0] + "," + d.target.pos[1];
});
}
</script>
</body>
</html>
but the result of the code was not as I expected which was supposed to be like this http://bl.ocks.org/d3noob/5155181 with addition of colours, opacity and width. I also want to draw arrows. Could anybody figure this out please?
I'm sorry I'm very new to stackoverflow; it's my first time I have written this topic.
For adding arrow in path following steps:
Append Marker:
svg.append("svg:defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
.enter().append("svg:marker") // This section adds in the arrows
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 45)
.attr("refY",-5.2)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
Append arrow in Path
link = link.data(force.links());
link.enter()
.append("path")
.attr("class", "link")
.attr("marker-end", "url(#end)");
Path CSS:
.link {
stroke: slategray;
stroke-opacity: 0.6;
fill: none;
stroke-width: 1.5px;
}
DEMO for your code
According to radius you want to change the arrow position refer this ,and it will help for dragging nodes
First step:
Make fill none :)
.link {
stroke: slategray;
fill: none;
stroke-opacity: 0.6;
}
Working on the arrows
JSFIDDLE
I have extended the pie-chart example at:
with pies that vary in radius depending on a percentage. I would like to add gridlines (circles) every 20 percent, but I can't figure out how.
here is the updated csv:
age,population,percent
<5,2704659,67
5-13,4499890,38
14-17,2159981,91
18-24,3853788,49
25-44,14106543,71
45-64,8819342,88
=65,612463,64
and here is the updated code with pie-parts of different radius:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
background: #333;
}
.arc path {
stroke: #fff;
stroke-width: 2px;
}
.arc grid {
stroke: #fff;
stroke-width: 1;
stroke-dasharray: 5,5;
}
.arc text {
fill:#fff;
font-size:12px;
font-weight:bold;
}
.arc line {
stroke: #fff;
}
</style>
<body>
<script src="d3.js"></script>
<script>
var width = 960,
height = 500,
radius = Math.min(width, height) / 2 - 10;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(function(d) { return 50 + (radius - 50) * d.data.percent / 100; })
.innerRadius(20);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
var grid = d3.svg.area.radial()
.radius(150);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.population = +d.population;
d.percent = d.percent;
});
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.age); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function(d) { return d.data.age; });
});
</script>
First set the number of ticks:
var numTicks = 5; // Each tick is 20%
Then create the data to create the gridlines:
var sdat = [];
for (i=0; i<=numTicks; i++) {
sdat[i] = (radius/numTicks) * i;
}
And then you can use a function to create the radial gridlines, and you can call it from within the d3.csv block:
addCircleAxes = function() {
var circleAxes, i;
svg.selectAll('.circle-ticks').remove();
circleAxes = svg.selectAll('.circle-ticks')
.data(sdat)
.enter().append('svg:g')
.attr("class", "circle-ticks");
// radial tick lines
circleAxes.append("svg:circle")
.attr("r", String)
.attr("class", "circle")
.style("stroke", "#CCC")
.style("opacity", 0.5)
.style("fill", "none");
// Labels for each circle
circleAxes.append("svg:text")
.attr("text-anchor", "center")
.attr("dy", function(d) { return d - 5 })
.style("fill", "#fff")
.text(function(d,i) { return i * (100/numTicks) });
};
An example is here: http://bl.ocks.org/3994129
(Borrowed from: http://kreese.net/blog/2012/08/26/d3-js-creating-a-polar-area-diagram-radial-bar-chart/)