我尝试使用动态数据显示创建实时图表,绘制DateTime
与Integer
值。我需要的是使用固定轴值平滑滚动X轴。就像平移一样,即当您从中心拖动绘图时,它会随着鼠标光标顺畅地流动。我想自动有类似的行为。
目前,在更改计时器中的数据源时,轴范围会动态变化,滚动不平滑。是否可以改变这种行为。有任何想法,请帮忙。
我尝试在400毫秒计时器中动态更新日期和整数数据源,从而生成基于数据源的轴范围更改的实时图表。
以下是测试代码:
关于窗口加载
timer = new Timer(400);
ds = new ObservableDataSource<VoltagePoint>();
ds.SetXMapping(x => dateAxis.ConvertToDouble(x.Date));
ds.SetYMapping(y => y.Voltage);
plotter.AddLineGraph(ds, 2, "Sample");
timer.Start();
On Timer tick
Random rnd = new Random();
TestPoint pt = new TestPoint (rnd.Next(1, 500), DateTime.Now);
ds.AppendAsync(plotter.Viewport.Dispatcher, pt);
答案 0 :(得分:2)
我相信你是这样的:
// Your code (unchanged)
timer = new Timer(400);
ds = new ObservableDataSource<VoltagePoint>();
ds.SetXMapping(x => dateAxis.ConvertToDouble(x.Date));
ds.SetYMapping(y => y.Voltage);
plotter.AddLineGraph(ds, 2, "Sample");
timer.Start();
// Make the Viewport not move when items are added.
plotter.Viewport.AutoFitToView = false;
// Put in your initial viewing dimensions
var xMin = dateAxis.ConvertToDouble(DateTime.Now);
var startXMax = dateAxis.ConvertToDouble(DateTime.Now.AddMinutes(1));
var startYMin = -20;
var startYMax = 520;
// Set the initial visible area.
plotter.Visible = new Rect { X = xMin, Width = startXMax - xMin, Y = startYMin, Height = startYMax - startYMin };
// If you wish, you can also restrict where the user can scroll:
plotter.Viewport.Restrictions.Add(new CustomAxisRestriction(xMin));
如果限制是另一种控制用户看到的方式,下面是一个非常基本的例子:
public class CustomAxisRestriction : ViewportRestrictionBase
{
private double xMin;
public CustomAxisRestriction(double xMin)
{
this.xMin = xMin;
}
public override Rect Apply(Rect oldDataRect, Rect newDataRect, Viewport2D viewport)
{
newDataRect.X = Math.Max(newDataRect.X, xMin);
return newDataRect;
}
}
基本上,您在限制中所需要的只是覆盖Apply
方法,并带有上述签名。
在您的情况下,您可能还希望在newDataRect.Y
和newDataRect.Height
上添加限制,如果您希望将其约束在-20&lt; - &gt;中。 520(或者),但是我会把它留给你 - 基本的想法就在上面。
希望这有帮助!如果以上任何内容都没有意义,请告诉我:)。
添加另一个计时器,例如,在初始化时:
animationTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(20) };
animationTimer.Tick += animationTimer_Tick;
animationTimer.Start();
我使用DispatcherTimer
而不是Timer
,因为需要在UI线程上移动ViewPort
。然后就是:
private void animationTimer_Tick(object sender, EventArgs e)
{
var oldRect = plotter.Visible;
oldRect.X = Math.Max(oldRect.X, dateAxis.ConvertToDouble(DateTime.Now.AddMinutes(-0.1)));
plotter.Visible = oldRect;
}
当然,您需要从用户体验的角度仔细思考用户应该如何/是否能够中断此滚动,并重新启用它。但我会把它留给你......!
但我上面给出的所有代码都应该有用(或者至少在本地工作!)如果你有任何问题,请告诉我。
我确实遇到了一些轴在动画过程中表现奇怪的问题,我认为这基本上是轴TicksProvider
的一个小错误,所以如果有必要,你可能需要实现自己的:{{ 1}},dateAxis.TicksProvider = new CustomTicksProvider();
继承自CustomTicksProvider
,但使用Google搜索实现相对简单。