[英]Passing Data to D3.js with Django Backend
I want to build a line chart following the code here .我想按照这里的代码构建一个折线图。 I've made slight change to the data being passed with contains epoch time and a closing price.
我对包含纪元时间和收盘价的数据进行了轻微更改。 Following is the code
以下是代码
{% load static %}
<html>
<script src="https://d3js.org/d3.v4.js"></script>
<body>
<h1> Hello! </h1>
<div id="my_dataviz"></div>
</body>
<script>
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.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 + ")");
//Read the data
var d = {
"Date":{
"0":1641168000000,
"1":1641254400000,
"2":1641340800000
},
"Close":{
"0":182.01,
"1":179.7,
"2":174.92
}
};
// When reading the csv, I must format variables:
d3.json(d,
function(d){
return { date : d3.timeParse("%s")(d.Date), value : d.Close }
},
// Now I can use this dataset:
function(data) {
// Add X axis --> it is a date format
var x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.value; })])
.range([ height, 0 ]);
svg.append("g")
.call(d3.axisLeft(y));
// Add the line
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.value) })
)
})
</script>
</html>
I am unable to generate the graph.我无法生成图表。 I've attached the console screenshot below.
我在下面附上了控制台屏幕截图。
There seems to be an error passing data as seen in html file below传递数据似乎有错误,如下面的 html 文件所示
I can't figure out how to pass the data, what should be the correct way to do it?我不知道如何传递数据,正确的方法应该是什么?
Edit编辑
Applied suggested changes as follows应用建议的更改如下
{% load static %}
<html>
<script src="https://d3js.org/d3.v6.js"></script>
<body>
<h1> Hello! </h1>
<div id="my_dataviz"></div>
<!-- <canvas id="chart" width="100" height="100"></canvas> -->
<!-- <script src={% static "js\linechart.js" %}></script>
<script>
var data = {{ AAPL|safe }};
var chart = LineChart(data, {
x: d => d.date,
y: d => d.close,
yLabel: "↑ Daily close ($)",
width: 400,
height: 400,
color: "steelblue"
});
</script> -->
</body>
<script>
// set the dimensions and margins of the graph
const margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
const svg = d3.select("#my_dataviz")
.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})`);
var d = [
{
"Date": 1641168000000,
"Close": 182.01
},
{
"Date": 1641254400000,
"Close": 179.7
},
{
"Date": 1641168000000,
"Close": 174.92
},
];
d3.json(d,
// When reading the csv, I must format variables:
function(d){
return { date : d3.timeParse("%s")(d.Date), value : d.Close }
}).then(
// Now I can use this dataset:
function(data) {
// Add X axis --> it is a date format
const x = d3.scaleTime()
.domain(d3.extent(data, function(d) { return d.date; }))
.range([ 0, width ]);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));
// Add Y axis
const y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.value; })])
.range([ height, 0 ]);
svg.append("g")
.call(d3.axisLeft(y));
// Add the line
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(function(d) { return x(d.date) })
.y(function(d) { return y(d.value) })
)
})
</script>
</html>
I think there's two things happeningg here:我认为这里发生了两件事:
d3.json(data, parsingFunction)
, d3 is expecting the data entry to be an array of elements, where each element contains all the information for that entry in your datum.d3.json(data, parsingFunction)
时,d3 期望数据条目是一个元素数组,其中每个元素包含数据中该条目的所有信息。 What the parsingFunction does here, is recievee each element in the array and you have to write the logic of how to treat your data (in your case, parse the epoch and keep the close price as it was). Therefore, what you should do is change the way your data is being sent so that it's an array where each entry is an object containing thee corresponding time and close price, ie:因此,您应该做的是更改数据的发送方式,使其成为一个数组,其中每个条目都是一个包含相应时间和收盘价的对象,即:
var d = [
{
"Date": 1641168000000,
"Close": 182.01
},
{
"Date": 1641254400000,
"Close": 179.7
},
{
"Date": 1641168000000,
"Close": 174.92
},
];
d3.json
return a promise .d3.json
return a promise 。 Which means you have to wait for it to arrive.var data = await d3.json(.., ..)
and then using data to do whatever you want.var data = await d3.json(.., ..)
来做到这一点,然后使用 data 来做任何你想做的事情。 OR, specify a callback function (which is what you were trying to do, I believe)..then(callback)
statement..then(callback)
语句指定要在 promise 解决后调用该函数。 And by doing that, you can correctly parse the data with the code you sent above:通过这样做,您可以使用上面发送的代码正确解析数据:
d3.json(d, function(d){
return { date : d3.timeParse("%s")(d.Date), value : d.Close }
}
).then(function(data){
// Use the data
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.