2012-10-11 74 views
1

我正在使用画布元素在WPF中绘制程序。我想要实现的是一个可拖动端点的滚动条。这些类型的滚动条的例子在Adobe的After Effects视频编辑软件中。通过设置内外点动态缩放WPF中的画布

这样的滚动条的基本功能是,它能够滚动槽的内容是更大然后它的容器,但无论是左,右终点可以拖动动态地改变内容的规模。

我在绘图程序中实现了一个类似的滚动条;用户应该能够拖动进出点(画布中的矩形),并且绘图画布应该通过缩放到所需的范围来响应这一点。 信息我需要这样的:

  • 宽度的总图的(plotpoints量)
  • 宽度容器(静态,600像素)
  • 百分比IN和OUT点的相对于总宽度滚动条画布

Link to current screenshot

有了这个信息我已经创建了一个MatrixTransform,使用ScaleAt()方法吨o缩放容器内的剧情画布,以便它与下面滚动条中的入点和出点匹配。为此我使用了下面的代码。 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 
} 

后市展望:一切都应该工作,当plotpoints量随时间增长绘制图形将很好地扩展。现实:图形在移动点时缩放,但不具有代表性;此外,添加的绘图点越多,整个画布越向右移动,我看起来对变形的控制就越少。现在的算法可能是错误的方法来获得我需要的结果,但我花了相当长的时间思考如何正确地做到这一点。

更新

我已经上传的视频给上的互动更清晰的画面。在视频中,您可以清楚地看到画布向右移动。 Screencapture video

我该如何缩放画布(绘图)以适应两个边界?

+0

可以使用第三方控制? telerik RadTimeBar和RadTimeLine都有这种行为。 – Ewerton

+0

啊,我看到,这些控件完全符合我的需求,但它们是商业工具。我想自己编写解决方案以从我的错误中学习,并将项目放在github上,所以上述工具在这个意义上并不能真正帮助我。除非他们在他们的网站上某处显示了底层代码? – Pepf

回答

0

所以,经过一番努力,我找到了正确的算法来解决这个问题。我会后下面的resetTransform功能的调整版本:

//Reset graph transform 
    public void resetTransform(Boolean useSlider = false) 
    { 
     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 delta = (outP-inP); 
      double factor = (maxVal/delta) * xscale; 

      anchorOut = (outP/maxVal) * view.XMAX; //Define anchorpoint coordinates 
      anchorIn = (inP/maxVal) * view.XMAX; 
      double center = (anchorOut +anchorIn)/2; //Define centerpoint 

      m.Translate(-anchorIn, 0); //Move graph to inpoint 
      m.ScaleAt(factor, -yscale,0,0); //scale around the inpoint, with a factor so that outpoint is plot.Height(=600px) further away 
      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 
    } 

因此而不是围绕中心点缩放,我应该先翻译的图像,然后缩放周围的一个因素画布的起源。这意味着画布的另一面是精确的plot.Height像素(带有一些额外的缩放比例)

一切似乎现在正常工作,但因为我使用自定义控件(draggable矩形在画布中)我注意到这些矩形不要总是开启摩丝事件。

因为正是出于这样的问题的范围,我在this post描述的问题进一步