在开始日期和结束日期之间附加一行
Appending a Line between a start and end date
基本上我使用 D3 创建基于甘特图的图表。我有一个 .json 文件,其中包含我的数据,并且能够创建显示适当信息的 x-y 刻度。我遇到的这个问题是,我希望这些行在数组中的 15 个项目中的每一个的开始日期和结束日期之间延伸,所有这些都包含名称、开始日期和结束日期。当我打开图表时,信息会显示,但它只显示一条从 y 轴开始的实线,它一直延伸到个人开始日期。
在尝试补救这种情况时,我意识到通过将今天的日期添加为数组中 startDate 下的新项目,任何日期为今天的项目都完全按照我的要求执行,而其他项目则不然。我不确定是什么原因造成的,但推测这可能与日期的解析方式有关?完全不知所措,因为我还是 d3 的新手。
// employment.json
[
{
"name": "Placeholder 1",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 2",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2018-10-31"
},
{
"name": "Placeholder 3",
"position": "Occupation 1",
"startDate": "2013-11-05",
"endDate": "2014-03-03"
},
{
"name": "Placeholder 4",
"position": "Occupation 1",
"startDate": "2014-05-09",
"endDate": "2015-04-06"
},
{
"name": "Placeholder 5",
"position": "Occupation 1",
"startDate": "2014-12-01",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 6",
"position": "Occupation 1",
"startDate": "2015-04-20",
"endDate": "2016-10-18"
},
{
"name": "Placeholder 7",
"position": "Occupation 1",
"startDate": "2016-05-05",
"endDate": "2019-07-31"
},
{
"name": "Placeholder 8",
"position": "Occupation 1",
"startDate": "2016-11-07",
"endDate": "2017-05-12"
},
{
"name": "Placeholder 9",
"position": "Occupation 1",
"startDate": "2017-09-18",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 10",
"position": "Occupation 1",
"startDate": "2018-01-11",
"endDate": "2018-09-20"
},
{
"name": "Placeholder 11",
"position": "Occupation 1",
"startDate": "2018-04-17",
"endDate": "2018-07-24"
},
{
"name": "Placeholder 12",
"position": "Occupation 1",
"startDate": "2018-07-04",
"endDate": "2018-08-30"
},
{
"name": "Placeholder 13",
"position": "Occupation 1",
"startDate": "2018-07-09",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 14",
"position": "Occupation 1",
"startDate": "2019-01-16",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 15",
"position": "Occupation 1",
"startDate": "2019-04-01",
"endDate": "2019-08-01"
},
{
"name": "Total Time",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
}
]
// app.js
var margin = {top: 10, right: 30, bottom: 80, left: 100},
width = 960 - margin.left - margin.right,
height = 560 - margin.top - margin.bottom;
var svg = d3.select("#employment_history")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
d3.json('json/employment.json', function(error, data) {
if (error) {
return console.warn(error);
} else {
console.log(data);
}
var x = d3.scaleBand()
.range([0, width ])
.domain(data.map(function(d) { return d.startDate },
data.map(function(d) { return d.endDate })))
.padding(0.2);
svg.append('g')
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
var y = d3.scaleBand()
.range([ 0, height ])
.domain(data.map(function(d) { return d.name; }))
.padding(2);
svg.append("g")
.call(d3.axisLeft(y))
// Lines
svg.selectAll("myLine")
.data(data)
.enter()
.append("line")
.attr("x1", function(d) { return x(d.startDate); })
.attr("x2", function(d) { return x(d.endDate); })
.attr("y1", function(d) { return y(d.name); })
.attr("y2", function(d) { return y(d.name); })
.attr("stroke", "orange")
.attr("stroke-width", "2px")
})
控制台中没有显示错误,它提供了一个从 Y 轴开始并延伸到开始日期的图表,而不是从开始日期开始并连接到结束日期。
我正在尝试完成的示例以及创建此示例所遵循的示例是:https://www.d3-graph-gallery.com/graph/lollipop_cleveland.html
你的体重秤错误。
这里的主要问题是 x 轴,它应该使用 时间刻度 ,而不是波段刻度。那么,让我们看看必要的更改:
首先,解析数据数组中的日期:
const parse = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.startDate = parse(d.startDate);
d.endDate = parse(d.endDate);
});
然后,设置时间尺度,根据日期计算域:
var x = d3.scaleTime()
.range([0, width])
.domain([d3.min(data, function(d) {
return d.startDate
}), d3.max(data, function(d) {
return d.endDate
})]);
最后,你的 y 尺度应该是 point 尺度,而不是 band 尺度:
var y = d3.scalePoint()
.range([0, height])
.domain(data.map(function(d) {
return d.name;
}))
.padding(0.5);
这是工作代码(在较小的 SVG 中):
const data = [{
"name": "Placeholder 1",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 2",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2018-10-31"
},
{
"name": "Placeholder 3",
"position": "Occupation 1",
"startDate": "2013-11-05",
"endDate": "2014-03-03"
},
{
"name": "Placeholder 4",
"position": "Occupation 1",
"startDate": "2014-05-09",
"endDate": "2015-04-06"
},
{
"name": "Placeholder 5",
"position": "Occupation 1",
"startDate": "2014-12-01",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 6",
"position": "Occupation 1",
"startDate": "2015-04-20",
"endDate": "2016-10-18"
},
{
"name": "Placeholder 7",
"position": "Occupation 1",
"startDate": "2016-05-05",
"endDate": "2019-07-31"
},
{
"name": "Placeholder 8",
"position": "Occupation 1",
"startDate": "2016-11-07",
"endDate": "2017-05-12"
},
{
"name": "Placeholder 9",
"position": "Occupation 1",
"startDate": "2017-09-18",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 10",
"position": "Occupation 1",
"startDate": "2018-01-11",
"endDate": "2018-09-20"
},
{
"name": "Placeholder 11",
"position": "Occupation 1",
"startDate": "2018-04-17",
"endDate": "2018-07-24"
},
{
"name": "Placeholder 12",
"position": "Occupation 1",
"startDate": "2018-07-04",
"endDate": "2018-08-30"
},
{
"name": "Placeholder 13",
"position": "Occupation 1",
"startDate": "2018-07-09",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 14",
"position": "Occupation 1",
"startDate": "2019-01-16",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 15",
"position": "Occupation 1",
"startDate": "2019-04-01",
"endDate": "2019-08-01"
},
{
"name": "Total Time",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
}
];
var margin = {
top: 10,
right: 30,
bottom: 80,
left: 100
},
width = 600 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
const parse = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.startDate = parse(d.startDate);
d.endDate = parse(d.endDate);
});
var x = d3.scaleTime()
.range([0, width])
.domain([d3.min(data, function(d) {
return d.startDate
}), d3.max(data, function(d) {
return d.endDate
})]);
svg.append('g')
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
var y = d3.scalePoint()
.range([0, height])
.domain(data.map(function(d) {
return d.name;
}))
.padding(0.5);
svg.append("g")
.call(d3.axisLeft(y))
// Lines
svg.selectAll("myLine")
.data(data)
.enter()
.append("line")
.attr("x1", function(d) {
return x(d.startDate);
})
.attr("x2", function(d) {
return x(d.endDate);
})
.attr("y1", function(d) {
return y(d.name);
})
.attr("y2", function(d) {
return y(d.name);
})
.attr("stroke", "orange")
.attr("stroke-width", "2px")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
基本上我使用 D3 创建基于甘特图的图表。我有一个 .json 文件,其中包含我的数据,并且能够创建显示适当信息的 x-y 刻度。我遇到的这个问题是,我希望这些行在数组中的 15 个项目中的每一个的开始日期和结束日期之间延伸,所有这些都包含名称、开始日期和结束日期。当我打开图表时,信息会显示,但它只显示一条从 y 轴开始的实线,它一直延伸到个人开始日期。
在尝试补救这种情况时,我意识到通过将今天的日期添加为数组中 startDate 下的新项目,任何日期为今天的项目都完全按照我的要求执行,而其他项目则不然。我不确定是什么原因造成的,但推测这可能与日期的解析方式有关?完全不知所措,因为我还是 d3 的新手。
// employment.json
[
{
"name": "Placeholder 1",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 2",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2018-10-31"
},
{
"name": "Placeholder 3",
"position": "Occupation 1",
"startDate": "2013-11-05",
"endDate": "2014-03-03"
},
{
"name": "Placeholder 4",
"position": "Occupation 1",
"startDate": "2014-05-09",
"endDate": "2015-04-06"
},
{
"name": "Placeholder 5",
"position": "Occupation 1",
"startDate": "2014-12-01",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 6",
"position": "Occupation 1",
"startDate": "2015-04-20",
"endDate": "2016-10-18"
},
{
"name": "Placeholder 7",
"position": "Occupation 1",
"startDate": "2016-05-05",
"endDate": "2019-07-31"
},
{
"name": "Placeholder 8",
"position": "Occupation 1",
"startDate": "2016-11-07",
"endDate": "2017-05-12"
},
{
"name": "Placeholder 9",
"position": "Occupation 1",
"startDate": "2017-09-18",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 10",
"position": "Occupation 1",
"startDate": "2018-01-11",
"endDate": "2018-09-20"
},
{
"name": "Placeholder 11",
"position": "Occupation 1",
"startDate": "2018-04-17",
"endDate": "2018-07-24"
},
{
"name": "Placeholder 12",
"position": "Occupation 1",
"startDate": "2018-07-04",
"endDate": "2018-08-30"
},
{
"name": "Placeholder 13",
"position": "Occupation 1",
"startDate": "2018-07-09",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 14",
"position": "Occupation 1",
"startDate": "2019-01-16",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 15",
"position": "Occupation 1",
"startDate": "2019-04-01",
"endDate": "2019-08-01"
},
{
"name": "Total Time",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
}
]
// app.js
var margin = {top: 10, right: 30, bottom: 80, left: 100},
width = 960 - margin.left - margin.right,
height = 560 - margin.top - margin.bottom;
var svg = d3.select("#employment_history")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
d3.json('json/employment.json', function(error, data) {
if (error) {
return console.warn(error);
} else {
console.log(data);
}
var x = d3.scaleBand()
.range([0, width ])
.domain(data.map(function(d) { return d.startDate },
data.map(function(d) { return d.endDate })))
.padding(0.2);
svg.append('g')
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
var y = d3.scaleBand()
.range([ 0, height ])
.domain(data.map(function(d) { return d.name; }))
.padding(2);
svg.append("g")
.call(d3.axisLeft(y))
// Lines
svg.selectAll("myLine")
.data(data)
.enter()
.append("line")
.attr("x1", function(d) { return x(d.startDate); })
.attr("x2", function(d) { return x(d.endDate); })
.attr("y1", function(d) { return y(d.name); })
.attr("y2", function(d) { return y(d.name); })
.attr("stroke", "orange")
.attr("stroke-width", "2px")
})
控制台中没有显示错误,它提供了一个从 Y 轴开始并延伸到开始日期的图表,而不是从开始日期开始并连接到结束日期。
我正在尝试完成的示例以及创建此示例所遵循的示例是:https://www.d3-graph-gallery.com/graph/lollipop_cleveland.html
你的体重秤错误。
这里的主要问题是 x 轴,它应该使用 时间刻度 ,而不是波段刻度。那么,让我们看看必要的更改:
首先,解析数据数组中的日期:
const parse = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.startDate = parse(d.startDate);
d.endDate = parse(d.endDate);
});
然后,设置时间尺度,根据日期计算域:
var x = d3.scaleTime()
.range([0, width])
.domain([d3.min(data, function(d) {
return d.startDate
}), d3.max(data, function(d) {
return d.endDate
})]);
最后,你的 y 尺度应该是 point 尺度,而不是 band 尺度:
var y = d3.scalePoint()
.range([0, height])
.domain(data.map(function(d) {
return d.name;
}))
.padding(0.5);
这是工作代码(在较小的 SVG 中):
const data = [{
"name": "Placeholder 1",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 2",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2018-10-31"
},
{
"name": "Placeholder 3",
"position": "Occupation 1",
"startDate": "2013-11-05",
"endDate": "2014-03-03"
},
{
"name": "Placeholder 4",
"position": "Occupation 1",
"startDate": "2014-05-09",
"endDate": "2015-04-06"
},
{
"name": "Placeholder 5",
"position": "Occupation 1",
"startDate": "2014-12-01",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 6",
"position": "Occupation 1",
"startDate": "2015-04-20",
"endDate": "2016-10-18"
},
{
"name": "Placeholder 7",
"position": "Occupation 1",
"startDate": "2016-05-05",
"endDate": "2019-07-31"
},
{
"name": "Placeholder 8",
"position": "Occupation 1",
"startDate": "2016-11-07",
"endDate": "2017-05-12"
},
{
"name": "Placeholder 9",
"position": "Occupation 1",
"startDate": "2017-09-18",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 10",
"position": "Occupation 1",
"startDate": "2018-01-11",
"endDate": "2018-09-20"
},
{
"name": "Placeholder 11",
"position": "Occupation 1",
"startDate": "2018-04-17",
"endDate": "2018-07-24"
},
{
"name": "Placeholder 12",
"position": "Occupation 1",
"startDate": "2018-07-04",
"endDate": "2018-08-30"
},
{
"name": "Placeholder 13",
"position": "Occupation 1",
"startDate": "2018-07-09",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 14",
"position": "Occupation 1",
"startDate": "2019-01-16",
"endDate": "2019-08-01"
},
{
"name": "Placeholder 15",
"position": "Occupation 1",
"startDate": "2019-04-01",
"endDate": "2019-08-01"
},
{
"name": "Total Time",
"position": "Occupation 1",
"startDate": "2013-09-05",
"endDate": "2019-08-01"
}
];
var margin = {
top: 10,
right: 30,
bottom: 80,
left: 100
},
width = 600 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
const parse = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.startDate = parse(d.startDate);
d.endDate = parse(d.endDate);
});
var x = d3.scaleTime()
.range([0, width])
.domain([d3.min(data, function(d) {
return d.startDate
}), d3.max(data, function(d) {
return d.endDate
})]);
svg.append('g')
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
var y = d3.scalePoint()
.range([0, height])
.domain(data.map(function(d) {
return d.name;
}))
.padding(0.5);
svg.append("g")
.call(d3.axisLeft(y))
// Lines
svg.selectAll("myLine")
.data(data)
.enter()
.append("line")
.attr("x1", function(d) {
return x(d.startDate);
})
.attr("x2", function(d) {
return x(d.endDate);
})
.attr("y1", function(d) {
return y(d.name);
})
.attr("y2", function(d) {
return y(d.name);
})
.attr("stroke", "orange")
.attr("stroke-width", "2px")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>