目前正试图在d3.js
中设置PieChart的绘制动画,而我目前在使用ArcTween函数方面遇到了困难,继承我的代码:
<!doctype HTML>
<html>
<head>
<title>Page Title</title>
<meta charset="UTF-8">
<script type="text/javascript" src="js/d3.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<script type="text/javascript">
//=========================================================================================================================================
// initializing variables
var data = []; // empty array to hold the objects imported from the JSON file
var oRadius = 300; //var holding value for the outer radius of the arc
var iRadius = 80; //var holding the value for the inner radius of the arc
var cRadius = 3; //var holding the value for the corner radius of the arc
var colors = d3.scale.category20b();//built in D3 function to color pieces of data
var width = 1400; //setting the width of the svg
var height = 1000; //setting the height of the svg
var dRadius = 5; //setting the radius for the dots
var sColor = "white"; // color for the stroke of the arcs
var dStrokeColor = "#666"; // stroke color for the dots
var dFillColor = "#ccc" // fill color for the dots
var fontSize = 25; // font size value for the text labels
var numFont = 15; // font size for the number labels
var linePadding = 160; // value to translate the text and number labels to the end of each polyLine
var myArcMaker= d3.svg.arc().outerRadius(oRadius).innerRadius(iRadius).cornerRadius(cRadius); //var that returns the values needed to create the arcs of the pie chart
var bigArcMaker= d3.svg.arc().outerRadius(400).innerRadius(oRadius).cornerRadius(cRadius); //var that returns the values needed to create the arcs of the big pie chart used to draw the polylines
var mySvg = d3.select('body') //select the html body in the DOM
.append('svg') // place an empty svg in the body
.attr('width', width) //give the svg this width
.attr("height", height)//give the svg this height
.append("g")//append a group to the svg
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")// centers the pie chart in the center of the svg this will make sure everything in the group is centered
mySvg.append("g") //creates a group
.attr("class", "slices"); // give it a class of slices, used for the pie chart arcs
mySvg.append("g") // creates a group
.attr("class", "dots"); // give it a class of dots, used for the circles in the centre of the arcs
mySvg.append("g")//creates a group
.attr("class", "lines");// give it a class of lines, used for the big pie chart surrounding the main piechart
mySvg.append("g")//creates a group
.attr("class", "polyLines");//gives it a class of polylines, used for the polylines protruding it from the pie chart arcs
mySvg.append("g")//creates a group
.attr("class", "labels");//gives a class of labels, used for the text labels at the end of the polylines
mySvg.append("g")//creates a group
.attr("class", "numlabels");//gives it a class of numlabels, used for the number labels at the end of the polylines
var myPie = d3.layout.pie()
.sort(null) //removes any d3 sorting
.startAngle((Math.PI)/360) // setting the start angle for the arcs
.endAngle((2*(Math.PI))) // setting the end angle for the arcs
.padAngle(2*(2*(Math.PI))/360).value(function(d){return d.value}); //setting the values for that start angle, end angle and pad angle for the arcs and takes in the the values from the objects in the data array
//======================================================================================================================================================
d3.json("data.json", function (json) // importing the json file
{
data = json; // setting the empty data array equal to the values of the objects in the json file
visual(); // this function holds all the d3 code to create the arc
})
//======================================================================================================================================================
function visual() // this function prevents the code that creates the arc from running before the objects from the json file are added into the empty data array
{
// console.log(data); // checking to see if the objects are loaded into the data ray using the console in chrome
var slice = mySvg.select("g.slices") //selecting the class slices
.selectAll("path.slice")//selecting all paths in the slice class
.data(myPie(data))//binds the data to the DOM elements
.enter()//begin looping through the data
.append("path")//append a path
.attr("class", "slice")//give it a class of slice
.attr("d", function(d) {//runs the data in the dataset through the arcmaker function
return myArcMaker(d)
})
.attr("fill", function(d, i) {
return colors(i);
}) //using the d3 color brewer to color each arc
.each(function(d) { this._current = d; })
.attr("stroke", "white") //giving each arc a stroke of white
.style('stroke-width',2) //gives the stroke a width of 2px
.each(function(d) { this._current = d; })
.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
var dots = mySvg.select("g.dots") //select the group dots
.selectAll("cirlces") //select all circles in the dots group
.data(myPie(data))//binds the data to the DOM elements
.enter()//begin the loop
.append("circle")//draw a circle
.attr("class", "g.dots")//gives it a class of dots
.attr("transform", function(d)//transform each circle to the centre of each arc using the .centroid method
{
return "translate(" + myArcMaker.centroid(d) + ")";
})
.attr("r", dRadius)//setting the radius of the circle
.attr("fill", dFillColor)//setting the fill color
.attr("stroke", sColor)//setting the stroke color
//
var lines = mySvg.select(".lines") //select the lines class *--------------------------------------*
.selectAll("path.lines")//select all paths in the lines class * This section here is to draw *
.data(myPie(data)) //binds the data to the DOM elements * the invisible piechart that *
.enter()//begin the loop * surrounds the smaller piechart this *
.append("path")//draw a path * used for the polylines later on *
.attr("class", "lines")//give it a class of lines *--------------------------------------*
.attr("d", function(d) {//set the d value to the values returned from the bigArcMaker function
return bigArcMaker(d)
}).attr("fill", "none")//give the fill a value of none
.attr("stroke", "none")//give the stroke a value of none
// var outerDots = mySvg.select("g.dots")//select the dots group
// .selectAll("cirlces")//select all circles in the dots group
// .data(myPie(data))//binds the data to the DOM elements
// .enter()
// .append("circle")//create a circle
// .attr("class", "g.dots")//give it a class of dots
// .attr("transform", function(d)//translate it to the centroid of the bigArc surrounding the main pie chart
// {
// return "translate(" + bigArcMaker.centroid(d) + ")";
// })
// .attr("r", dRadius)
// .attr("fill", dFillColor)
// .attr("stroke", sColor)
// var x1 = myArcMaker.centroid(d)[0];
// var y1 = myArcMaker.centroid(d)[1];
// var x2 = bigArcMaker.centroid(d)[0];
// var y2 = bigArcMaker.centroid(d)[1];
// var x3 = function(d){if(x2<0){return bigArcMaker.centroid(d)[0]-160}}
// var lineData = [{'x': x1},
// ]
var polyLines = mySvg.select(".polyLines")//select the class of polylines
.selectAll("polylines")//sellect all polylines in the class of polylines
.data(myPie(data))//binds the data to the DOM elements
.enter()
.append("polyline")//create a polyline
.attr("class", "polyLines")//give it a class of polylines
.attr("points", function(d) {//set the points for the polylines
var p = " "; //used because i was getting errors with my strings also makes this the conditional statement more readable
p += myArcMaker.centroid(d)[0] + ',' + myArcMaker.centroid(d)[1] + ',' + bigArcMaker.centroid(d)[0] + ',' + bigArcMaker.centroid(d)[1] + ',';
p += bigArcMaker.centroid(d)[0] < 0 ? bigArcMaker.centroid(d)[0] - linePadding : bigArcMaker.centroid(d)[0] + linePadding; //if the x value for the bigArc maker is less than zero - linePadding, if its greater, add linePading
p += ',' + bigArcMaker.centroid(d)[1];
return p;
})
.attr("fill", "none")//gives the fill value none
.attr("stroke", sColor) //gives the stroke a color of sColor
.style('stroke-width',2)//gives the stroke-width of 2 pixels
var labels = mySvg.select(".labels")//select class labels
.selectAll("text")//select all text
.data(myPie(data))//binds the data to the DOM elements
.enter()
.append("text")//create a text
.text(function(d) //setting the text value to the Fruits label in the dataset
{
return d.data.Fruits;
})
.style("fill", sColor)//sets the fill to the sColor attribute
.attr("x", function(d)//conditional statement that determines where the text will be placed, similar to the polylines
{
if(bigArcMaker.centroid(d)[0]>0)
{
return bigArcMaker.centroid(d)[0]+linePadding;
}
else
{
return bigArcMaker.centroid(d)[0]-linePadding;
}
})
.attr("y", function(d){return bigArcMaker.centroid(d)[1]})//set the why value to the y value of the centroid array
.attr("text-anchor", function(d){
if(bigArcMaker.centroid(d)>0)//conditional statement that sets the text anchor for each piece of text, similar to polylines
{
return "start"
}
else{
return "end"
}
})
.attr("font-family", "Helvetica") // sets the font family
.style("font-size", fontSize)//sets the font size
var numLabels = mySvg.select(".numlabels") //select the class numlabels
.selectAll("text")//selects all text in the class numlabels
.data(myPie(data))//binds the data to the DOM elements
.enter()
.append("text")//append a text
.text(function(d) //sets the value of the text to the value attribute in the dataset array
{
return d.data.value;
})
.style("fill", sColor)//sets the fill color
.attr("x", function(d)//conditional statement to set the x value of the text similar to the polylines and labels
{
if(bigArcMaker.centroid(d)[0]>0)
{
return bigArcMaker.centroid(d)[0]+linePadding;
}
else
{
return bigArcMaker.centroid(d)[0]-linePadding;
}
})
.attr("y", function(d){return bigArcMaker.centroid(d)[1]})//set the why value to the y value of the centroid array
.attr("text-anchor", function(d){
if(bigArcMaker.centroid(d)>0)//conditional statement that sets the text anchor for each piece of text, similar to polylines
{
return "start"
}
else{
return "end"
}
})
.attr("dy", 20)
.attr("font-family", "Helvetica") // sets the font family
.style("font-size", numFont)
function arcTween(a)
{
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t)
{
return myArcMaker(i(t));
};
}
}
</script>
</body>
</html>
我希望它从开始角度开始并绘制到结束角度,我尝试使用d.startAngle和d.endAngle但是当我在chrome中检查它时,我得到一个未被捕获的引用错误,因为d未定义。目前代码正在编译,当我检查它时我没有错误,我不太确定它是如何工作的,所以探索会很棒
继承我的JSFiddle:http://jsfiddle.net/JamieHyland1/gyekfnr2/
答案 0 :(得分:0)
你很近,你的补间功能有点偏差。此外,您可以废弃所有this._current
内容,只在补间函数本身中进行闭包。
function arcTween(a) { //<-- a is the datum bound to each arc
var startAngle = a.startAngle; //<-- keep reference to start angle
var i = d3.interpolate(a.startAngle, a.endAngle); //<-- interpolate start to end
return function(t) {
return myArcMaker({ //<-- return arc at each iteration from start to interpolate end
startAngle: startAngle,
endAngle: i(t)
});
};
}
您将此称为:
var slice = mySvg.select("g.slices") //selecting the class slices
.selectAll("path.slice") //selecting all paths in the slice class
.data(myPie(data)) //binds the data to the DOM elements
.enter() //begin looping through the data
.append("path") //append a path
.attr("class", "slice") //give it a class of slice
.attr("fill", function(d, i) {
return colors(i);
}) //using the d3 color brewer to color each arc
.attr("stroke", "white") //giving each arc a stroke of white
.style('stroke-width', 2) //gives the stroke a width of 2px
.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
完整代码:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<meta charset="UTF-8" />
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script type="text/javascript">
//=========================================================================================================================================
// initializing variables
var data = []; // empty array to hold the objects imported from the JSON file
var oRadius = 300; //var holding value for the outer radius of the arc
var iRadius = 80; //var holding the value for the inner radius of the arc
var cRadius = 3; //var holding the value for the corner radius of the arc
var colors = d3.scale.category20b(); //built in D3 function to color pieces of data
var width = 1400; //setting the width of the svg
var height = 1000; //setting the height of the svg
var dRadius = 5; //setting the radius for the dots
var sColor = "white"; // color for the stroke of the arcs
var dStrokeColor = "#666"; // stroke color for the dots
var dFillColor = "#ccc" // fill color for the dots
var fontSize = 25; // font size value for the text labels
var numFont = 15; // font size for the number labels
var linePadding = 160; // value to translate the text and number labels to the end of each polyLine
var myArcMaker = d3.svg.arc().outerRadius(oRadius).innerRadius(iRadius).cornerRadius(cRadius); //var that returns the values needed to create the arcs of the pie chart
var bigArcMaker = d3.svg.arc().outerRadius(400).innerRadius(oRadius).cornerRadius(cRadius); //var that returns the values needed to create the arcs of the big pie chart used to draw the polylines
var mySvg = d3.select('body') //select the html body in the DOM
.append('svg') // place an empty svg in the body
.attr('width', width) //give the svg this width
.attr("height", height) //give the svg this height
.append("g") //append a group to the svg
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") // centers the pie chart in the center of the svg this will make sure everything in the group is centered
mySvg.append("g") //creates a group
.attr("class", "slices"); // give it a class of slices, used for the pie chart arcs
mySvg.append("g") // creates a group
.attr("class", "dots"); // give it a class of dots, used for the circles in the centre of the arcs
mySvg.append("g") //creates a group
.attr("class", "lines"); // give it a class of lines, used for the big pie chart surrounding the main piechart
mySvg.append("g") //creates a group
.attr("class", "polyLines"); //gives it a class of polylines, used for the polylines protruding it from the pie chart arcs
mySvg.append("g") //creates a group
.attr("class", "labels"); //gives a class of labels, used for the text labels at the end of the polylines
mySvg.append("g") //creates a group
.attr("class", "numlabels"); //gives it a class of numlabels, used for the number labels at the end of the polylines
var myPie = d3.layout.pie()
.sort(null) //removes any d3 sorting
.startAngle((Math.PI) / 360) // setting the start angle for the arcs
.endAngle((2 * (Math.PI))) // setting the end angle for the arcs
.padAngle(2 * (2 * (Math.PI)) / 360).value(function(d) {
return d.value
}); //setting the values for that start angle, end angle and pad angle for the arcs and takes in the the values from the objects in the data array
//======================================================================================================================================================
// d3.json("data.json", function (json) // importing the json file
// {
data = [{
value: 10
}, {
value: 20
}, {
value: 30
}];
visual(); // this function holds all the d3 code to create the arc
// })
//======================================================================================================================================================
function visual() // this function prevents the code that creates the arc from running before the objects from the json file are added into the empty data array
{
// console.log(data); // checking to see if the objects are loaded into the data ray using the console in chrome
var slice = mySvg.select("g.slices") //selecting the class slices
.selectAll("path.slice") //selecting all paths in the slice class
.data(myPie(data)) //binds the data to the DOM elements
.enter() //begin looping through the data
.append("path") //append a path
.attr("class", "slice") //give it a class of slice
.attr("fill", function(d, i) {
return colors(i);
}) //using the d3 color brewer to color each arc
.attr("stroke", "white") //giving each arc a stroke of white
.style('stroke-width', 2) //gives the stroke a width of 2px
.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
var dots = mySvg.select("g.dots") //select the group dots
.selectAll("cirlces") //select all circles in the dots group
.data(myPie(data)) //binds the data to the DOM elements
.enter() //begin the loop
.append("circle") //draw a circle
.attr("class", "g.dots") //gives it a class of dots
.attr("transform", function(d) //transform each circle to the centre of each arc using the .centroid method
{
return "translate(" + myArcMaker.centroid(d) + ")";
})
.attr("r", dRadius) //setting the radius of the circle
.attr("fill", dFillColor) //setting the fill color
.attr("stroke", sColor) //setting the stroke color
//
var lines = mySvg.select(".lines") //select the lines class *--------------------------------------*
.selectAll("path.lines") //select all paths in the lines class * This section here is to draw *
.data(myPie(data)) //binds the data to the DOM elements * the invisible piechart that *
.enter() //begin the loop * surrounds the smaller piechart this *
.append("path") //draw a path * used for the polylines later on *
.attr("class", "lines") //give it a class of lines *--------------------------------------*
.attr("d", function(d) { //set the d value to the values returned from the bigArcMaker function
return bigArcMaker(d)
}).attr("fill", "none") //give the fill a value of none
.attr("stroke", "none") //give the stroke a value of none
// var outerDots = mySvg.select("g.dots")//select the dots group
// .selectAll("cirlces")//select all circles in the dots group
// .data(myPie(data))//binds the data to the DOM elements
// .enter()
// .append("circle")//create a circle
// .attr("class", "g.dots")//give it a class of dots
// .attr("transform", function(d)//translate it to the centroid of the bigArc surrounding the main pie chart
// {
// return "translate(" + bigArcMaker.centroid(d) + ")";
// })
// .attr("r", dRadius)
// .attr("fill", dFillColor)
// .attr("stroke", sColor)
// var x1 = myArcMaker.centroid(d)[0];
// var y1 = myArcMaker.centroid(d)[1];
// var x2 = bigArcMaker.centroid(d)[0];
// var y2 = bigArcMaker.centroid(d)[1];
// var x3 = function(d){if(x2<0){return bigArcMaker.centroid(d)[0]-160}}
// var lineData = [{'x': x1},
// ]
var polyLines = mySvg.select(".polyLines") //select the class of polylines
.selectAll("polylines") //sellect all polylines in the class of polylines
.data(myPie(data)) //binds the data to the DOM elements
.enter()
.append("polyline") //create a polyline
.attr("class", "polyLines") //give it a class of polylines
.attr("points", function(d) { //set the points for the polylines
var p = " "; //used because i was getting errors with my strings also makes this the conditional statement more readable
p += myArcMaker.centroid(d)[0] + ',' + myArcMaker.centroid(d)[1] + ',' + bigArcMaker.centroid(d)[0] + ',' + bigArcMaker.centroid(d)[1] + ',';
p += bigArcMaker.centroid(d)[0] < 0 ? bigArcMaker.centroid(d)[0] - linePadding : bigArcMaker.centroid(d)[0] + linePadding; //if the x value for the bigArc maker is less than zero - linePadding, if its greater, add linePading
p += ',' + bigArcMaker.centroid(d)[1];
return p;
})
.attr("fill", "none") //gives the fill value none
.attr("stroke", sColor) //gives the stroke a color of sColor
.style('stroke-width', 2) //gives the stroke-width of 2 pixels
var labels = mySvg.select(".labels") //select class labels
.selectAll("text") //select all text
.data(myPie(data)) //binds the data to the DOM elements
.enter()
.append("text") //create a text
.text(function(d) //setting the text value to the Fruits label in the dataset
{
return d.data.Fruits;
})
.style("fill", sColor) //sets the fill to the sColor attribute
.attr("x", function(d) //conditional statement that determines where the text will be placed, similar to the polylines
{
if (bigArcMaker.centroid(d)[0] > 0) {
return bigArcMaker.centroid(d)[0] + linePadding;
} else {
return bigArcMaker.centroid(d)[0] - linePadding;
}
})
.attr("y", function(d) {
return bigArcMaker.centroid(d)[1]
}) //set the why value to the y value of the centroid array
.attr("text-anchor", function(d) {
if (bigArcMaker.centroid(d) > 0) //conditional statement that sets the text anchor for each piece of text, similar to polylines
{
return "start"
} else {
return "end"
}
})
.attr("font-family", "Helvetica") // sets the font family
.style("font-size", fontSize) //sets the font size
var numLabels = mySvg.select(".numlabels") //select the class numlabels
.selectAll("text") //selects all text in the class numlabels
.data(myPie(data)) //binds the data to the DOM elements
.enter()
.append("text") //append a text
.text(function(d) //sets the value of the text to the value attribute in the dataset array
{
return d.data.value;
})
.style("fill", sColor) //sets the fill color
.attr("x", function(d) //conditional statement to set the x value of the text similar to the polylines and labels
{
if (bigArcMaker.centroid(d)[0] > 0) {
return bigArcMaker.centroid(d)[0] + linePadding;
} else {
return bigArcMaker.centroid(d)[0] - linePadding;
}
})
.attr("y", function(d) {
return bigArcMaker.centroid(d)[1]
}) //set the why value to the y value of the centroid array
.attr("text-anchor", function(d) {
if (bigArcMaker.centroid(d) > 0) //conditional statement that sets the text anchor for each piece of text, similar to polylines
{
return "start"
} else {
return "end"
}
})
.attr("dy", 20)
.attr("font-family", "Helvetica") // sets the font family
.style("font-size", numFont)
function arcTween(a) {
var startAngle = a.startAngle;
var i = d3.interpolate(a.startAngle, a.endAngle);
return function(t) {
return myArcMaker({
startAngle: startAngle,
endAngle: i(t)
});
};
}
}
</script>
</body>
</html>