我正在尝试使用D3构建折线图(在使用webpack和react-faux-dom构建的React应用中),并显示除折线以外的所有内容。检查开发工具是否存在路径渲染,但它似乎不在屏幕右侧(将路径悬停在path.line 141523000000 x 742.33上方,数据的正确高度正确,宽度似乎是UTC毫秒)。我不确定为什么。
x轴是时间刻度
const x = d3.scaleTime().range([0, width]);
const xAxis = d3.axisBottom(x).ticks(10).tickFormat(d3.timeFormat('%b %d, %Y'));
使用
const parseTime = d3.timeParse('%Y-%m-%d');
两个数据
data.stocks.forEach((d) => {
d.date = parseTime(d.date);
d['GOOG'] = +d['GOOG'];
});
和轴的域
x.domain(d3.extent(data.stocks, (d) => parseTime(d.date)));
如果为某个域设置了x轴,该域的数字比UTC毫秒小得多,那么我可以将线向右移得太远而无法在图表上看到,但是它们都用parseTime()
和我看过的示例仅使用d3.timeFormat()
,所以我没有发现问题。使用一堆控制台日志,看来数据正在正确地通过
const valueline = d3.line()
.x((d) => d.date)
.y((d) => d['GOOG']);
svg.append('path')
.data([data.stocks])
.attr('class', 'line')
.attr('d', valueline);
但是我似乎无法改变任何东西来获得图表上的线条。对此有所了解和/或对D3更有经验的人可以发现发生了什么事?
如果上面的内容并不明显,则完整部分为
import React from 'react';
import ReactFauxDOM from 'react-faux-dom';
import * as d3 from 'd3';
export default class StockChart extends React.Component {
render() {
const div = new ReactFauxDOM.Element('div');
let stockMax;
const rawData = this.props.data; // see below if needed
const smallestDataSetSize = d3.min(rawData.map((stock) => stock.closingValues.length));
const restrictingDataSet = rawData.filter((stock) => stock.closingValues.length === smallestDataSetSize)[0];
const parseTime = d3.timeParse('%Y-%m-%d');
const margin = {top: 20, right: 40, bottom: 70, left: 40}
const width = window.innerWidth - margin.left - margin.right;
const height = window.innerHeight - margin.top - margin.bottom - 75*2;
const x = d3.scaleTime().range([0, width]);
const y = d3.scaleLinear().range([height, 0]);
const xAxis = d3.axisBottom(x).ticks(10).tickFormat(d3.timeFormat('%b %d, %Y'));
const yAxis = d3.axisLeft(y).ticks(5);
// Get prelimiary data to set up chart
stockMaximums = rawData.map((stock) => d3.max(stock.closingValues.map((d) => parseInt(d.price))));
stockMax = d3.max(stockMaximums);
// Fromat data into a JSON format that can be used with D3
const data = { stocks: []};
for (let i = smallestDataSetSize - 1; i > -1; i--) {
const date = restrictingDataSet.closingValues[i].date;
data.stocks.push({
'date': date
});
rawData.map((stock) => {
const stockData = stock.closingValues.filter((stockData) => stockData.date === date);
data.stocks[data.stocks.length - 1][stock.name] = parseFloat(stockData[0].price);
});
}
// Draw the plot
let svg = d3.select(div).append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.bottom + margin.top)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
x.domain(d3.extent(data.stocks, (d) => parseTime(d.date)));
y.domain([0, stockMax*11/10]);
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', '-1rem')
.attr('dy', '-.2rem')
.attr('transform', 'rotate(-65)');
svg.append('g')
.call(yAxis);
// Just trying one line right now while debugging
const valueline = d3.line()
.x((d) => d.date)
.y((d) => d['GOOG']);
data.stocks.forEach((d) => {
d.date = parseTime(d.date);
d['GOOG'] = +d['GOOG'];
});
svg.append('path')
.data([data.stocks])
.attr('class', 'line')
.attr('d', valueline);
return div.toReact();
}
}
和目前唯一的CSS
.line {
fill: none;
stroke: steelblue;
stroke-width: 2;
}
带有示例数据
const rawData = {
closingValues: [
{ date: "2018-09-28", price: "1193.4700" },
{ date: "2018-09-21", price: "1166.0900" },
{ date: "2018-09-14", price: "1172.5300" },
{ date: "2018-09-07", price: "1164.8300" },
{ date: "2018-08-31", price: "1218.1900" },
{ date: "2018-08-24", price: "1220.6500" },
{ date: "2018-08-17", price: "1200.9600" },
{ date: "2018-08-10", price: "1237.6100" },
{ date: "2018-08-03", price: "1223.7100" },
{ date: "2018-07-27", price: "1238.5000" },
{ date: "2018-07-20", price: "1184.9100" },
{ date: "2018-07-13", price: "1188.8200" },
{ date: "2018-07-06", price: "1140.1700" },
{ date: "2018-06-29", price: "1115.6500" },
{ date: "2018-06-22", price: "1155.4800" },
{ date: "2018-06-15", price: "1152.2600" },
{ date: "2018-06-08", price: "1120.8700" },
{ date: "2018-06-01", price: "1119.5000" },
{ date: "2018-05-25", price: "1075.6600" },
{ date: "2018-05-18", price: "1066.3600" },
{ date: "2018-05-11", price: "1098.2600" },
{ date: "2018-05-04", price: "1048.2100" },
{ date: "2018-04-27", price: "1030.0500" },
{ date: "2018-04-20", price: "1072.9600" },
{ date: "2018-04-13", price: "1029.2700" },
{ date: "2018-04-06", price: "1007.0400" },
{ date: "2018-03-29", price: "1031.7900" },
{ date: "2018-03-23", price: "1021.5700" },
{ date: "2018-03-16", price: "1135.7300" },
{ date: "2018-03-09", price: "1160.0400" },
{ date: "2018-03-02", price: "1078.9200" },
{ date: "2018-02-23", price: "1126.7900" },
{ date: "2018-02-16", price: "1094.8000" },
{ date: "2018-02-09", price: "1037.7800" },
{ date: "2018-02-02", price: "1111.9000" },
{ date: "2018-01-26", price: "1175.8400" },
{ date: "2018-01-19", price: "1137.5100" },
{ date: "2018-01-12", price: "1122.2600" },
{ date: "2018-01-05", price: "1102.2300" },
{ date: "2017-12-29", price: "1046.4000" },
{ date: "2017-12-22", price: "1060.1200" },
{ date: "2017-12-15", price: "1064.1900" },
{ date: "2017-12-08", price: "1037.0500" },
{ date: "2017-12-01", price: "1010.1700" },
{ date: "2017-11-24", price: "1040.6100" },
{ date: "2017-11-17", price: "1019.0900" },
{ date: "2017-11-10", price: "1028.0700" },
{ date: "2017-11-03", price: "1032.4800" },
{ date: "2017-10-27", price: "1019.2700" },
{ date: "2017-10-20", price: "988.2000" },
{ date: "2017-10-13", price: "989.6800" },
{ date: "2017-10-06", price: "978.8900" },
{ date: "2017-09-29", price: "959.1100" },
{ date: "2017-09-22", price: "928.5300" },
{ date: "2017-09-15", price: "920.2900" },
{ date: "2017-09-08", price: "926.5000" },
{ date: "2017-09-01", price: "937.3400" },
{ date: "2017-08-25", price: "915.8900" },
{ date: "2017-08-18", price: "910.6700" },
{ date: "2017-08-11", price: "914.3900" },
{ date: "2017-08-04", price: "927.9600" },
{ date: "2017-07-28", price: "941.5300" },
{ date: "2017-07-21", price: "972.9200" },
{ date: "2017-07-14", price: "955.9900" },
{ date: "2017-07-07", price: "918.5900" },
{ date: "2017-06-30", price: "908.7300" },
{ date: "2017-06-23", price: "965.5900" },
{ date: "2017-06-16", price: "939.7800" },
{ date: "2017-06-09", price: "949.8300" },
{ date: "2017-06-02", price: "975.6000" },
{ date: "2017-05-26", price: "971.4700" },
{ date: "2017-05-19", price: "934.0100" },
{ date: "2017-05-12", price: "932.2200" },
{ date: "2017-05-05", price: "927.1300" },
{ date: "2017-04-28", price: "905.9600" },
{ date: "2017-04-21", price: "843.1900" },
{ date: "2017-04-13", price: "823.5600" },
{ date: "2017-04-07", price: "824.6700" },
{ date: "2017-03-31", price: "829.5600" },
{ date: "2017-03-24", price: "814.4300" },
{ date: "2017-03-17", price: "852.1200" },
{ date: "2017-03-10", price: "843.2500" },
{ date: "2017-03-03", price: "829.0800" },
{ date: "2017-02-24", price: "828.6400" },
{ date: "2017-02-17", price: "828.0700" },
{ date: "2017-02-10", price: "813.6700" },
{ date: "2017-02-03", price: "801.4900" },
{ date: "2017-01-27", price: "823.3100" },
{ date: "2017-01-20", price: "805.0200" },
{ date: "2017-01-13", price: "807.8800" },
{ date: "2017-01-06", price: "806.1500" },
{ date: "2016-12-30", price: "771.8200" },
{ date: "2016-12-23", price: "789.9100" },
{ date: "2016-12-16", price: "790.8000" },
{ date: "2016-12-09", price: "789.2900" },
{ date: "2016-12-02", price: "750.5000" },
{ date: "2016-11-25", price: "761.6800" },
{ date: "2016-11-18", price: "760.5400" },
{ date: "2016-11-11", price: "754.0200" },
{ date: "2016-11-04", price: "762.0200" }
],
id: "-LNgk1Gxv0RFmJbiYgnx",
lastUpdated: "2018-09-28",
name: "GOOG"
};
答案 0 :(得分:1)
代码存在的问题是比例尺的使用和数据的解析。
在行的计算中应用x
和y
缩放比例
const valueline = d3.line()
.x((d) => x(d.date))
.y((d) => y(d['GOOG']));
整个代码是(仅内部部分,因为我使用了HTML文件进行调试)
const smallestDataSetSize = d3.min(rawData.map((stock) => stock.closingValues.length));
const restrictingDataSet = rawData.filter((stock) => stock.closingValues.length === smallestDataSetSize)[0];
const parseTime = d3.timeParse('%Y-%m-%d');
let svgWidth = window.innerWidth;
let svgHeight = window.innerHeight - 75*2;
const margin = {top: 20, right: 40, bottom: 70, left: 40}
const width = svgWidth - margin.left - margin.right;
const height = svgHeight - margin.top - margin.bottom;
const x = d3.scaleTime().range([0, width]);
const y = d3.scaleLinear().range([height, 0]);
const xAxis = d3.axisBottom(x).ticks(10).tickFormat(d3.timeFormat('%b %d, %Y'));
const yAxis = d3.axisLeft(y).ticks(5);
// Get prelimiary data to set up chart
var stockMaximums = rawData.map((stock) => d3.max(stock.closingValues.map((d) => parseInt(d.price))));
var stockMax = d3.max(stockMaximums);
// Fromat data into a JSON format that can be used with D3
const data = { stocks: []};
for (let i = smallestDataSetSize - 1; i > -1; i--) {
const date = restrictingDataSet.closingValues[i].date;
data.stocks.push({
'date': date
});
rawData.map((stock) => {
const stockData = stock.closingValues.filter((stockData) => stockData.date === date);
data.stocks[data.stocks.length - 1][stock.name] = parseFloat(stockData[0].price);
});
}
data.stocks.forEach((d) => {
d.date = parseTime(d.date);
d['GOOG'] = +d['GOOG'];
});
// Draw the plot
let svg = d3.select(div).append('svg')
.attr('width', svgWidth)
.attr('height', svgHeight)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
// x.domain(d3.extent(data.stocks, (d) => parseTime(d.date)));
x.domain(d3.extent(data.stocks, (d) => d.date));
y.domain([0, stockMax*11/10]);
svg.append('g')
.attr('class', 'x axis')
.attr('transform', `translate(0, ${height})`)
.call(xAxis)
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', '-1rem')
.attr('dy', '-.2rem')
.attr('transform', 'rotate(-65)');
svg.append('g')
.attr('class', 'y axis')
.call(yAxis);
// Just trying one line right now while debugging
const valueline = d3.line()
.x((d) => x(d.date))
.y((d) => y(d['GOOG']));
svg.append('path')
.attr('class', 'line')
.attr('d', valueline(data.stocks));