如何制作信息框并附上图表 d3.js
How to make information box and attach it with chart in d3.js
是否可以按照附图中的 d3.js 创建图表?特别是信息框。上下文来自特定的开始和结束日期,如果数据在日期丢失,请在图表中放置一个点而不是条形图。我面临的困难是使用 d3.js.
使用线将信息框与点连接起来
整个图表应使用 (SVG) d3.js 实现。
谁能给出任何数据集的解决方案示例?
这只是一个示例,希望它足以让您入门。
const url = "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json"
const margin = {
top: 30,
left: 40,
right: 40,
bottom: 100
};
const width = 800;
const height = 300;
const svg = d3.select("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const g = svg.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
const notice = svg.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top + height})`)
notice.append('rect')
.classed('notice-box', true)
.attr('x', 0)
.attr('y', margin.top)
.attr('width', width)
.attr('height', margin.bottom - margin.top);
const warning = notice.append('text')
.attr('x', 10)
.attr('y', margin.top + 30);
const format = d3.timeFormat("Q%q %Y")
const setWarning = (data) => {
warning.text(`Missing data for ${data.map(d => format(d.date)).join(', ')}`);
notice.selectAll('line')
.data(data)
.enter()
.append('line')
.attr('stroke', 'black')
.attr('x1', d => x(d.date))
.attr('y1', margin.top)
.attr('x2', d => x(d.date))
.attr('y2', y(0) - height);
notice.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('fill', 'black')
.attr('r', 3)
.attr('cx', d => x(d.date))
.attr('cy', y(0) - height);
}
var x = d3.scaleTime().range([0, width]);
const y = d3.scaleLinear().range([height, 0]);
// Since v5 d3.json is promise-based, hence the change.
d3.json(url)
.then(response => response.data)
.then(data => data.map(([date, value]) => ({
date: new Date(date),
value: value
})))
.then(data => {
data.filter(({
date
}) => date.getFullYear() >= 2000 && date.getFullYear() <= 2005 && date.getMonth() === 0)
.forEach(d => d.value = null);
x.domain(d3.extent(data.map(({
date
}) => date)));
const barWidth = width / data.length;
y.domain([0, d3.max(data.map(({
value
}) => value))]);
g.append('g')
.call(d3.axisBottom().scale(x))
.attr('id', 'x-axis')
.attr('transform', `translate(0, ${height})`);
g.append('g')
.call(d3.axisLeft(y))
.attr('id', 'y-axis');
g.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', d => x(d.date))
.attr('y', d => y(d.value))
.attr('width', barWidth)
.attr('height', d => height - y(d.value))
.style('fill', '#33adff');
const missing = data.filter(({
value
}) => value === null);
setWarning(missing);
});
#y-axis path {
stroke: black;
stroke-width: 1;
fill: none;
}
#x-axis path {
stroke: black;
stroke-width: 1;
fill: none;
}
.notice-box {
fill: none;
stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg></svg>
是否可以按照附图中的 d3.js 创建图表?特别是信息框。上下文来自特定的开始和结束日期,如果数据在日期丢失,请在图表中放置一个点而不是条形图。我面临的困难是使用 d3.js.
使用线将信息框与点连接起来整个图表应使用 (SVG) d3.js 实现。
谁能给出任何数据集的解决方案示例?
这只是一个示例,希望它足以让您入门。
const url = "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json"
const margin = {
top: 30,
left: 40,
right: 40,
bottom: 100
};
const width = 800;
const height = 300;
const svg = d3.select("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const g = svg.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
const notice = svg.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top + height})`)
notice.append('rect')
.classed('notice-box', true)
.attr('x', 0)
.attr('y', margin.top)
.attr('width', width)
.attr('height', margin.bottom - margin.top);
const warning = notice.append('text')
.attr('x', 10)
.attr('y', margin.top + 30);
const format = d3.timeFormat("Q%q %Y")
const setWarning = (data) => {
warning.text(`Missing data for ${data.map(d => format(d.date)).join(', ')}`);
notice.selectAll('line')
.data(data)
.enter()
.append('line')
.attr('stroke', 'black')
.attr('x1', d => x(d.date))
.attr('y1', margin.top)
.attr('x2', d => x(d.date))
.attr('y2', y(0) - height);
notice.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('fill', 'black')
.attr('r', 3)
.attr('cx', d => x(d.date))
.attr('cy', y(0) - height);
}
var x = d3.scaleTime().range([0, width]);
const y = d3.scaleLinear().range([height, 0]);
// Since v5 d3.json is promise-based, hence the change.
d3.json(url)
.then(response => response.data)
.then(data => data.map(([date, value]) => ({
date: new Date(date),
value: value
})))
.then(data => {
data.filter(({
date
}) => date.getFullYear() >= 2000 && date.getFullYear() <= 2005 && date.getMonth() === 0)
.forEach(d => d.value = null);
x.domain(d3.extent(data.map(({
date
}) => date)));
const barWidth = width / data.length;
y.domain([0, d3.max(data.map(({
value
}) => value))]);
g.append('g')
.call(d3.axisBottom().scale(x))
.attr('id', 'x-axis')
.attr('transform', `translate(0, ${height})`);
g.append('g')
.call(d3.axisLeft(y))
.attr('id', 'y-axis');
g.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', d => x(d.date))
.attr('y', d => y(d.value))
.attr('width', barWidth)
.attr('height', d => height - y(d.value))
.style('fill', '#33adff');
const missing = data.filter(({
value
}) => value === null);
setWarning(missing);
});
#y-axis path {
stroke: black;
stroke-width: 1;
fill: none;
}
#x-axis path {
stroke: black;
stroke-width: 1;
fill: none;
}
.notice-box {
fill: none;
stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg></svg>