我正在尝试使用d3 js显示stak图表。我也尝试使用对数刻度,但没有开始工作。
8月份赌注栏未正确显示,或者可能会有更多此类案例。
如何使用对数比例正确显示?
var margins = {
top: 12,
left: 48,
right: 24,
bottom: 24
},
legendPanel = {
width: 180
},
width = 500 - margins.left - margins.right - legendPanel.width,
height = 100 - margins.top - margins.bottom,
dataset = [{
data: [{
month: 'Aug',
count: 1
}, {
month: 'feb',
count: 234
}, {
month: 'mar',
count: 345
}],
name: 'Series #1'
}, {
data: [{
month: 'Aug',
count: 3
}, {
month: 'feb',
count: 267
}, {
month: 'mar',
count: 573
}],
name: 'Series #2'
},
{
data: [{
month: 'Aug',
count: 20
}, {
month: 'feb',
count: 267
}, {
month: 'mar',
count: 573
}],
name: 'Series #3'
}
],
series = dataset.map(function (d) {
return d.name;
}),
dataset = dataset.map(function (d) {
return d.data.map(function (o, i) {
// Structure it so that your numeric
// axis (the stacked amount) is y
return {
y: o.count,
x: o.month
};
});
}),
stack = d3.layout.stack();
stack(dataset);
var dataset = dataset.map(function (group) {
return group.map(function (d) {
// Invert the x and y values, and y0 becomes x0
return {
x: d.y,
y: d.x,
x0: d.y0
};
});
}),
svg = d3.select('body')
.append('svg')
.attr('width', width + margins.left + margins.right + legendPanel.width)
.attr('height', height + margins.top + margins.bottom)
.append('g')
.attr('transform', 'translate(' + margins.left + ',' + margins.top + ')'),
xMax = d3.max(dataset, function (group) {
return d3.max(group, function (d) {
return d.x + d.x0;
});
}),
xScale = d3.scale.linear()
.domain([0, xMax])
.range([0, width]),
months = dataset[0].map(function (d) {
return d.y;
}),
_ = console.log(months),
yScale = d3.scale.ordinal()
.domain(months)
.rangeRoundBands([0, height], .1),
xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom'),
yAxis = d3.svg.axis()
.scale(yScale)
.orient('left'),
colours = d3.scale.category10(),
groups = svg.selectAll('g')
.data(dataset)
.enter()
.append('g')
.style('fill', function (d, i) {
return colours(i);
}),
rects = groups.selectAll('rect')
.data(function (d) {
return d;
})
.enter()
.append('rect')
.attr('x', function (d) {
return xScale(d.x0);
})
.attr('y', function (d, i) {
return yScale(d.y);
})
.attr('height', function (d) {
return yScale.rangeBand();
})
.attr('width', function (d) {
return xScale(d.x);
})
.on('mouseover', function (d) {
var xPos = parseFloat(d3.select(this).attr('x')) / 2 + width / 2;
var yPos = parseFloat(d3.select(this).attr('y')) + yScale.rangeBand() / 2;
d3.select('#tooltip')
.style('left', xPos + 'px')
.style('top', yPos + 'px')
.select('#value')
.text(d.x);
d3.select('#tooltip').classed('hidden', false);
})
.on('mouseout', function () {
d3.select('#tooltip').classed('hidden', true);
})
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'axis')
.call(yAxis);
svg.append('rect')
.attr('fill', 'yellow')
.attr('width', 160)
.attr('height', 30 * dataset.length)
.attr('x', width + margins.left)
.attr('y', 0);
series.forEach(function (s, i) {
svg.append('text')
.attr('fill', 'black')
.attr('x', width + margins.left + 8)
.attr('y', i * 24 + 24)
.text(s);
svg.append('rect')
.attr('fill', colours(i))
.attr('width', 60)
.attr('height', 20)
.attr('x', width + margins.left + 90)
.attr('y', i * 24 + 6);
});
示例代码jsfiddle
答案 0 :(得分:0)
d3中有内置的对数刻度,但还需要进行一些修改。 您需要做的第一件事是将xScale更改为对数:
xScale = d3.scale.log()
.domain([0.5, xMax])//The x-min can not be 0!
.range([0, width]),
注意xmin是0.5而不是0.因为0不能以对数标度存在。放置大于1的任何东西都会使得系列#1的8月不可见,因为它是1。
您需要的第二件事是以不同的方式计算宽度,因为您的比例不再是线性的,即10-> 20宽于110-> 120:
.attr('width', function (d) {
return xScale(d.x0+d.x)- (d.x0==0 ? 0 : xScale(d.x0));
})
这只是取结束点(d.x0+d.x)
的位置并减去起点d.x0
的位置。不是如果d.x0 == 0
,则0用作起始位置,因为0在xScale中不存在
最后,默认情况下会将刻度显示为1e+02
,因此请更改刻度线的格式
xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom')
.ticks(0, '.1s'),
请参阅jsfiddle