As the title says. How can I reverse the animation path in a pie (D3.js). As default, the pie renders clockwise with animation. How do I reverse it?
See picture example.
JS here:
var pie = d3.layout.pie()
.sort(null)
.startAngle(1 * Math.PI)
.endAngle(3 * Math.PI)
.value(function (d) { return d.percentage; });
g.append("path")
.attr("d", arc)
.style("fill", function (d) { return d.data.color; })
.attr({
"fill": function (d) {
return d.data.color;
}
})
.transition()
.duration(1000)
.attrTween("d", function (d) {
var i = d3.interpolate(d.startAngle, d.endAngle);
return function (t) {
d.endAngle = i(t);
return arc(d);
}
});
Just swap endAngle with startAngle:
.transition()
.duration(1000)
.attrTween("d", function (d) {
var i = d3.interpolate(d.endAngle, d.startAngle);
return function (t) {
d.startAngle = i(t);
return arc(d);
}
});
Check the snippet:
var dataset = {
apples: [5345, 2879, 1997, 2437, 4045],
};
var width = 460,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 50);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var path = svg.selectAll("path")
.data(pie(dataset.apples))
.enter().append("path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.transition()
.duration(1000)
.attrTween("d", function (d) {
var i = d3.interpolate(d.endAngle, d.startAngle);
return function (t) {
d.startAngle = i(t);
return arc(d);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
Related
I am trying to animate the start angle of the arc using D3.js
Any help or link for reference would do.
I have tried the below:
http://jsfiddle.net/87e3d4tj/
d3.select('#my-path').datum({
startAngle: endAngle,
endAngle: ( 90 * (Math.PI/180) )
})
.transition()
.duration(duration)
.attrTween('d', d => {
var interpolate = d3.interpolate(d.startAngle, d.endAngle);
return function(t) {
d.endAngle = endAngle;
d.startAngle = interpolate(t);
return arc(d);
};
});
i have tried the below hope you are looking for the same.
https://jsfiddle.net/debasish007/eu7xo4mL/
var width = 400,
height = 400,
τ = (Math.PI/180);
var arc = d3.arc()
.innerRadius(130)
.outerRadius(150);
var svg = d3.select("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
var foreground = svg.append("path")
.datum({
endAngle: 90 * τ,
startAngle: -90 * τ
})
.style("fill", "blue")
.attr("d", arc);
setTimeout(function () {
foreground.transition()
.duration(750)
.call(arcTween, -30 * τ, 90 * τ);
}, 1500);
function arcTween(transition, newStartAngle, newFinishAngle) {
transition.attrTween("d", function (d) {
var interpolateStart = d3.interpolate(d.startAngle, newStartAngle);
return function (t) {
d.endAngle = newFinishAngle;
d.startAngle = interpolateStart(t);
return arc(d);
};
});
}
I am begginer to d3.js and getting errors, I customized the example for my needs but gettings these in the console. Please help. Thank you in Advance.
Error: Invalid value for <path> attribute d="M-1.8369701987210297e-14,-100A100,100 0 1,1 NaN,NaNLNaN,NaNA60,60 0 1,0 -1.1021821192326178e-14,-60Z"a # d3.v3.min.js:1
d3.v3.min.js:1 Error: Invalid value for <path> attribute d="MNaN,NaNA100,100 0 1,1 NaN,NaNLNaN,NaNA60,60 0 1,0 NaN,NaNZ"
var getData = function () {
var size = 3;
var data =[];
var text = "";
data=[
{
label:"Saved",
value:200,
},{
label:"Ordered",
value:1255,
},{
label:"Shipped",
value:760,
},{
label:"Backordered",
value:150,
},
{
label:"Cancelled",
value:250,
},
];
d3.select("#data").html(text);
return data;
};
console.log(getData());
var chart = donut(250,200,16,40)
.$el(d3.select("#chart"))
.data(getData())
.render();
d3.select("#refresh").on("click", function () {
chart.data(getData()).render();
});
function donut(width,height,label_font_size,value_font_size) {
// Default settings
var $el = d3.select("body")
var data = {};
// var showTitle = true;
var width = width,
height = height,
radius = Math.min(width, height) / 2;
//var arc = d3.svg.arc().outerRadius(radius);
var arcOver = d3.svg.arc()
.innerRadius(radius + 20);
var currentVal;
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null)
.value(function (d) {
console.log(d);
return d.value.value;
});
var svg, g, arc;
var object = {};
// Method for render/refresh graph
object.render = function () {
if (!svg) {
arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(radius - (radius / 2.5));
svg = $el.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
g = svg.selectAll(".arc")
.data(pie(d3.entries(data)))
.enter().append("g")
.attr("class", "arc");
g.append("path")
// Attach current value to g so that we can use it for animation
.each(function (d) {
//this._current = d;
})
.attr("d", arc)
.style("fill", function (d,i) {
return color(i);
});
/*g.append("text")
.attr("transform", function (d,i) {
return "translate(" + arc.centroid(d,i) + ")";
})
.attr("dy", ".35em")
.style("text-anchor", "middle");
g.select("text").text(function (d) {
//return d.data.key;
});
*/
svg.append("text")
.datum(data)
.attr("x", 0)
.attr("y", 0)
.attr("class", "text-tooltip")
.style("text-anchor", "middle")
.attr("font-weight", "bold")
.style("font-size", radius / 2.5 + "px");
g.on("mouseover", function (obj) {
var tooltipText=svg.select("text.text-tooltip");
tooltipText.attr("fill", function (d,i) {
return color(i);
});
tooltipText.append("tspan")
.attr("dy", -15)
.attr("x",0)
.attr("class", "text-tooltip-label")
.style("font-size", label_font_size + "px")
.text(function(d) {return d[obj.data.key].label;});
tooltipText.append("tspan")
.attr("dy", ".9em") // offest by 1.2 em
.attr("x",0)
.attr("class", "text-tooltip-value")
.style("font-size", value_font_size + "px")
.text(function(d) {return d[obj.data.key].value;});
d3.select(this)
.attr("stroke","white")
.transition()
.duration(1000)
.attr("d", arcOver)
.attr("stroke-width",6);
});
g.on("mouseout", function (obj) {
svg.select("text.text-tooltip").text("");
d3.select(this).transition()
.attr("d", arc)
.attr("stroke","none");
});
} else {
g.data(pie(d3.entries(data))).exit().remove();
g.select("path")
.transition().duration(200)
.attrTween("d", function (a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return arc(i(t));
};
});
g.select("text")
.attr("transform", function (d,i) {
return "translate(" + arc.centroid(d,i) + ")";
});
svg.select("text.text-tooltip").datum(data);
}
return object;
};
// Getter and setter methods
object.data = function (value) {
if (!arguments.length) return data;
data = value;
return object;
};
object.$el = function (value) {
if (!arguments.length) return $el;
$el = value;
return object;
};
object.width = function (value) {
if (!arguments.length) return width;
width = value;
radius = Math.min(width, height) / 2;
return object;
};
object.height = function (value) {
if (!arguments.length) return height;
height = value;
radius = Math.min(width, height) / 2;
return object;
};
return object;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="chart"></div>
I'm trying to display a sunburst with text. I used the code from a sunburst example and tried to add text to it (worked), but when it updates, my text disappears. I can only get it to display all text or text when loaded then no text. So when it updates, the text is either gone or is not in sync with the data.
Can anybody tell me what is wrong because I don't know anymore.
Original code: http://bl.ocks.org/mbostock/4348373
My adaptions:
var width = 1060,
height = 900,
radius = Math.min(width, height) / 2;
var x = d3.scale.linear()
.range([0, 2 * Math.PI]);
var y = d3.scale.sqrt()
.range([0, radius]);
var color = d3.scale.category20c();
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")");
var partition = d3.layout.partition()
.value(function(d) { return d.size; });
var arc = d3.svg.arc()
.startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
.endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
.innerRadius(function(d) { return Math.max(0, y(d.y)); })
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
d3.json("http://localhost:50043/data.json", function (error, root) {
if (error) throw error;
var data = partition.nodes(root);
var path = svg.selectAll("path")
.data(partition.nodes(root))
.enter()
//.append("g");
.append("path")
//.attr("display", function (d) { return d.depth ? null : "none"; })
.attr("d", arc)
.style("fill", function (d) { return color((d.children ? d : d.parent).name); })
.on("click", click);
var text = svg.selectAll("text")
.data(data)
.enter()
.append("text")
.classed("label", true)
.attr("x", function (d) { return d.x; })
.attr("text-anchor", "middle")
// translate to the desired point and set the rotation
.attr("transform", function (d) {
if (d.depth > 0) {
return "translate(" + arc.centroid(d) + ")" +
"rotate(" + getAngle(d) + ")";
} else {
return null;
}
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("pointer-events", "none")
.text(function (d) { return d.name; });
function click(data) {
text.remove();
text = svg.selectAll("text")
.data(data)
.enter()
.append("text")
.classed("label", true)
.attr("x", function(d) { return d.x; })
.attr("text-anchor", "middle")
// translate to the desired point and set the rotation
.attr("transform", function(d) {
if (d.depth > 0) {
return "translate(" + arc.centroid(d) + ")" +
"rotate(" + getAngle(d) + ")";
} else {
return null;
}
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("pointer-events", "none")
.text(function (d) { return d.name; });
path.transition()
.duration(750)
.attrTween("d", arcTween(data));
}
function getAngle(d) {
// Offset the angle by 90 deg since the '0' degree axis for arc is Y axis, while
// for text it is the X axis.
var thetaDeg = (180 / Math.PI * (arc.startAngle()(d) + arc.endAngle()(d)) / 2 - 90);
// If we are rotating the text by more than 90 deg, then "flip" it.
// This is why "text-anchor", "middle" is important, otherwise, this "flip" would
// a little harder.
return (thetaDeg > 90) ? thetaDeg - 180 : thetaDeg;
}
function arcTween(d) {
var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, 1]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
return function (d, i) {
return i
? function (t) { return arc(d); }
: function (t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
};
}
});
d3.select(self.frameElement).style("height", height + "px");
Update: You can find my code on https://github.com/KenBonny/D3-Chart-Test
You can view the handywork on github page: https://kenbonny.github.io/D3-Chart-Test/
It's because you are not passing any data to click
wirte function click() { instead of function click(data) {
and I think it will work
Problem: The Arctween function will not work on the .on("mouseOver").
Intention: When hovering the arcs in the Pie Chart a highlight needs to start (opacity etc.) and information needs (infoHover) to show, next to the Arctween that I also want to activate.
I am aware that the code is not perfect at all, I'm just experimenting with d3.js.
Thanks in advance!
Javascript:
d3.json("dataExample.json", function (data) {
var width = 260,
height = 260;
var outerRadius = height / 2 - 20,
innerRadius = outerRadius / 3,
cornerRadius = 10;
colors = d3.scale.category20c();
var tempColor;
var pie = d3.layout.pie()
.padAngle(.02)
.value(function(d) {
return d.value;
})
var arc = d3.svg.arc()
.padRadius(outerRadius)
.innerRadius(innerRadius);
var infoHover = d3.select('#chart').append('div')
.style('position', 'absolute')
.style('padding', '0 30px')
.style('opacity', 0)
function arcTween(outerRadius, delay) {
return function() {
d3.select(this).transition().delay(delay).attrTween("d", function(d) {
var i = d3.interpolate(d.outerRadius, outerRadius);
return function(t) { d.outerRadius = i(t); return arc(d); };
});
};
}
var svg = d3.select("#chart").append("svg")
.data(data)
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.selectAll('path').data(pie(data))
.enter().append('path')
.attr('fill', function(d, i) {
return colors(i);
})
.each(function(d) { d.outerRadius = outerRadius - 20; })
.attr('d', arc)
.on("mouseover", function(d) {
infoHover.transition()
.style('opacity', .9)
.style('left', '85px')
.style('top', '120px')
infoHover.html(d.value + '%')
d3.selectAll("path")
.transition()
.duration(500)
.style("opacity", .18)
d3.select(this)
.transition()
.duration(500)
.style('opacity', 1)
.style('cursor', 'pointer')
arcTween(outerRadius, 0);
})
.on("mouseout", function(d) {
d3.selectAll("path")
.transition()
.duration(500)
.style("opacity", 1)
d3.select(this)
.style('opacity', 1)
arcTween(outerRadius - 20, 150);
});
});
Your arcTween returns a function your need to call:
arcTween(outerRadius, 0).call(this);
I'm drawing charts with d3.js.
Is it possible to add radial gradients to donut chart, how on this picture?
Assuming the arc parts are path elements that are filled you can use a radial gradient to get that result.
See this similar question, we can reuse the example to arrive at:
var dataset = {
apples: [53245, 28479, 19697, 24037, 40245],
};
var width = 460,
height = 300,
radius = Math.min(width, height) / 2;
var color = d3.scale.category20();
var pie = d3.layout.pie()
.sort(null);
var arc = d3.svg.arc()
.innerRadius(radius - 100)
.outerRadius(radius - 50);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var grads = svg.append("defs").selectAll("radialGradient").data(pie(dataset.apples))
.enter().append("radialGradient")
.attr("gradientUnits", "userSpaceOnUse")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", "100%")
.attr("id", function(d, i) { return "grad" + i; });
grads.append("stop").attr("offset", "15%").style("stop-color", function(d, i) { return color(i); });
grads.append("stop").attr("offset", "20%").style("stop-color", "white");
grads.append("stop").attr("offset", "27%").style("stop-color", function(d, i) { return color(i); });
var path = svg.selectAll("path")
.data(pie(dataset.apples))
.enter().append("path")
.attr("fill", function(d, i) { return "url(#grad" + i + ")"; })
.attr("d", arc);
Jsfiddle: http://jsfiddle.net/X8hfm/