D3 - 如何从对象数组创建多个折线图
D3 - How to create multiple line charts from an array of objects
我正在尝试从一组对象创建多个折线图,但很难理解如何绑定数据并正确创建 Y 轴和 X 轴。
以下是我正在处理的数据的简化版本:
var prices = [{
"pagination": {
"count": 6,
},
"data": [
{
"open": 9.67,
"close": 9.98,
"volume": 17876279,
"symbol": "WISH",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 10.3,
"close": 9.61,
"volume": 34099145,
"symbol": "WISH",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 10.36,
"close": 10.31,
"volume": 20379283,
"symbol": "WISH",
"date": "2021-08-03T00:00:00+0000"
}
]
},
{
"pagination": {
"count": 6,
},
"data": [
{
"open": 27.3,
"close": 28.33,
"volume": 2360664,
"symbol": "CRSR",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 26.83,
"close": 27.4,
"volume": 4409156,
"symbol": "CRSR",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 26.99,
"close": 27.13,
"volume": 8675462,
"symbol": "CRSR",
"date": "2021-08-03T00:00:00+0000"
}
]
}]
这就是我到目前为止在创建折线图时所做的工作
var priceMargin = {top: 10, right: 30, bottom: 30, left: 60},
priceWidth = 460 - priceMargin.left - priceMargin.right,
priceHeight = 400 - priceMargin.top - priceMargin.bottom;
var priceSvg = d3.selectAll(".company-price")
.data(prices, function(d){
return d.data
})
.append("svg")
.attr("width", priceWidth + priceMargin.left + priceMargin.right)
.attr("height", priceHeight + priceMargin.top + priceMargin.bottom)
.append("g")
.attr("transform", "translate(" + priceMargin.left + "," + priceMargin.top + ")")
我的目标是为数组中的每个对象创建一个折线图,它由单独的“.company-price”中的 Y(收盘价)和 X(日期)轴的值范围组成 div 容器,但不确定如何创建 X 轴和 Y 轴并访问上面传入的数据。下面是我的 HTML 结构和我想要实现的目标的截图
如有任何帮助或建议,我们将不胜感激!
想想您在 d3 中创建的 div 数组。
const div = d3.select("#companies-container");
data.map(symbol=>{
const {data, pagination} = symbol;
const companyContainer = div.append("div").attr("class","company-container");
const companyProfile = companyContainer.append("div").attr("class", "company-profile");
const companyRecommend = companyContainer.append("div").attr("class", "company-container");
const companyPrice = companyContainer.append("div").attr("class","company-price");
const svg = companyPrice.append("svg").width(400).height(200);
// All your code here
const x = scaleLinear().domain(d3.extent(data, d=>d.date)).range([margin.left, width-margin.right]);
// Calculate y, render lines etc.
})
在此处查看 JsFiddle https://jsfiddle.net/9ukd75yn/20/
这是实现此目的的一种方法,假设公司价格 div 已经创建并且与 prices
数组的顺序相同。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<body>
<div id="companies-container">
<div id="company-container">
<div class="company-price"></div>
</div>
<div id="company-container">
<div class="company-price"></div>
</div>
</div>
<script>
// data
const prices = [{
"pagination": {
"count": 6,
},
"data": [
{
"open": 9.67,
"close": 9.98,
"volume": 17876279,
"symbol": "WISH",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 10.3,
"close": 9.61,
"volume": 34099145,
"symbol": "WISH",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 10.36,
"close": 10.31,
"volume": 20379283,
"symbol": "WISH",
"date": "2021-08-03T00:00:00+0000"
}
]
},
{
"pagination": {
"count": 6,
},
"data": [
{
"open": 27.3,
"close": 28.33,
"volume": 2360664,
"symbol": "CRSR",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 26.83,
"close": 27.4,
"volume": 4409156,
"symbol": "CRSR",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 26.99,
"close": 27.13,
"volume": 8675462,
"symbol": "CRSR",
"date": "2021-08-03T00:00:00+0000"
}
]
}];
// bind the data to the company-price div
// call the lineChart function for each div
d3.selectAll('.company-price')
.data(prices)
.each(lineChart);
// function to draw line chart
function lineChart({pagination, data}) {
const priceMargin = {top: 10, right: 30, bottom: 30, left: 60};
const priceWidth = 460 - priceMargin.left - priceMargin.right;
const priceHeight = 400 - priceMargin.top - priceMargin.bottom;
// this refers to the company-price div
const svg = d3.select(this)
.append('svg')
.attr("width", priceWidth + priceMargin.left + priceMargin.right)
.attr("height", priceHeight + priceMargin.top + priceMargin.bottom)
.append("g")
.attr("transform", `translate(${priceMargin.left},${priceMargin.top})`);
// scales
const parseDate = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');
const x = d3.scaleTime()
.domain(d3.extent(data, d => parseDate(d.date)))
.range([0, priceWidth]);
const y = d3.scaleLinear()
.domain(d3.extent(data, d => d.close))
.range([priceHeight, 0]);
// line generator
const line = d3.line()
.x(d => x(parseDate(d.date)))
.y(d => y(d.close));
// draw line
svg.append('path')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('d', line(data));
// axes
svg.append('g')
.call(d3.axisLeft(y));
svg.append('g')
.attr('transform', `translate(0,${priceHeight})`)
.call(d3.axisBottom(x));
}
</script>
</body>
</html>
我正在尝试从一组对象创建多个折线图,但很难理解如何绑定数据并正确创建 Y 轴和 X 轴。
以下是我正在处理的数据的简化版本:
var prices = [{
"pagination": {
"count": 6,
},
"data": [
{
"open": 9.67,
"close": 9.98,
"volume": 17876279,
"symbol": "WISH",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 10.3,
"close": 9.61,
"volume": 34099145,
"symbol": "WISH",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 10.36,
"close": 10.31,
"volume": 20379283,
"symbol": "WISH",
"date": "2021-08-03T00:00:00+0000"
}
]
},
{
"pagination": {
"count": 6,
},
"data": [
{
"open": 27.3,
"close": 28.33,
"volume": 2360664,
"symbol": "CRSR",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 26.83,
"close": 27.4,
"volume": 4409156,
"symbol": "CRSR",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 26.99,
"close": 27.13,
"volume": 8675462,
"symbol": "CRSR",
"date": "2021-08-03T00:00:00+0000"
}
]
}]
这就是我到目前为止在创建折线图时所做的工作
var priceMargin = {top: 10, right: 30, bottom: 30, left: 60},
priceWidth = 460 - priceMargin.left - priceMargin.right,
priceHeight = 400 - priceMargin.top - priceMargin.bottom;
var priceSvg = d3.selectAll(".company-price")
.data(prices, function(d){
return d.data
})
.append("svg")
.attr("width", priceWidth + priceMargin.left + priceMargin.right)
.attr("height", priceHeight + priceMargin.top + priceMargin.bottom)
.append("g")
.attr("transform", "translate(" + priceMargin.left + "," + priceMargin.top + ")")
我的目标是为数组中的每个对象创建一个折线图,它由单独的“.company-price”中的 Y(收盘价)和 X(日期)轴的值范围组成 div 容器,但不确定如何创建 X 轴和 Y 轴并访问上面传入的数据。下面是我的 HTML 结构和我想要实现的目标的截图
如有任何帮助或建议,我们将不胜感激!
想想您在 d3 中创建的 div 数组。
const div = d3.select("#companies-container");
data.map(symbol=>{
const {data, pagination} = symbol;
const companyContainer = div.append("div").attr("class","company-container");
const companyProfile = companyContainer.append("div").attr("class", "company-profile");
const companyRecommend = companyContainer.append("div").attr("class", "company-container");
const companyPrice = companyContainer.append("div").attr("class","company-price");
const svg = companyPrice.append("svg").width(400).height(200);
// All your code here
const x = scaleLinear().domain(d3.extent(data, d=>d.date)).range([margin.left, width-margin.right]);
// Calculate y, render lines etc.
})
在此处查看 JsFiddle https://jsfiddle.net/9ukd75yn/20/
这是实现此目的的一种方法,假设公司价格 div 已经创建并且与 prices
数组的顺序相同。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<body>
<div id="companies-container">
<div id="company-container">
<div class="company-price"></div>
</div>
<div id="company-container">
<div class="company-price"></div>
</div>
</div>
<script>
// data
const prices = [{
"pagination": {
"count": 6,
},
"data": [
{
"open": 9.67,
"close": 9.98,
"volume": 17876279,
"symbol": "WISH",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 10.3,
"close": 9.61,
"volume": 34099145,
"symbol": "WISH",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 10.36,
"close": 10.31,
"volume": 20379283,
"symbol": "WISH",
"date": "2021-08-03T00:00:00+0000"
}
]
},
{
"pagination": {
"count": 6,
},
"data": [
{
"open": 27.3,
"close": 28.33,
"volume": 2360664,
"symbol": "CRSR",
"date": "2021-08-05T00:00:00+0000"
},
{
"open": 26.83,
"close": 27.4,
"volume": 4409156,
"symbol": "CRSR",
"date": "2021-08-04T00:00:00+0000"
},
{
"open": 26.99,
"close": 27.13,
"volume": 8675462,
"symbol": "CRSR",
"date": "2021-08-03T00:00:00+0000"
}
]
}];
// bind the data to the company-price div
// call the lineChart function for each div
d3.selectAll('.company-price')
.data(prices)
.each(lineChart);
// function to draw line chart
function lineChart({pagination, data}) {
const priceMargin = {top: 10, right: 30, bottom: 30, left: 60};
const priceWidth = 460 - priceMargin.left - priceMargin.right;
const priceHeight = 400 - priceMargin.top - priceMargin.bottom;
// this refers to the company-price div
const svg = d3.select(this)
.append('svg')
.attr("width", priceWidth + priceMargin.left + priceMargin.right)
.attr("height", priceHeight + priceMargin.top + priceMargin.bottom)
.append("g")
.attr("transform", `translate(${priceMargin.left},${priceMargin.top})`);
// scales
const parseDate = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');
const x = d3.scaleTime()
.domain(d3.extent(data, d => parseDate(d.date)))
.range([0, priceWidth]);
const y = d3.scaleLinear()
.domain(d3.extent(data, d => d.close))
.range([priceHeight, 0]);
// line generator
const line = d3.line()
.x(d => x(parseDate(d.date)))
.y(d => y(d.close));
// draw line
svg.append('path')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('d', line(data));
// axes
svg.append('g')
.call(d3.axisLeft(y));
svg.append('g')
.attr('transform', `translate(0,${priceHeight})`)
.call(d3.axisBottom(x));
}
</script>
</body>
</html>