我尝试使用D3实现条形图,但似乎给了我这样的错误:
错误:属性x:预期长度“ NaN”。
这是我的代码:
let url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json";
let margin = {
left: 80,
right: 20,
top: 20,
bottom: 20
};
let w = 1000 - margin.left - margin.right;
let h = 500 - margin.top - margin.bottom;
d3.json(url).then((json) => {
let data = json.data;
let end = data.length - 1;
let minDate = data[0][0];
let maxDate = data[end][0];
let xScale = d3.scaleTime()
.domain([minDate, maxDate])
.range([margin.left, w])
let yScale = d3.scaleLinear()
.domain([0, d3.max(data, (d) => {
return d[1];
})])
.range([h, 0])
let yAxis = d3.axisLeft(yScale)
.ticks(10, "");
let xAxis = d3.axisBottom(xScale)
.tickFormat(d3.timeFormat("%Y"), 5)
let div = d3.select("body").append("div")
let svg = d3.select("svg").attr('width', w).attr('height', h);
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function (d) {
console.log(d[0].length)
return xScale(new Date(d[0]))
})
.attr("y", function (d) {
return (yScale(d[1]))
})
.attr("height", function (d) {
return (h - (yScale(d[1])))
})
.attr("width", function (d) {
return (Math.ceil(w / 274))
})
})
答案 0 :(得分:1)
这里有两个问题:
在创建xScale
时,您传递的不是Date
对象。相反,您需要创建minDate
的{{1}}和maxDate
实例:
Date
执行此操作时,您不会附加任何SVG:
let minDate = new Date(data[0][0]);
let maxDate = new Date(data[end][0]);
let xScale = d3.scaleTime()
.domain([minDate, maxDate])
.range([margin.left, w]);
这将在第一行上附加一个let div = d3.select("body").append("div")
let svg = d3.select("svg").attr('width', w).attr('height', h);
,并在第二行上创建一个空选择,因为至少在您提供的代码中还没有任何<div>
可供选择。您需要创建一个SVG并保留对该选择的引用:
<svg>
看看下面的演示:
// Create a div.
let div = d3.select("body").append("div")
// Append the SVG to the above created div and store the reference in svg.
let svg = div.append("svg").attr('width', w).attr('height', h);
let url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json";
let margin = {
left: 80,
right: 20,
top: 20,
bottom: 20
};
let w = 1000 - margin.left - margin.right;
let h = 500 - margin.top - margin.bottom;
d3.json(url).then((json) => {
let data = json.data;
let end = data.length - 1;
let minDate = new Date(data[0][0]);
let maxDate = new Date(data[end][0]);
let xScale = d3.scaleTime()
.domain([minDate, maxDate])
.range([margin.left, w])
let yScale = d3.scaleLinear()
.domain([0, d3.max(data, (d) => {
return d[1];
})])
.range([h, 0])
let yAxis = d3.axisLeft(yScale)
.ticks(10, "");
let xAxis = d3.axisBottom(xScale)
.tickFormat(d3.timeFormat("%Y"), 5)
let div = d3.select("body").append("div")
let svg = div.append("svg").attr('width', w).attr('height', h);
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function (d) {
return xScale(new Date(d[0]))
})
.attr("y", function (d) {
return (yScale(d[1]))
})
.attr("height", function (d) {
return (h - (yScale(d[1])))
})
.attr("width", function (d) {
return (Math.ceil(w / 274))
})
})
.catch(e => console.log(e));