новичок в d3 здесь развлекается, но немного застрял. Я пытаюсь создать простой график, на котором будет построена линия для некоторых необработанных ценовых данных в формате (х - дата, у - значение) и средней линии. У меня есть код, работающий так, что я могу создать строку в svg для набора статических данных.
Теперь я пытаюсь обновить набор данных новым потоком данных, и я хочу, чтобысуществующая линия должна быть расширена, так как я хочу построить серию данных, поэтому там тоже нужны старые данные.
Может кто-нибудь помочь мне найти способ сделать это? Возможно ли это без удаления старой линии и повторного рисования? Т.е. я хочу это расширить. Это может быть достигнуто с помощью ввода выходного шаблона обновления? Многие примеры, которые я видел для этого шаблона, всегда добавляют / удаляют новые фигуры, а не соединяют / расширяют, если это имеет смысл.
Я создал простую линейную диаграмму d3, которая отображает линию для статических данных, ноКогда я использую setInterval, чтобы пропинговать некоторые новые данные, а не расширять линию, он добавляет новые.
В конечном итоге на диаграмме будет несколько строк, которые все будут нуждаться в обновлении в зависимости от данных, передаваемых через
<script>
var data_set = [
{ 'Date': '2009-03-23', 'Raw': 25, 'Raw2': 25, 'Asset': 'A' },
{ 'Date': '2009-03-24', 'Raw': 28, 'Raw2': 25.4, 'Asset': 'A' },
{ 'Date': '2009-03-25', 'Raw': 26, 'Raw2': 25.37, 'Asset': 'A' },
{ 'Date': '2009-03-26', 'Raw': 22, 'Raw2': 25.03, 'Asset': 'A' },
{ 'Date': '2009-03-27', 'Raw': 19, 'Raw2': 24.42, 'Asset': 'A' },
{ 'Date': '2009-03-28', 'Raw': 23, 'Raw2': 24.28, 'Asset': 'A' }]
// All of these vars have nothing to do with data yet - it's all setup code
var margin = { top: 30, right: 50, bottom: 30, left: 50 };
var svgWidth = 1200;
var svgHeight = 1000;
var graphWidth = svgWidth - margin.left - margin.right;
var graphHeight = svgHeight - margin.top - margin.bottom;
// var parseDate = d3.timeParse("%d/%m/%Y");
var parseDate = d3.timeParse("%Y-%m-%d");
var x = d3.scaleTime().range([0, graphWidth]);
var y = d3.scaleLinear().range([graphHeight, 0]);
var z = d3.scaleOrdinal(d3.schemeCategory10); // for colours
var xAxis = d3.axisBottom().scale(x).ticks(10);
var yAxis = d3.axisLeft().scale(y).ticks(10);
// Need to create the lines manually for each bit of data
var line1 = d3.line()
.x(function (d) { return x(d.Date); })
.y(function (d) { return y(d.Raw); });
var line2 = d3.line()
.x(function (d) { return x(d.Date); })
.y(function (d) { return y(d.Raw2); });
// Creates the SVG area within the div on the dom
// Just doing this once
var svg = d3.select("#graphDiv")
.append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")")
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}));
// Add the X Axis
svg.append("g").attr("class", "x axis")
.attr("transform", "translate(0," + graphHeight + ")")
.call(xAxis);
// Text label for x axis
svg.append("text")
.style("text-anchor", "middle")
.text("timeseries dates")
.attr("transform", "translate(" + (graphWidth / 2) + " ," + (graphHeight + margin.top) + ")");
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - (graphHeight / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("price points");
function drawGraph(data_set) {
// Pass in the data here
data_set.forEach(function (d) {
d.Date = parseDate(d.Date);
// + converts the strings to numbers from dataset
d.Raw = +d.Raw;
d.EWMA = +d.Raw2;
});
// Domains here represent the complete set of valaues e.g all dates
// These are set based on loaded data
x.domain(d3.extent(data_set, function (d) { return d.Date; }));
y.domain([d3.min(data_set, function (d) { return Math.min(d.Raw, d.Raw2) }),
d3.max(data_set, function (d) { return Math.max(d.Raw, d.Raw2) })]
);
var lines = svg.selectAll("path").data(data_set)
lines.enter().append("path")
.attr("class", "dataLine1")
.style("stroke", "pink")
.style("fill", "none").attr("d", line1(data_set))
lines.enter().append("path")
.attr("class", "dataLine2")
.style("stroke", "#21e0f4").attr("d",line2(data_set));
// // Remove any existing ones
lines.exit().remove()
}
// display initial chart
window.onload = drawGraph(data_set)
// Push new data every 5 seconds for a specific date
var h = setInterval(function () {
data_set.push({ 'Date': '2009-03-29', 'Raw': Math.floor(Math.random() * 50), 'Raw2': Math.floor(Math.random() * 25), 'Asset': 'A' }
,{ 'Date': '2009-03-30', 'Raw': Math.floor(Math.random() * 50), 'Raw2': Math.floor(Math.random() * 25), 'Asset': 'A' },
{ 'Date': '2009-03-31', 'Raw': Math.floor(Math.random() * 50), 'Raw2': Math.floor(Math.random() * 25), 'Asset': 'A' },
{ 'Date': '2009-04-01', 'Raw': Math.floor(Math.random() * 50), 'Raw2': Math.floor(Math.random() * 25), 'Asset': 'A' },
{ 'Date': '2009-04-02', 'Raw': Math.floor(Math.random() * 50), 'Raw2': Math.floor(Math.random() * 25), 'Asset': 'A' },
{ 'Date': '2009-04-03', 'Raw': Math.floor(Math.random() * 50), 'Raw2': Math.floor(Math.random() * 25), 'Asset': 'A' }); console.log('pushing');
drawGraph(data_set);
clearInterval(h); //doing this so that it doesnt spam - if i uncomment this, it will keep spamming new lines
}, 5000);
</script>
Я ожидаю, что будет две строки, одна для необработанного значения и однадля значения raw2. Через 5 секунд я добавляю новые данные и ожидаю, что обе строки будут расширены
В настоящее время происходит две новые линии для новых данных (необработанное значение и необработанное значение2), тогда как я хотел бы, чтобы существующие были расширены.