第一次使用D3并且我坚持认为应该简单的事情:
我正在尝试制作百分比宽度条形图SVG,我想将每个条形图的宽度设置为它将创建的“条形图”的数量。
svg.selectAll(".bar")
.data(function(d) {return d.values;})
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.browser); })
.attr("width", function(d) { return (100 / d.browser.length);})
.attr("y", function(d) { return y(d.time); })
.attr("height", function(d) { return height - y(d.time); })
.attr("fill", function(d) {return "#"+d.colour;})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
不起作用的关键部分是:.attr("width", function(d) { return (100 / d.browser.length);})
哪个不起作用。以下是我的TSV数据样本:
test browser time colour
1 - attr selector Chrome 65 fad009
1 - attr selector Firefox 125 dd8e27
1 - attr selector Opera 72 cc0f16
1 - attr selector IE9 140 27b7ed
1 - attr selector Android-4 120 80bd01
2 - attr qualified Chrome 64 fad009
2 - attr qualified Firefox 132 dd8e27
2 - attr qualified Opera 78 cc0f16
2 - attr qualified IE9 120 27b7ed
2 - attr qualified Android-4 145 80bd01
第1列和第2列都是常量,因为它们只是5个值中的一个,而我可以在那里硬编码20%,我想正确设置它,这样我就可以添加另一组结果了空格正确。
我的JS-fu很弱,所以随意光顾我,就像你在教孩子一样;)
有什么想法吗?
进一步要求代码:
// Adapted from http://bl.ocks.org/officeofjane/7315455
var margin = {top: 45, right: 20, bottom: 20, left: 200},
width = 850 - margin.left - margin.right,
height = 90 - margin.top - margin.bottom;
var formatPercent = d3.format(".0%");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.1);
// Scales. Note the inverted domain fo y-scale: bigger is up!
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickFormat(formatPercent);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong>" + d.test + "\t" + d.browser + "</strong><br/><span style='color:#fff'>" + d.time + " ms</span>";
});
// csv loaded asynchronously
d3.tsv("data2.tsv", type, function(data) {
// Data is nested by country
var selectorTests = d3.nest()
.key(function(d) { return d.test; })
.entries(data);
// Compute the minimum and maximum year and percent across symbols.
x.domain(data.map(function(d) { return d.browser; }));
y.domain([0, d3.max(selectorTests, function(s) { return s.values[0].time; })]);
// Add an SVG element for each country, with the desired dimensions and margin.
var svg = d3.select("#selectors").selectAll("svg")
.data(selectorTests)
.enter().append("svg")
.attr({
"width": "100%",
"height": "100%"
})
.attr("viewBox", "0 0 " + width + " " + height )
.attr("preserveAspectRatio", "xMidYMid meet")
.attr("pointer-events", "all")
.append("g").attr("transform", "translate(0,0)");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.append("text")
.attr("x", "0")
.attr("y", '-100%')
.attr("dy", ".71em")
.attr("text-anchor", "start")
.attr("font-size", "1.1em")
.text(function(d) { return d.key;});
// Accessing nested data: https://groups.google.com/forum/#!topic/d3-js/kummm9mS4EA
svg.selectAll(".bar")
.data(function(d) {return d.values;})
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.browser); })
.attr("width", data.length)
.attr("y", function(d) { return y(d.time); })
.attr("height", function(d) { return height - y(d.time); })
.attr("fill", function(d) {return "#"+d.colour;})
.on('mouseover', tip.show)
.on('mouseout', tip.hide);
svg.call(tip);
});
function type(d) {
d.time = +d.time;
return d;
}
如果我只使用data.length
我得到'10'这是'条目'的总数(道歉我可能在这里完全不正确的术语) - 我希望/期望看到'5',因为那是每个实例创建的柱数给出数据。希望有道理吗?
答案 0 :(得分:0)
我认为可视化您的数据格式化和“传播”的方式很有用:
d3.nest以这种格式返回您的数据:
[
{key: "1 - attr selector", values: [
{test: "1 - attr selector", browser: "Chrome", time: 65, colour: "fad009"},
{test: "1 - attr selector", browser: "Firefox", time: 125, colour: "dd8e27"},
...
]},
{key: "2 - attr qualified", values: [
{test: "2 - attr qualified", browser: "Chrome", time: 64, colour: "fad009"},
{test: "2 - attr qualified", browser: "Firefox", time: 132, colour: "dd8e27"},
....
]},
...
]
然后您有两个后续调用data
:一个在svg定义中,另一个在您发布的第一个代码段中。在第一个元素之后,d
元素的格式为
{key: "1 - attr selector", values: [
{test: "1 - attr selector", browser: "Chrome", time: 65, colour: "fad009"},
{test: "1 - attr selector", browser: "Firefox", time: 125, colour: "dd8e27"},
...
]}
这是您应该致电d.values.length
以获取该特定测试的浏览器数量的地方。
第二次调用data
后,您.data(function(d) {return d.values;})
每个d
元素的格式为
{test: "1 - attr selector", browser: "Chrome", time: 65, colour: "fad009"}
你看到,此时调用d.browser.length
将返回带有浏览器名称的字符串长度 - 实际上并不是你想要的。
你必须在第二次调用data
之前获得浏览器的数量,但是在调用之后你必须使用它 - 这就是问题所在。您需要获取父数据
我希望我能把问题告诉你。
谈论解决方案,有几个。我不确定,但是d3.select(this.parentNode).datum().length
或d3.select(this).node().parentNode.__data__.length
或类似的内容可以代替d.browser.length
。或者你可以记住一个变量中的长度(更好的是,一个数组:每个测试可能有不同数量的测试浏览器),然后使用它。