我正在使用画布元素在 WPF 中绘制程序。我想要实现的是一个带有可拖动端点的滚动条。Adobe 的 After Effects 视频编辑软件中就是这类滚动条的示例。
这种滚动条的基本功能是它能够滚动比它的容器更大的内容,但左右端点都可以拖动以动态改变内容的比例。
我在绘图程序中实现了一个类似的滚动条;用户应该能够拖动入点和出点(画布中的矩形),并且绘图画布应该通过缩放到所需范围来对此做出响应。我需要的信息:
- 总图的宽度(图点的数量)
- 容器的宽度(静态,600px)
- 入点和出点相对于滚动条画布总宽度的百分比
有了这些信息,我创建了一个 MatrixTransform,使用 ScaleAt() 方法缩放容器内的绘图画布,使其与下面滚动条中的入点和出点匹配。为此,我使用了以下代码。resetTransform 每秒调用FPS次以跟上传入的数据,并且 XMAX 和 YMAX 在其他地方更新以反映这一点。
public void resetTransform(Boolean useSlider = false)
{
//Add transformgroup to plot
double yscale = plot.Height / view.YMAX; //YMAX is maximum plot value received
double xscale = plot.Width / view.XMAX; //XMAX is total ammount of plotted points
Matrix m = new Matrix(1, 0, 0, 1, 0, 0);
if (useSlider)
{
double maxVal = zoomBar.ActualWidth - outPoint.Width;
double outP = Canvas.GetLeft(outPoint); //points position relative to the scrollbar
double inP = Canvas.GetLeft(inPoint);
double center = (((outP + inP) / 2) / maxVal) * plot.ActualWidth;
double delta = (outP-inP);
double factor = (maxVal/delta) * xscale;
double mappedinP = (inP / maxVal) * view.XMAX;
double anchorOut = (outP / maxVal) * view.XMAX;
double anchorIn = (inP / maxVal) * view.XMAX;
m.ScaleAt(factor, -yscale,center,0); //scale around the center point,
m.Translate(0, plot.Height); //to compensate the flipped graph, move it back down
}
scale = new ScaleTransform(m.M11, m.M22, 0, 0); //save scale factors in a scaletransform for reference
signals.scaleSignalStrokes(scale); //Scale the plotlines to compensate for canvas scaling
MatrixTransform matrixTrans = new MatrixTransform(m); //Create matrixtransform
plot.RenderTransform = matrixTrans; //Apply to canvas
}
期望:一切都应该正常工作,并且当绘图点的数量随着时间的推移而增长时,绘制的图形会很好地缩放。现实:移动点时图形会缩放,但不具有代表性;此外,添加的情节点越多,整个画布向右移动的越多,我似乎对转换的控制就越少。现在的算法可能是错误的方法来获得我需要的结果,但我花了很多时间思考如何正确地做到这一点。
更新
我已经上传了一个视频,以便更清楚地了解互动。在视频中,您可以清楚地看到画布向右移动。 截屏视频
我应该如何缩放画布(绘图)以适应两个边界?