我已经分别实现了平移和夹取,并且效果很好。现在我尝试同时使用夹取和平移,但我发现了一些问题。下面是我的代码:
XAML文件:
<AbsoluteLayout x:Name="PinchZoomContainer">
<controls:NavBar x:Name="NavBar" ShowPrevNext="true" ShowMenu="false" IsModal="true" />
<controls:PanContainer x:Name="PinchToZoomContainer">
<Image x:Name="ImageMain" />
</controls:PanContainer>
</AbsoluteLayout>
缩放/平移手势添加:
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(panGesture);
var pinchGesture = new PinchGestureRecognizer();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinchGesture);
平移方法:
void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Started:
startX = e.TotalX;
startY = e.TotalY;
Content.AnchorX = 0;
Content.AnchorY = 0;
break;
case GestureStatus.Running:
// Translate and ensure we don't pan beyond the wrapped user interface element bounds.
Content.TranslationX = Math.Max(Math.Min(0, x + e.TotalX), -Math.Abs(Content.Width - App.ScreenWidth));
Content.TranslationY = Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs(Content.Height - App.ScreenHeight));
break;
case GestureStatus.Completed:
// Store the translation applied during the pan
x = Content.TranslationX;
y = Content.TranslationY;
break;
}
}
收缩方法:
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started)
{
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
//ImageMain.AnchorX = 0;
//ImageMain.AnchorY = 0;
}
if (e.Status == GestureStatus.Running)
{
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max(1, currentScale);
currentScale = Math.Min(currentScale, 2.5);
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the X pixel coordinate.
double renderedX = Content.X + xOffset;
double deltaX = renderedX / Width;
double deltaWidth = Width / (Content.Width * startScale);
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
// The ScaleOrigin is in relative coordinates to the wrapped user interface element,
// so get the Y pixel coordinate.
double renderedY = Content.Y + yOffset;
double deltaY = renderedY / Height;
double deltaHeight = Height / (Content.Height * startScale);
double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
// Calculate the transformed element pixel coordinates.
double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale);
double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale);
// Apply translation based on the change in origin.
Content.TranslationX = targetX.Clamp(-Content.Width * (currentScale - 1), 0);
Content.TranslationY = targetY.Clamp(-Content.Height * (currentScale - 1), 0);
// Apply scale factor
Content.Scale = currentScale;
}
if (e.Status == GestureStatus.Completed)
{
// Store the translation delta's of the wrapped user interface element.
xOffset = Content.TranslationX;
yOffset = Content.TranslationY;
}
}
如果我关闭其中一个手势,只使用另一个手势,那么这个功能就可以完美地工作。当我添加平移和捏取手势时,问题就出现了。看起来是这样的:
1)2)当你开始平移图像时,比如说,把图像移到Y轴中心和X轴中心,然后你尝试缩放,图像会回到它的初始状态。然后,当你平移时,它会把你移回到你尝试缩放之前的位置(这就是为什么我说平移工作正常)。
从我的调试中我了解到,当你缩放时,它不会考虑你当前所在的位置。所以当你先平移,然后缩放时,它不会缩放你所在的位置,而是图像的起点。然后当你试图从那里平移时,平移方法仍然会记住你所在的位置,它会把你移回到你试图缩放之前的位置。
希望能对此有一些见解。显然,我的捏法有问题。我只是想(显然想不通)我需要在里面加入逻辑,考虑到你目前所处的位置。
4条答案
按热度按时间k10s72fa1#
主要的原因可能是每个人似乎都在复制和使用这段代码(来自dev.xamarin站点),其中包含非常复杂和非常不必要的坐标计算:-)。不必要的原因是我们可以简单地要求视图为我们做繁重的工作,使用
AnchorX
和AnchorY
属性,这些属性正好用于此目的。我们可以双击操作来放大并恢复到原始比例。注意,由于Xamarin无法提供
Tap
事件的坐标值(实际上是一个非常不明智的决定),我们现在只能从中心放大:夹点处理程序同样简单,根本不需要计算任何平移。我们所要做的就是将锚点设置到夹点的起始点,框架会完成其余的工作,缩放将围绕该点进行。注意,我们这里甚至有一个额外的特性,在缩放比例的两端过冲时弹性反弹。
平移处理器更简单。开始时,我们从锚计算起点,平移过程中,我们不断改变锚点。这个锚点是相对于视图区域的,我们可以很容易地将它夹在0和1之间,这样就可以在极端停止平移,而根本不需要任何平移计算。
使用的常量和变量如下:
wwwo4jvm2#
用了一种完全不同的方法来处理这个问题。对于任何有问题的人来说,这是100%有效的。
打开面板已更新
收缩时更新
OnSizeAllocated(您可能不需要其中的大部分,但需要一些。请考虑
ScreenWidth
、ScreenHeight
、yOffset
、xOffset
、currentScale
)配置(C#中的XAML)
2uluyalo3#
我一直在工作的图像查看器与平移和缩放...
我达到了另一个变化。
我会和你分享。
首先,我们需要一个Pan/Zoom类控制器:
在内容页中:
dwbf0jvd4#
对我来说,它的工作原理如下,只是对问题中给出的代码做了一些修改,
Pan代码