我正在做一个表面应用,我需要缩放我的场景(缩放),同时用户用手指缩放(即捏)
目前我的工作正常,但问题是我需要放大用户手指之间的中心点。
我有理由,但翻译背后的数学很难掌握。
当我将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的画布,它是我应用变换的画布。
答案 0 :(得分:1)
我必须自己做这件事。基本上,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;
}
}
答案 1 :(得分: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;
}