我正在尝试创建这个特定的d3应用程序,其中可以像这样动态显示一系列数据。每个段包含两个数据。
第一步是打印圆圈,使系列之间有足够的空间,但最大的圆圈总是在较小的圆圈下。
// 版本3 - 包含正确的标签和图例 http://jsfiddle.net/0ht35rpb/33/
// ******版本2小提琴****** http://jsfiddle.net/1oka61mL/10/
- 如何正确设置对角线标签 - 相同角度,正确对齐? - 添加传奇? - 以相反的颜色掩盖底部指针然后以不同的颜色继续线?
// ******最新Jsfiddle ****** http://jsfiddle.net/0ht35rpb/26/
var width = 600;
var height = 400;
var svg = d3.select('svg').attr("width", width).attr("height", height);
//Count
//Checkins
//Popularity
var data = [{
"name": "Twitter",
"items": [{
"id": 0,
"label": "Count",
"value": 200
}, {
"id": 1,
"label": "Checkins",
"value": 1000
}, {
"id": 2,
"label": "Popularity",
"value": 30
}]
}, {
"name": "Facebook",
"items": [{
"id": 0,
"label": "Count",
"value": 500
}, {
"id": 1,
"label": "Checkins",
"value": 300
}, {
"id": 2,
"label": "Popularity",
"value": 740
}]
}, {
"name": "Ebay",
"items": [{
"id": 0,
"label": "Count",
"value": 4000
}, {
"id": 1,
"label": "Checkins",
"value": 1000
}, {
"id": 2,
"label": "Popularity",
"value": 40
}]
}, {
"name": "Foursquare",
"items": [{
"id": 0,
"label": "Count",
"value": 2000
}, {
"id": 1,
"label": "Checkins",
"value": 3000
}, {
"id": 2,
"label": "Popularity",
"value": 4500
}]
}];
var outerRadius = [];
// organise the data.
// Insert indices and sort items in each series
// keep a running total of max circle size in each series
// for later positioning
var x = 0;
var totalWidth = d3.sum(
data.map(function(series) {
series.items.forEach(function(item, i) {
item.index = i;
});
series.items.sort(function(a, b) {
return b.value - a.value;
});
var maxr = Math.sqrt(series.items[0].value);
outerRadius.push(maxr);
x += maxr;
series.xcentre = x;
x += maxr;
return maxr * 2;
})
);
// make scales for position and colour
var scale = d3.scale.linear().domain([0, totalWidth]).range([0, width]);
//var colScale = d3.scale.category10();
function colores_google(n) {
var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f"];
return colores_g[n % colores_g.length];
}
// add a group per series, position the group according to the values and position scale we calculated above
var groups = svg.selectAll("g").data(data);
groups.enter().append("g");
groups.attr("transform", function(d) {
return ("translate(" + d.xcentre + ",0)");
});
// then add circles per series, biggest first as items are sorted
// colour according to index (the property we inserted previously so we can
// keep track of their original position in the series)
var circles = groups.selectAll("circle").data(function(d) {
return d.items;
}, function(d) {
return d.index;
});
circles.enter().append("circle").attr("cy", height / 2).attr("cx", 0);
circles
.attr("r", function(d) {
return Math.sqrt(d.value);
})
.style("fill", function(d) {
return colores_google(d.index);
});
var labelsgroups = svg.selectAll("text").data(data);
labelsgroups.enter().append("text");
labelsgroups
.attr("y", function(d, i) {
d.y = 300;
d.cy = 200;
return 300;
})
.attr("x", function(d) {
d.x = d.xcentre;
d.cx = d.xcentre;
return d.xcentre;
})
.text(function(d) {
return d.name;
})
.each(function(d) {
var bbox = this.getBBox();
d.sx = d.x - bbox.width / 2 - 2;
d.ox = d.x + bbox.width / 2 + 2;
d.sy = d.oy = d.y + 5;
})
.attr("text-anchor", "middle");
var pointersgroups = svg.selectAll("path.pointer").data(data);
pointersgroups.enter().append("path");
pointersgroups
.attr("class", "pointer")
.attr("marker-end", "url(#circ)");
pointersgroups
.attr("d", function(d) {
return "M" + (d.xcentre) + "," + (d.oy - 25) + "L" + (d.xcentre) + "," + (d.sy - 25) + " " + d.xcentre + "," + (d.cy);
})
function fetchValue(items, label) {
for (i = 0; i <= items.length; i++) {
if (items[i].label == label) {
return items[i].value;
}
}
}
function fetchRadius(items, label) {
for (i = 0; i <= items.length; i++) {
if (items[i].label == label) {
return Math.sqrt(items[i].value);
}
}
}
/*
var labels1groups = svg.selectAll(".label1").data(data);
labels1groups.enter().append("text");
labels1groups
.attr("class", "label1")
.attr("y", function(d, i) {
d.y = 100;
d.cy = 100;
return 100;
})
.attr("x", function(d) {
d.x = d.xcentre;
d.cx = d.xcentre+50;
return d.xcentre+50;
})
.text(function(d) {
return fetchValue(d.items, "Count");
})
.attr("transform", function(d, i) {
return "translate(" + (15 * i) + "," + (i * 45) + ") rotate(-45)";
})
.each(function(d) {
var bbox = this.getBBox();
d.sx = d.x - bbox.width / 2 - 2;
d.ox = d.x + bbox.width / 2 + 2;
d.sy = d.oy = d.y ;
})
.attr("text-anchor", "left");
*/
var gridSize = 100;
var labels1groups = svg.selectAll(".label2")
.data(data)
.enter().append("text")
.text(function(d) {
return fetchValue(d.items, "Count");
//return d;
})
.attr("x", function(d, i) {
d.x = i * gridSize + 50;
d.cx = i * gridSize + 50;
return i * gridSize;
})
.attr("y", function(d, i) {
d.y = 105;
d.cy = 50;
return 0;
})
.attr("transform", function(d, i) {
return "translate(" + gridSize / 2 + ", -6)" +
"rotate(-45 " + ((i + 0.5) * gridSize) + " " + (-6) + ")";
})
.each(function(d) {
var bbox = this.getBBox();
d.sx = d.x - bbox.width / 2 - 2;
d.ox = d.x + bbox.width / 2 + 2;
d.sy = d.oy = d.y;
})
.style("text-anchor", "end")
.attr("class", function(d, i) {
return ((i >= 8 && i <= 16) ?
"timeLabel mono axis axis-worktime" :
"timeLabel mono axis");
});
var pointers1groups = svg.selectAll("path.pointer1").data(data);
pointers1groups.enter().append("path");
pointers1groups
.attr("class", "pointer1")
.attr("marker-end", "url(#circ)");
pointers1groups
.attr("d", function(d, i) {
//d.y = outerRadius[i];
//d.y = d.oy - d.cy;
//fetchRadius(d.items, "Count");
//(d.xcentre+100)
// + " " + d.cx + "," + d.cy
//return "M "+ (d.xcentre) +" 25 ,L "+ dist +" 75";
return "M" + (d.xcentre) + "," + (d.y + d.oy - fetchRadius(d.items, "Count") - 10) + "L" + (d.xcentre + 80) + "," + d.cy;
})
//年长的Jsfiddle http://jsfiddle.net/59bunh8u/51/
var rawData = [{
"name": "Twitter",
"items" : [
{
"label" : "15 billion",
"unit" : "per day",
"value" : 1500
},
{
"label" : "450 checkins",
"unit" : "per day",
"value" : 450
}
]
},
{
"name": "Facebook",
"items" : [
{
"label" : "5 billion",
"unit" : "per day",
"value" : 5000
},
{
"label" : "2000 checkins",
"unit" : "per day",
"value" : 2000
}
]
}];
$.each(rawData, function(index, value) {
var total = 0;
var layerSet = [];
var ratios = [25, 100];
$.each(value["items"], function(i, v) {
total += v["value"];
});
value["total"] = total;
});
var w = $this.data("width");
var h = $this.data("height");
var el = $this;
var margin = {
top: 65,
right: 90,
bottom: 5,
left: 150
};
var svg = d3.select(el[0]).append("svg")
.attr("class", "series")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var defs = svg.append("svg:defs");
$.each(rawData, function(i, v) {
circleDraw(i, v["items"]);
});
//calculates where each element should be placed
function calculateDistance (d, i, items) {
var dcx = 0;
for (var k = 0; k < i; k++) {
dcx += Math.sqrt(items[k].value);
}
return dcx + 10 * i;
}
function getPercentage(value, total) {
return ((value / total) * 100);
}
function circleDraw(index, data){
data.sort(function(a, b) {
return parseFloat(b.value) - parseFloat(a.value);
});
var circlelayer = svg.append("g")
.attr("class", "circlelayer");
var circle = circlelayer.selectAll("circle")
.data(data);
circle.enter().append("circle")
.attr("class", function(d, i) {
if (i == 0) {
return "blue";
}
return "gold";
})
.attr("cy", 60)
.attr("cx", function(d, i) {
return calculateDistance(d, index, data);
})
.attr("r", function(d, i) {
return Math.sqrt(d.value);
});
circle.exit().remove();
}
答案 0 :(得分:0)
以下是绘制线条的方法:
float[] results = new float[1];
Location.distanceBetween(currentlatitude, currentlongitude, originLat, originLon, results);
float distanceInMeters = results[0];
更新了jsfiddle
答案 1 :(得分:0)
我设法将对角线标记和指针对齐,指向正确的圆形颜色来表示该组。我很想对这个图表进行微调,并且可以更好地控制填充和图表宽度/高度参数。该图表看起来很稳定,但会热衷于使用不同的值和大小的数据集进行测试。
/ <强>最新强> / http://jsfiddle.net/0ht35rpb/33/
var width = 760;
var height = 400;
var svg = d3.select('#serieschart')
.append("svg:svg")
.attr("width", width)
.attr("height", height);
//Count
//Checkins
//Popularity
var data = [{
"name": "Twitter",
"items": [{
"id": 0,
"label": "Count",
"value": 200
}, {
"id": 1,
"label": "Checkins",
"value": 1000
}, {
"id": 2,
"label": "Popularity",
"value": 30
}]
}, {
"name": "Facebook",
"items": [{
"id": 0,
"label": "Count",
"value": 500
}, {
"id": 1,
"label": "Checkins",
"value": 300
}, {
"id": 2,
"label": "Popularity",
"value": 740
}]
}, {
"name": "Ebay",
"items": [{
"id": 0,
"label": "Count",
"value": 4000
}, {
"id": 1,
"label": "Checkins",
"value": 1000
}, {
"id": 2,
"label": "Popularity",
"value": 40
}]
}, {
"name": "Foursquare",
"items": [{
"id": 0,
"label": "Count",
"value": 2000
}, {
"id": 1,
"label": "Checkins",
"value": 3000
}, {
"id": 2,
"label": "Popularity",
"value": 4500
}]
}];
var legend_group = svg.append("g")
.attr("class", "legend")
.attr("width", 80)
.attr("height", 100)
.append("svg:g")
.attr("class", "legendsection")
.attr("transform", "translate(0,30)");
var legend = legend_group.selectAll("circle").data(data[0].items);
legend.enter().append("circle")
.attr("cx", 70)
.attr("cy", function(d, i) {
return 15 * i;
})
.attr("r", 7)
.attr("width", 18)
.attr("height", 18)
.style("fill", function(d, i) {
return colores_google(i);
});
legend.exit().remove();
var legendtext = legend_group.selectAll("text").data(data[0].items);
legendtext.enter().append("text")
.attr("class", "labels")
.attr("dy", function(d, i) {
return 15 * i;
})
.attr("text-anchor", function(d) {
return "start";
})
.text(function(d) {
return d.label;
});
legendtext.exit().remove();
var m = [80, 20, 20, 10];
var w =+ width - m[0];
var h =+ height - m[1];
var chart = svg.append("g")
.attr("class", "serieschart")
.attr("width", w)
.attr("height", h);
var outerRadius = [];
// organise the data.
// Insert indices and sort items in each series
// keep a running total of max circle size in each series
// for later positioning
var x = 0;
var totalWidth = d3.sum(
data.map(function(series) {
series.items.forEach(function(item, i) {
item.index = i;
});
series.items.sort(function(a, b) {
return b.value - a.value;
});
var maxr = Math.sqrt(series.items[0].value);
outerRadius.push(maxr);
x += maxr;
series.xcentre = x;
x += maxr;
return maxr * 2;
})
);
// make scales for position and colour
var scale = d3.scale.linear().domain([0, totalWidth]).range([0, w]);
//var colScale = d3.scale.category10();
function colores_google(n) {
var colores_g = ["#f7b363", "#448875", "#c12f39", "#2b2d39", "#f8dd2f"];
return colores_g[n % colores_g.length];
}
function fetchValue(items, label) {
for (i = 0; i <= items.length; i++) {
if (items[i].label == label) {
return items[i].value;
}
}
}
function fetchRadius(items, label) {
for (i = 0; i <= items.length; i++) {
if (items[i].label == label) {
return Math.sqrt(items[i].value);
}
}
}
// add a group per series, position the group according to the values and position scale we calculated above
var groups = chart.selectAll("g.seriesGroup").data(data);
var newGroups = groups.enter().append("g").attr("class", "seriesGroup");
newGroups.append("text")
.attr("class", "seriesName")
.attr("text-anchor", "middle");
newGroups.append("line")
.attr("class", "seriesName")
.attr("y1", h - 40)
.attr("y2", h / 2);
newGroups.append("text")
.attr("class", "datumValue")
.attr("y", 10)
//.attr("transform", "rotate(-45)")
;
newGroups.append("g").attr("class", "circleGroup");
newGroups.append("g").attr("class", "datumLine")
.append("line")
.attr("class", "datumValue")
.attr("y2", 40);
var focus = "Count";
groups.attr("transform", function(d) {
return "translate(" + scale(d.xcentre) + ",0)";
});
groups.select("text.seriesName")
.text(function(d) {
return d.name;
})
.attr("y", h - 20);
groups.select("text.datumValue")
.text(function(d) {
return fetchValue(d.items, focus);
})
.attr("transform", function(d) {
return "translate(" + ((h / 2) - 20 - scale(fetchRadius(d.items, focus))) + ",20) rotate(-45)";
});
groups.select("line.datumValue")
.attr("y1", function(d) {
return (h / 2) - scale(fetchRadius(d.items, focus));
})
.attr("x2", function(d) {
return (h / 2) - scale(fetchRadius(d.items, focus) + 20);
});
// then add circles per series, biggest first as items are sorted
// colour according to index (the property we inserted previously so we can
// keep track of their original position in the series)
var circles = groups
.select(".circleGroup")
.selectAll("circle").data(function(d) {
return d.items;
}, function(d) {
return d.index;
});
circles.enter().append("circle").attr("cy", h / 2).attr("cx", 0);
circles
.attr("r", function(d) {
return scale(Math.sqrt(d.value));
})
.style("fill", function(d) {
return colores_google(d.index);
});