【问题标题】:How to calculate translate while zooming in WPF/Surface如何在放大 WPF/Surface 时计算平移
【发布时间】:2010-01-27 03:52:28
【问题描述】:

我正在做一个表面应用程序,我需要在用户用手指缩放(即捏合)时缩放我的场景(缩放)

目前我可以正常工作,但问题是我需要放大用户手指之间的中心点。

我的意思是,但翻译背后的数学很难掌握。

当我将ScaleTransform 应用到我的 Canvas 场景时,它会放大画布的左上角,我需要它来放大我的捏合手势的中心点(同样,我确实有)。

翻译的数学如何使缩放看起来放大手势的中心点?

编辑:

这基本上就是我所拥有的:

void Affine2DManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e)
{
    //apply zoom and translate
    if (e.ScaleDelta != 1)
        ApplyZoom(e);
    else if (e.Delta.Length != 0)
        ApplyTranslation(e);
}

private void ApplyZoom(Affine2DOperationDeltaEventArgs e)
{
    //scale
    var newScale = _zoomTransform.ScaleX * e.ScaleDelta;
    newScale = GetCappedZoomLevel(newScale);

    _zoomTransform.ScaleX = newScale;
    _zoomTransform.ScaleY = newScale;
}

private void ApplyTranslation(Affine2DOperationDeltaEventArgs e)
{
    var xDiff = e.ManipulationOrigin.X - _screenStartPoint.X;
    var yDiff = e.ManipulationOrigin.Y - _screenStartPoint.Y;

    var translateX = xDiff + _startOffset.X;
    var translateY = yDiff + _startOffset.Y;

    //bounds testing to limit translation
    var rect = new Rect(0.0, 0.0, ZoomCanvas.RenderSize.Width, ZoomCanvas.RenderSize.Height);
    Rect bounds = ZoomCanvas.TransformToAncestor(MainViewportCanvas).TransformBounds(rect);

    if (CanTranslateX(translateX, bounds))
        _translateTransform.X = translateX;

    if (CanTranslateY(translateY, bounds))
        _translateTransform.Y = translateY;
}

真的很基本,但它在一定程度上有效......

_zoomTransform 是 ScaleTransform,_translateTransform 是 TranslateTransform

MainViewport 是一个包含 ZoomCanvas 的画布,这是我应用变换的画布。

【问题讨论】:

    标签: wpf math touch pixelsense


    【解决方案1】:

    这是我的实现,最终运行良好

    private void ApplyZoom(Affine2DOperationDeltaEventArgs e)
        {
            //scale
            var newScale = _zoomTransform.ScaleX * e.ScaleDelta;
            newScale = GetCappedZoomLevel(newScale);
            var pinchPoint = e.ManipulationOrigin;
            DoZoom(newScale, _transformGroup.Inverse.Transform(pinchPoint), pinchPoint);
        }
    
        private void DoZoom(double newScale, Point pinchPosition, Point physicalPosition)
        {
            _translateTransform.X = -1 * (pinchPosition.X * newScale - physicalPosition.X);
            _translateTransform.Y = -1 * (pinchPosition.Y * newScale - physicalPosition.Y);
            _zoomTransform.ScaleX = newScale;
            _zoomTransform.ScaleY = newScale;
        }
    

    【讨论】:

      【解决方案2】:

      我必须自己做这件事。基本上,一个可以承载任意内容并允许用户平移和缩放(使用手势)的 Surface 控件。我的操纵处理器Affine2DManipulationDelta 的处理程序如下所示。希望它是不言自明的,可以让你到达你需要的地方。

      private void OnManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e)
      {
          Debug.Assert(_scrollViewer != null);
      
          if (CanScale && _scrollViewer != null && e.ScaleDelta != 1)
          {
              var scrollViewerContent = _scrollViewer.Content as UIElement;
      
              //can't do anything if the content isn't present and isn't a UIElement
              if (scrollViewerContent != null)
              {
                  var newScale = Scale * e.ScaleDelta;
      
                  newScale = Math.Max(MinScale, newScale);
                  newScale = Math.Min(MaxScale, newScale);
      
                  var origin = e.ManipulationOrigin;
                  var pointInContent = _scrollViewer.TranslatePoint(origin, scrollViewerContent);
      
                  var deltaScale = newScale - Scale;
                  //width and height changes across the whole image
                  var deltaWidth = deltaScale * _scrollViewer.ExtentWidth;
                  var deltaHeight = deltaScale * _scrollViewer.ExtentHeight;
                  //width and height changes relative to the point in the scroll viewer's content
                  deltaWidth = (pointInContent.X / _scrollViewer.ExtentWidth) * deltaWidth;
                  deltaHeight = (pointInContent.Y / _scrollViewer.ExtentHeight) * deltaHeight;
      
                  _offset = Vector.Add(_offset, new Vector(deltaWidth, deltaHeight));
                  var centerPoint = new Point(origin.X + deltaWidth, origin.Y + deltaHeight);
                  centerPoint.Offset(_offset.X, _offset.Y);
      
                  Scale = newScale;
      
                  HorizontalOffset = _scrollViewer.HorizontalOffset + deltaWidth;
                  VerticalOffset = _scrollViewer.VerticalOffset + deltaHeight;
              }
          }
          else if (CanPan && e.Delta.Length != 0)
          {
              var newHorizontalOffset = _scrollViewer.HorizontalOffset + (e.Delta.X * -1);
              var newVerticalOffset = _scrollViewer.VerticalOffset + (e.Delta.Y * -1);
              newHorizontalOffset = Math.Max(0, newHorizontalOffset);
              newVerticalOffset = Math.Max(0, newVerticalOffset);
              HorizontalOffset = newHorizontalOffset;
              VerticalOffset = newVerticalOffset;
          }
      }
      

      【讨论】:

      • 只是几个问题,ScaleCanPanCanScale 只是自定义属性吗?还是您扩展了ScrollViewer?使用滚动查看器会比使用 X 和 Y 平移更容易吗?
      猜你喜欢
      • 1970-01-01
      • 2021-03-02
      • 2019-09-09
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 2018-03-31
      • 1970-01-01
      • 2018-11-14
      相关资源
      最近更新 更多