gpt4 book ai didi

javascript - 根据 SignalR 输入不断更新 d3 图表中的线条

转载 作者:搜寻专家 更新时间:2023-11-01 04:41:32 26 4
gpt4 key购买 nike

我有一个显示三条线的 d3 图表,其中每条线都有自己的 y 轴。它还具有用于显示时间的 x 轴。所有轴上都有缩放/平移。 enter image description here这适用于显示历史数据,但我还需要一个按钮来开始显示实时数据。

我有一个触发 SignalR 的按钮,它再次为我提供了可以推送到我的数据阵列的新数据。

我的问题是每次用新数据值更新数组时如何更新这三行并在水平方向上移动它们。我试过关注 thisthis指南,但我真正要做的就是在旧线之上重新绘制整条线。 (我现在只想更新其中一个)

在显示我的图表代码之前,我应该提到我的数组每秒更新一次新值(这发生在一个单独的 js 文件中,包含在同一 View 中):

speed.push(entry.Speed);
redraw();

<script>
/* d3 vars */
var graph;
var m = [];
var w;
var h;

/* d3 scales */
var x;
var y1;
var y2;
var y3;

/* d3 axes */
var xAxis;
var yAxisLeft;
var yAxisLeftLeft;
var yAxisRight;

/* d3 lines */
var line1;
var line2;
var line3;

/* d3 zoom */
var zoom;
var zoomLeftLeft;
var zoomRight;

/* Data */
var speed = [];
var depth = [];
var weight = [];
var timestamp = [];

var url = '@Url.Action("DataBlob", "Trend", new {id = Model.Unit.UnitId, runId = Request.Params["runId"]})';

var data = $.getJSON(url, null, function(data) {
var list = JSON.parse(data);
var format = d3.time.format("%Y-%m-%dT%H:%M:%S").parse;
if ($("#IsLiveEnabled").val() != "true") {
list.forEach(function(d) {
speed.push(d.Speed);
depth.push(d.Depth);
weight.push(d.Weight);
var date = format(d.Time);
d.Time = date;
timestamp.push(d.Time);
});
}

$('#processing').hide();

m = [20, 85, 30, 140]; // margins: top, right, bottom, left
w = ($("#trendcontainer").width() - 35) - m[1] - m[3]; // width
h = 600 - m[0] - m[2]; // height

x = d3.time.scale().domain(d3.extent(timestamp, function(d) {
return d;
})).range([0, w]);

y1 = d3.scale.linear().domain([0, d3.max(speed)]).range([h, 0]);
y2 = d3.scale.linear().domain([0, d3.max(depth)]).range([h, 0]);
y3 = d3.scale.linear().domain([0, d3.max(weight)]).range([h, 0]);

line1 = d3.svg.line()
.interpolate("basis")
.x(function(d, i) {
return x(timestamp[i]);
})
.y(function(d) {
return y1(d);
});

line2 = d3.svg.line()
.interpolate("basis")
.x(function(d, i) {
return x(timestamp[i]);
})
.y(function(d) {
return y2(d);
});

line3 = d3.svg.line()
.interpolate("basis")
.x(function(d, i) {
return x(timestamp[i]);
})
.y(function(d) {
return y3(d);
});

zoom = d3.behavior.zoom()
.x(x)
.y(y1)
.scaleExtent([1, 35])
.on("zoom", zoomed);

zoomLeftLeft = d3.behavior.zoom()
.x(x)
.y(y3)
.scaleExtent([1, 35])
.on("zoom", zoomed);

zoomRight = d3.behavior.zoom()
.x(x)
.y(y2)
.scaleExtent([1, 35])
.on("zoom", zoomed);

// Add an SVG element with the desired dimensions and margin.
graph = d3.select(".panel-body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.call(zoom)
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");

graph.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", w)
.attr("height", h);

// create xAxis
xAxis = d3.svg.axis().scale(x).tickSize(-h).tickSubdivide(false);
// Add the x-axis.
graph.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);

// create left yAxis
yAxisLeft = d3.svg.axis().scale(y1).ticks(10).orient("left");
// Add the y-axis to the left
graph.append("svg:g")
.attr("class", "y axis axisLeft")
.attr("transform", "translate(-25,0)")
.call(yAxisLeft)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Speed (m/min)");

// create leftleft yAxis
yAxisLeftLeft = d3.svg.axis().scale(y3).ticks(10).orient("left");
// Add the y-axis to the left
graph.append("svg:g")
.attr("class", "y axis axisLeftLeft")
.attr("transform", "translate(-85,0)")
.call(yAxisLeftLeft)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Weight (kg)");

// create right yAxis
yAxisRight = d3.svg.axis().scale(y2).ticks(10).orient("right");
// Add the y-axis to the right
graph.append("svg:g")
.attr("class", "y axis axisRight")
.attr("transform", "translate(" + (w + 25) + ",0)")
.call(yAxisRight)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -15)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Depth (m)");

graph.append("svg:path").attr("d", line1(speed)).attr("class", "y1").attr("clip-path", "url(#clip)");
graph.append("svg:path").attr("d", line2(depth)).attr("class", "y2").attr("clip-path", "url(#clip)");
graph.append("svg:path").attr("d", line3(weight)).attr("class", "y3").attr("clip-path", "url(#clip)");
});

function redraw() {
graph.append("svg:path")
.attr("d", line1(speed))
.attr("class", "y1")
.attr("clip-path", "url(#clip)");
}

function zoomed() {
zoomRight.scale(zoom.scale()).translate(zoom.translate());
zoomLeftLeft.scale(zoom.scale()).translate(zoom.translate());

graph.select(".x.axis").call(xAxis);
graph.select(".y.axisLeft").call(yAxisLeft);
graph.select(".y.axisLeftLeft").call(yAxisLeftLeft);
graph.select(".y.axisRight").call(yAxisRight);
graph.select(".x.grid")
.call(make_x_axis()
.tickFormat(""));
graph.select(".y.axis")
.call(make_y_axis()
.tickSize(5, 0, 0));
graph.selectAll(".y1")
.attr("d", line1(speed));
graph.selectAll(".y2")
.attr("d", line2(depth));
graph.selectAll(".y3")
.attr("d", line3(weight));
};

var make_x_axis = function() {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(10);
};

var make_y_axis = function() {
return d3.svg.axis()
.scale(y1)
.orient("left")
.ticks(10);
};

</script>

我确实意识到它不正确,但我似乎无法弄清楚如何将新值附加到绘制线的末尾并移动它。

最佳答案

在这里,我制作了一个非常基本的图表,其中包含一个按钮,可以满足您的需求。它有点不稳定,因为缺少一些日期。我希望它能帮到你,它基于 http://bl.ocks.org/mbostock 上的一个简单示例。

相关部分如下:

    //Add new post to data
data.push({
"Date": new Date(new Date().setDate(new Date().getDate() + skip)),
"Close": price
});

//assign the new data to the graph
svg.select(".area")
.datum(data)
.attr("d", area)
.attr("transform", null);

//Make sure the X axis is updated (not updating the Y axis in the example, but same principle)
x.domain(d3.extent(data.map(function (d) {
return d.Date;
})));
svg.select(".x.axis").transition().call(xAxis);

data.shift();

var skip = 0;
var oldPrice = 11;

var data = [{
"Date": "2015-08-20",
"Close": 7
}, {
"Date": "2015-08-23",
"Close": 8
}, {
"Date": "2015-08-24",
"Close": 9
}, {
"Date": "2015-08-25",
"Close": 6
}, {
"Date": "2015-08-26",
"Close": 5
}, {
"Date": "2015-08-27",
"Close": 7
}, {
"Date": "2015-08-30",
"Close": 5
}, {
"Date": "2015-08-31",
"Close": 9
}, {
"Date": "2015-09-01",
"Close": 8
}, {
"Date": "2015-09-02",
"Close": 10
}, {
"Date": "2015-09-03",
"Close": 11
}, {
"Date": "2015-09-07",
"Close": 12
}, {
"Date": "2015-09-08",
"Close": 11
}, {
"Date": "2015-09-09",
"Close": 12
}, {
"Date": "2015-09-10",
"Close": 13
}, {
"Date": "2015-09-13",
"Close": 14
}, {
"Date": "2015-09-14",
"Close": 15
}, {
"Date": "2015-09-15",
"Close": 13
}, {
"Date": "2015-09-16",
"Close": 11
}, {
"Date": "2015-09-17",
"Close": 7
}, {
"Date": "2015-09-20",
"Close": 6
}, {
"Date": "2015-09-21",
"Close": 5
}, {
"Date": "2015-09-22",
"Close": 6
}, {
"Date": "2015-09-23",
"Close": 7
}, {
"Date": "2015-09-24",
"Close": 8
}, {
"Date": "2015-09-27",
"Close": 10
}, {
"Date": "2015-09-28",
"Close": 9
}, {
"Date": "2015-09-29",
"Close": 10
}, {
"Date": "2015-09-30",
"Close": 11
}];


var margin = {
top: 10,
right: 10,
bottom: 100,
left: 40
};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;


var parseDate = d3.time.format("%Y-%m-%d").parse;

var x = d3.time.scale().range([0, width]),

y = d3.scale.linear().range([height, 0]);

var xAxis = d3.svg.axis().scale(x).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");

var area = d3.svg.area()
.interpolate("monotone")
.x(function (d) {
return x(d.Date);
})
.y0(height)
.y1(function (d) {
return y(d.Close);
});


var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);

svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);

var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");


data.forEach(function (d) {
d.Date = parseDate(d.Date);
d.Close = +d.Close;

});

x.domain(d3.extent(data.map(function (d) {
return d.Date;
})));
y.domain([0, 200]);

focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);

focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);

focus.append("g")
.attr("class", "y axis")
.call(yAxis);

function update() {

//Generate a new price
var price = Math.floor(Math.random() * 5) + oldPrice

//Add new post to data
data.push({
"Date": new Date(new Date().setDate(new Date().getDate() + skip)),
"Close": price
});

//assign the new data to the graph
svg.select(".area")
.datum(data)
.attr("d", area)
.attr("transform", null);

//Make sure the X axis is updated (not updating the Y axis in the example, but same principle)
x.domain(d3.extent(data.map(function (d) {
return d.Date;
})));
svg.select(".x.axis").transition().call(xAxis);

data.shift();

skip++;
oldPrice = price;
}


$(document).ready(function () {

$('#update').click(function () {
update();

});

});
svg {
font: 10px sans-serif;
}
.area {
fill: steelblue;
clip-path: url(#clip);
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
</head>
<body>
<input type="button" id="update" value="update">
</body>
</html>

关于javascript - 根据 SignalR 输入不断更新 d3 图表中的线条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23386162/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com