以我刚接触D3的事实开头,这可能是我所缺少的一个简单错误-我知道一定是这样。我正在尝试访问数据的方式。
试图弄清楚这个家伙一段时间。 (也许我看了太久了)
我一直玩到它,直到我的台词 finally 完全出现为止,但是现在它并没有显示完整的台词,只有两点-这是我不确定的数字。
谢谢!
编辑:目标是使用lineData [0]沿lineData 1(月)的x轴绘制一条线。最终,lineData 2将用于第二行,但此刻只是试图使第一行工作。
编辑:更新的代码(根据Shashank的建议)可以在这里找到: https://codepen.io/anon/pen/RevxYG?editors=0010
这是我的代码:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
console.log("lineData", lineData)
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleOrdinal()
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d[0]); });
// create svg container
let lineChart = d3.select(element)
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
lineChart.append("path")
.datum(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData)
.attr("d", line)
.enter()
.append("circle")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(i)})
.attr("cy", function(d) { return yScale(d[0])})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
数据正在通过函数传递。
答案 0 :(得分:1)
遗漏点:
除了输出范围是连续的和数字的,带刻度类似于序数刻度。
为什么不使用d3.scaleOrdinal
?这是一个示例:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
let xScale = d3.scaleOrdinal().range(lineData[2])
.domain(lineData[0]);
console.log('domain is: ' + xScale.domain());
console.log('range is: ' + xScale.range());
<script src="https://d3js.org/d3.v4.min.js"></script>
您会看到重复的值如何映射到对您的情况无济于事的月份,因此d3.scaleBand()
(您也可以使用d3.scalePoint
。Read more about it in this answer. < / p>
使用上述频段比例,您将通过以下方式将域设置为lineData[2]
:
xScale = d3.scaleBand().domain(lineData[2])
未将转换应用于line
和circles
。因此,我附加了<g>
容器以分别包含直线和圆并转换了这些组元素。例如:
var dots = lineChart.append('g')
.attr("transform", "translate(20, 0)");
下面的解决方案仅在将第一行添加到图表时回答此特定问题。正如您在评论中提到的那样,您最终将第二个元素添加为另一行时,path
的选择将会更改
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleBand().domain(lineData[2])
.rangeRound([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(lineData[2][i]) + xScale.bandwidth()/2;
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.data(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
var dots = lineChart.append('g')
.attr("transform", "translate(20, 0)");
dots.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle").classed('dot', true)
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(lineData[2][i]) + xScale.bandwidth()/2})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
<script src="https://d3js.org/d3.v4.min.js"></script>
建议:像对yScale
[0,52]一样,将域设置为静态值不是一个好习惯。尝试使用d3.extent或d3.min方法。
希望这会有所帮助。
编辑:当您尝试使用d3.scalePoint
时,在line
函数和圆圈中选择xScale值时犯了一个小错误。您需要在fn行中选择categories[i]
,如下所示:
.x(function(d, i) {
return xScale(categories[i]);
})
使用d3.scalePoint更新的代码段
let data = {
'New': [4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
'Terminated': [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]
};
let categories = ["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"];
let lineData = [data.New, data.Terminated, categories];
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 60]).nice()
.range([height - 40 , 0]);
let xScale = d3.scalePoint()
.domain(lineData[2].map(function(d, i) { return d; }))
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(categories[i]);
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.datum(lineData)
.attr("d", function(d) { return line(d[0]); })
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle")
.attr("transform", "translate(20, 0)")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(categories[i])})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
<script src="https://d3js.org/d3.v4.min.js"></script>
希望这也有帮助。