是否有人知道如何使用JavaScript SVG创建一条线条/圆形图表,其中的线条扩展到代表不同数据点的不同象限?
下面的图片展示了我正在寻找的东西。
首先将dougnut图表与占位符进行映射,其中行可以跳出来。
//最新小提琴
http://jsfiddle.net/Qh9X5/10152/
下一步是绘制一条线以反射标记。
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data));
slice.enter()
.insert("path")
.attr('fill', function(d, i) {
console.log("d", d);
return colores_google(i);
})
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
var placeholders = svg.select(".placeholders").selectAll("circle.placeholder")
.data(pie(data));
placeholders.enter()
.insert("circle")
.style("fill", function(d) {
return "white";
})
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("r", "3")
.attr("class", function(d) {
return "placeholder " + d.data.group;
});
placeholders
.transition().duration(1000)
placeholders.exit()
.remove();
var gapplaceholders = svg.select(".placeholders").selectAll("circle.placeholder.gap");
gapplaceholders.remove();
答案 0 :(得分:3)
我已经设法开始在这个圆环图的节点上绘制多条线。
http://jsfiddle.net/Qh9X5/10208/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data));
slice.enter()
.insert("path")
.attr('fill', function(d, i) {
return colores_google(i);
})
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
var placeholders = svg.select(".placeholders").selectAll("circle.placeholder")
.data(pie(data));
placeholders.enter()
.insert("circle")
.style("fill", function(d) {
return "white";
})
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("x", function(d) {
return arc.centroid(d)[0];
})
.attr("y", function(d) {
return arc.centroid(d)[1];
})
.attr("r", "3")
.attr("id", function(d) {
return "p" + d.data.id;
})
.attr("class", function(d) {
return "placeholder " + d.data.group;
});
placeholders
.transition().duration(1000)
placeholders.exit()
.remove();
var labelholders = svg.select(".labelholders").selectAll("text.labelholder")
.data(pie(data));
labelholders.enter()
.insert("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("dy", -5)
.text(function(d) {
return d.data.id;
})
.attr("class", function(d) {
return "labelholder " + d.data.group;
});
labelholders
.transition().duration(1000)
labelholders.exit()
.remove();
var gapplaceholders = svg.select(".placeholders").selectAll("circle.placeholder.gap");
gapplaceholders.remove();
var lineColors = ["e2d7c7",
"d7b093",
"c04830",
"fffcef",
"4aaba2",
"c94f42",
"52b0a2"
];
var lineData = [{
group: 1,
plots: [21, 22, 18, 1]
}, {
group: 2,
plots: [20, 23, 17, 9]
}, {
group: 3,
plots: [21, 24, 16, 15]
}, {
group: 3,
plots: [19, 23, 16, 0]
}, {
group: 5,
plots: [19, 24, 18, 6]
}, {
group: 6,
plots: [19, 24, 17, 14]
}, {
group: 3,
plots: [20, 23, 16, 2]
}, {
group: 5,
plots: [19, 23, 16, 4]
}
]
$.each(lineData, function(index, value) {
var coords = [];
var group = value.group;
$.each(value.plots, function(i, v) {
$("#p" + v).each(function() {
var x = $(this).attr("x");
var y = $(this).attr("y");
var obj = {
"x": x,
"y": y
};
coords.push(obj);
});
});
var first = {
"x": 5 * index,
"y": radius - 35
};
coords.push(first);
var first = {
"x": 5 * index,
"y": radius + 200
};
coords.push(first);
var maxLeng = coords.length - 2;
$.each(coords, function(i, v) {
var line = svg.append("line")
.style("stroke", function(d) {
return lineColors[group];
})
.attr("x1", coords[i]["x"])
.attr("y1", coords[i]["y"])
.attr("x2", coords[i + 1]["x"])
.attr("y2", coords[i + 1]["y"]);
if (i == maxLeng) {
return false;
}
});
});
答案 1 :(得分:0)
最新的jsfiddle。
http://jsfiddle.net/Qh9X5/10276/
图表现在响应人文数据 - 虽然需要进一步考虑调整底角以将下面的字符串束缚在底部间隙中。
baseX2Angle = 0.5
var svg = d3.select("#pies")
.append("svg")
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "placeholders");
svg.append("g")
.attr("class", "gapplaceholders");
svg.append("g")
.attr("class", "labelholders");
var width = 560,
height = 450,
radius = Math.min(width, height) / 2;
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.outerRadius(radius * 0.85)
.innerRadius(radius * 0.83);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ") rotate(7)");
var key = function(d) {
return d.data.label;
};
function colores_google(n) {
var colores_g = ["#e9168a", "#f8dd2f", "#448875", "#c3bd75", "#2b2d39", "#311854", "#553814", "#f7b363", "#89191d", "#c12f34", "#2b2a2c", "#c5b8a6", "#57585b"];
return colores_g[n % colores_g.length];
}
var data = [
/*
{
"group": "g1",
"set": [
"skill1",
"skill2",
"skill3",
"skill4",
"skill5",
"skill6",
"skill7",
"skill8",
"skill9",
"skill10",
"skill11",
"skill12",
"skill13",
"skill14",
"skill15",
"skill16",
"skill17",
"skill18",
"skill19",
"skill20",
"skill21",
"skill22",
"skill23",
"skill24",
"skill25",
"skill26",
"skill27",
"skill28",
"skill29",
"skill30",
"skill31",
"skill32",
"skill33",
"skill34",
"skill35",
"skill36",
"skill37",
"skill38",
"skill39",
"skill40",
"skill41",
"skill42",
"skill43",
"skill44",
"skill45",
"skill46"
]
},
*/
/*
{
"group": "g2",
"set": [
"<5secs",
"<1min",
"<1hour",
"<1day"
]
},
*/
{
"group": "g3",
"set": [
"unsure, unanserablem impossible",
"philiosophical, optimistic, vague, open",
"measurable, mathmatical, logical",
"clever, funny, sarcastic"
]
}, {
"group": "g4",
"set": [
"Facebook",
"Email",
"Twitter",
"Telephone",
"Linkedin"
]
}];
var id = 0;
var d = [];
var totalDataSpread = 0;
$.each(data, function(index, value) {
totalDataSpread += value.set.length;
});
console.log("totalDataSpread", totalDataSpread);
$.each(data, function(index, value) {
var segmentTotal = value.set.length;
$.each(value.set, function(i, v) {
d.push({
group: value.group,
label: v,
id: id++,
value: 1 // ((segmentTotal/totalDataSpread)*10)
});
});
var gapSize = 10;
if (segmentTotal > 10) {
gapSize = 20;
}
//console.log("create GAP", value.set);
d.push({
group: "gap",
label: "gap " + id,
id: -1,
value: gapSize
});
});
console.log("d", d);
data = d;
var lineColors = ["e2d7c7",
"d7b093",
"c04830",
"fffcef",
"4aaba2",
"c94f42",
"52b0a2"
];
var lineData = [{
group: 1,
plotSets: [
"skill1",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 1,
plotSets: [
"skill2",
"<1min",
"unsure, unanserablem impossible",
"Facebook"
]
}, {
group: 4,
plotSets: [
"skill3",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 3,
plotSets: [
"skill4",
"<5secs",
"unsure, unanserablem impossible",
"Email"
]
}, {
group: 3,
plotSets: [
"skill5",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill6",
"<5secs",
"unsure, unanserablem impossible",
"Email"
]
}, {
group: 3,
plotSets: [
"skill7",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 3,
plotSets: [
"skill8",
"<5secs",
"unsure, unanserablem impossible",
"Twitter"
]
}, {
group: 4,
plotSets: [
"skill9",
"<1day",
"clever, funny, sarcastic",
"Telephone"
]
}, {
group: 3,
plotSets: [
"skill10",
"<5secs",
"unsure, unanserablem impossible",
"Twitter"
]
}, {
group: 2,
plotSets: [
"skill11",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill12",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill13",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill14",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill15",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill16",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill17",
"<1hour",
"unsure, unanserablem impossible",
"Email"
]
}, {
group: 4,
plotSets: [
"skill18",
"<1day",
"unsure, unanserablem impossible",
"Facebook"
]
}, {
group: 4,
plotSets: [
"skill19",
"<5secs",
"clever, funny, sarcastic",
"Telephone"
]
}, {
group: 3,
plotSets: [
"skill20",
"<5secs",
"unsure, unanserablem impossible",
"Linkedin"
]
}, {
group: 4,
plotSets: [
"skill21",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 3,
plotSets: [
"skill22",
"<1hour",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill23",
"<1hour",
"unsure, unanserablem impossible",
"Twitter"
]
}, {
group: 3,
plotSets: [
"skill24",
"<5secs",
"unsure, unanserablem impossible",
"Linkedin"
]
}, {
group: 4,
plotSets: [
"skill25",
"<1day",
"unsure, unanserablem impossible",
"Email"
]
}, {
group: 4,
plotSets: [
"skill26",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill27",
"<5secs",
"unsure, unanserablem impossible",
"Facebook"
]
}, {
group: 4,
plotSets: [
"skill28",
"<5secs",
"unsure, unanserablem impossible",
"Facebook"
]
}, {
group: 3,
plotSets: [
"skill29",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 3,
plotSets: [
"skill30",
"<5secs",
"unsure, unanserablem impossible",
"Linkedin"
]
}, {
group: 3,
plotSets: [
"skill31",
"<1day",
"clever, funny, sarcastic",
"Telephone"
]
}, {
group: 3,
plotSets: [
"skill32",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill33",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill34",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 2,
plotSets: [
"skill35",
"<5secs",
"unsure, unanserablem impossible",
"Twitter"
]
}, {
group: 1,
plotSets: [
"skill36",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill37",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill38",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill39",
"<1day",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill40",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill41",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 2,
plotSets: [
"skill42",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 4,
plotSets: [
"skill43",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 2,
plotSets: [
"skill44",
"<5secs",
"unsure, unanserablem impossible",
"Telephone"
]
}, {
group: 2,
plotSets: [
"skill45",
"<5secs",
"clever, funny, sarcastic",
"Twitter"
]
}];
//add gaps
change(data);
function change(data) {
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data));
slice.enter()
.insert("path")
.attr('fill', function(d, i) {
return colores_google(i);
})
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice
.exit()
.remove();
var placeholders = svg.select(".placeholders").selectAll("circle.placeholder")
.data(pie(data));
placeholders.enter()
.insert("circle")
.style("fill", function(d) {
return "white";
})
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("x", function(d) {
return arc.centroid(d)[0];
})
.attr("y", function(d) {
return arc.centroid(d)[1];
})
.attr("data-set", function(d) {
return d.data.label;
})
.attr("r", "5")
.attr("id", function(d) {
return "p" + d.data.id;
})
.attr("class", function(d) {
return "placeholder " + d.data.group;
});
placeholders
.transition().duration(1000)
placeholders.exit()
.remove();
/*removing mid arcs on gaps*/
var gapplaceholders = svg.select(".placeholders").selectAll("circle.placeholder.gap");
gapplaceholders.remove();
/*removing mid arcs on gaps*/
var labelholders = svg.select(".labelholders").selectAll("text.labelholder")
.data(pie(data));
labelholders.enter()
.insert("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("dy", -5)
.text(function(d) {
return d.data.label; //d.data.id;
})
.attr("class", function(d) {
return "labelholder " + d.data.group;
});
labelholders
.transition().duration(1000)
labelholders.exit()
.remove();
//gap place holder circles
var gapplaceholders = svg.select(".gapplaceholders");
var arcradius = radius * 0.85;
var circleradius = 1.5;
var lineCount = lineData.length;
// Approx number of circles we can fit around the circumference
var n = (Math.PI * 2 * arcradius) / (2 * circleradius);
var baseX2Angle = 0.5;
var gapcoords = [];
for (var i = 0; i < lineCount; i++) {
var ang = ((Math.PI * 2 * i) / n) - baseX2Angle;
var cx = arcradius * Math.sin(ang);
var cy = arcradius * Math.cos(ang);
gapplaceholders.append("circle")
.attr('cx', cx)
.attr('cy', cy)
.attr('class', "gapcircles")
.attr('r', circleradius);
gapcoords.push({
"x": cx,
"y": cy
});
}
//gap place holder circles
$.each(lineData, function(index, value) {
var coords = [];
var group = value.group;
$.each(value.plotSets, function(i, v) {
$('[data-set="' + v + '"]').each(function() {
var x = $(this).attr("x");
var y = $(this).attr("y");
coords.push({
"x": x,
"y": y
});
});
});
//console.log("coords", coords);
var baseX = 60;
coords.push({
"x": gapcoords[index].x,
"y": gapcoords[index].y
});
coords.push({
"x": (3 * index) - baseX,
"y": radius + 200
});
var maxLeng = coords.length - 2;
var linebatch = svg.append("g")
.attr("class", "linebatch")
$.each(coords, function(i, v) {
var line = linebatch.append("line")
.style("stroke", function(d) {
return lineColors[group];
})
.attr("x1", coords[i]["x"])
.attr("y1", coords[i]["y"])
.attr("x2", coords[i + 1]["x"])
.attr("y2", coords[i + 1]["y"]);
if (i == maxLeng) {
return false;
}
});
});
};