我目前在WPF中构建波形控制。 我打算建立一个缩放功能。这意味着用户应该有能力看到整个音频文件的每一个样本。众所周知...和audiofile可以有非常非常非常多的样本。所以我不得不画出极其多的线条,这将是开销。WPF线路虚拟化
所以我想到只有当他们被要求时才画线。问题是,我不知道什么是最好的,最干净的方式来做到这一点。你有什么想法,我可以开始建立这样一个功能。我不想让代码看起来像一个油炸的大脑。如果有人开始解决这个问题,我会非常感激。
我目前在WPF中构建波形控制。 我打算建立一个缩放功能。这意味着用户应该有能力看到整个音频文件的每一个样本。众所周知...和audiofile可以有非常非常非常多的样本。所以我不得不画出极其多的线条,这将是开销。WPF线路虚拟化
所以我想到只有当他们被要求时才画线。问题是,我不知道什么是最好的,最干净的方式来做到这一点。你有什么想法,我可以开始建立这样一个功能。我不想让代码看起来像一个油炸的大脑。如果有人开始解决这个问题,我会非常感激。
一种方法可以获得轨道的可见范围,然后绘制属于该区域的线。 This控制可能对您有所帮助。就个人而言,即使它不使用WPF的缩放功能,我也会将样本的坐标保持为只读集合,然后在需要渲染时将它们的组件乘以缩放因子。您将有ScrollViewer
与ScrollableWidth
(假设您的样本水平跨度)等于最后一个样本的乘以x坐标。获得上述效果的一种方法是始终绘制最后一个样本,而不将其连接到最后一个可见样本。最后,您将在您选择的容器中绘制可见线条,并将其用于ScrollViewer的Content
属性。
使用Canvas
和ScrollViewer
添加一个小例子,您可以使用它在滚动/缩放时更新内容。
var scrollViewer = _scrollViewer; //_scrollViewer is our container
var min = scrollViewer.ContentHorizontalOffset; //Calculating visible ranges
var max = min + scrollViewer.ViewportWidth;
int[] samples = { 10, 20, 30, 50, 80, 90, 100, 130 }; //Our original samples
const double zoomFactor = 10.0;
var canvas = new Canvas {HorizontalAlignment = HorizontalAlignment.Left};
foreach (var sampleX in samples)
{
var multipliedX = sampleX*zoomFactor;
if (multipliedX < min || multipliedX > max) continue;
var sampleCircle = new Ellipse {Width = 5, Height = 5, Stroke = Brushes.Black}; //Our Shape for the sample
canvas.Children.Add(sampleCircle);
Canvas.SetLeft(sampleCircle, multipliedX);
}
canvas.Width = samples.Last()*zoomFactor; //To extend the ScrollViewer's scrollable width
scrollViewer.Content = canvas;