我有一个简单的应用程序,我将UIPinchGestureRecognizer和UIPanGestureRecognizer附加到imageView,以便我可以拖动和缩放它。我已经做到了这一点,因此可以将imageView部分地从屏幕上移开并最小化显示器,但是图像的一小部分75像素仍保留在显示器上,因此可以将图像拖回到它上面。因此,例如,如果我尝试将imageView拖离显示器的右侧部分,它将在图像视图的75个像素剩余时停止,留下足够的空间让我将其拖回。与缩放相同的概念,我创建的边界框架可以防止imageView在显示屏上最小化。
无论如何,我的UIPinchGestureRecognizer委托方法中的边界代码存在这个问题。我正在做边界的方式是我创建一个框架,它是imageViews超级视图的复制品 - 除了它在每侧以及顶部和底部以75像素推动。我检查imageView是否与此框架相交,然后我知道它已到达右侧/左侧或顶部/底部的边界之一。它大部分都适用,但是当我将图像放大到相当大(通常在1000以上1000)时,边界不起作用 - 如果我进行超快速最小化缩放,则imageView被完全推离屏幕所以我不能拖回来。
我只是想知道为什么会这样。是否与图像尺寸过大有关?或者这是我的代码中的缺陷? (我在下面列出)。如果有人可以提供帮助,我们将不胜感激。
- (void)scale:(UIPinchGestureRecognizer *)sender
{
if([sender state] == UIGestureRecognizerStateBegan)
{
lastScale = [sender scale];
}
if ([sender state] == UIGestureRecognizerStateBegan ||
[sender state] == UIGestureRecognizerStateChanged)
{
CGFloat currentScale = [[[sender view].layer valueForKeyPath:@"transform.scale"] floatValue];
CGFloat newScale = 1 - (lastScale - [sender scale]);// * (CropThePhotoViewControllerPinchSpeed);
newScale = MAX(newScale, CropThePhotoViewControllerMinScale / currentScale);
CGFloat scaledWidth = newScale * sender.view.frame.size.width;
CGFloat scaledHeight = newScale * sender.view.frame.size.height;
CGRect translatedRect = CGRectMake(sender.view.frame.origin.x, sender.view.frame.origin.y, scaledWidth, scaledHeight);
CGRect boundaryRect = CGRectMake(sender.view.superview.frame.origin.x + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.origin.y + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.size.width - (CropThePhotoViewControllerBoundaryBuffer * 2), sender.view.superview.frame.size.height - (CropThePhotoViewControllerBoundaryBuffer * 2));
if (!(!CGRectIntersectsRect(boundaryRect,translatedRect) && newScale < 1))
{
CGAffineTransform transform = CGAffineTransformScale([[sender view] transform], newScale, newScale);
[[sender view] setTransform: transform];
lastScale = [sender scale];;
}
}
}
答案 0 :(得分:2)
我注意到我必须检查缩放后的NaN(不是数字)结果,然后单独处理它们。使用isnan()来检查。
答案 1 :(得分:1)
我发现了什么问题。对于这行代码,我错误地设置了x和y值:
CGRect translatedRect = CGRectMake(sender.view.frame.origin.x, sender.view.frame.origin.y, scaledWidth, scaledHeight);
应该是:
CGRect translatedRect = CGRectMake(sender.view.frame.origin.x + (((sender.view.frame.size.width - scaledWidth) / 2)), sender.view.frame.origin.y + (((sender.view.frame.size.height - scaledHeight) / 2)), scaledWidth, scaledHeight);
我没有考虑到当imageview缩小时原点会移动的事实。
我做了这个改变,实际上更新了要改进的方法。现在,如果用户尝试最小化超出边界,而不是仅执行缩放,而是将imageView右移到边框。这是更顺畅,最终更好的imo。经过测试,它运行良好,但如果有人发现任何错误,请告诉我:
- (void)scale:(UIPinchGestureRecognizer *)sender
{
if([sender state] == UIGestureRecognizerStateBegan)
{
previousScale = [sender scale];
}
if ([sender state] == UIGestureRecognizerStateBegan ||
[sender state] == UIGestureRecognizerStateChanged)
{
CGFloat nextScale = 1 - (previousScale - [sender scale]);// * (CropThePhotoViewControllerPinchSpeed);
nextScale = MAX(nextScale, CropThePhotoViewControllerMinScale / [[[sender view].layer valueForKeyPath:@"transform.scale"] floatValue]);
CGFloat scaledWidth = nextScale * sender.view.frame.size.width;
CGFloat scaledHeight = nextScale * sender.view.frame.size.height;
CGFloat currentScale = [sender scale];
CGRect translatedRect = CGRectMake(sender.view.frame.origin.x + (((sender.view.frame.size.width - scaledWidth) / 2)), sender.view.frame.origin.y + (((sender.view.frame.size.height - scaledHeight) / 2)), scaledWidth, scaledHeight);
CGRect boundaryRect = CGRectMake(sender.view.superview.frame.origin.x + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.origin.y + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.size.width - (CropThePhotoViewControllerBoundaryBuffer * 2), sender.view.superview.frame.size.height - (CropThePhotoViewControllerBoundaryBuffer * 2));
if ((!CGRectIntersectsRect(boundaryRect,translatedRect)) && (nextScale < 1))
{
CGFloat leftScaledEdge, rightScaledEdge, topScaledEdge, bottomScaledEdge;
CGFloat leftBoundary, rightBoundary, topBoundary, bottomBoundary;
CGFloat nextXScale, nextYScale;
nextXScale = CGFLOAT_MIN;
nextYScale = CGFLOAT_MIN;
rightScaledEdge = translatedRect.origin.x + translatedRect.size.width;
leftScaledEdge = translatedRect.origin.x;
bottomScaledEdge = translatedRect.origin.y + translatedRect.size.height;
topScaledEdge = translatedRect.origin.y;
leftBoundary = boundaryRect.origin.x;
rightBoundary = boundaryRect.origin.x + boundaryRect.size.width;
topBoundary = boundaryRect.origin.y;
bottomBoundary = boundaryRect.origin.y + boundaryRect.size.height;
if (rightScaledEdge < leftBoundary || leftScaledEdge > rightBoundary)
{
if (rightScaledEdge < leftBoundary)
{
CGFloat adjustedWidth = sender.view.frame.size.width - fabsf((leftBoundary - (sender.view.frame.origin.x + sender.view.frame.size.width)));
nextXScale = (nextScale * (adjustedWidth)) / scaledWidth;
}
else
{
CGFloat adjustedWidth = sender.view.frame.size.width - fabsf((rightBoundary - sender.view.frame.origin.x));
nextXScale = (nextScale * (adjustedWidth)) / scaledWidth;
}
}
if (bottomScaledEdge < topBoundary || topScaledEdge > bottomBoundary)
{
if (bottomScaledEdge < topBoundary)
{
CGFloat adjustedHeight = sender.view.frame.size.height - fabsf((topBoundary - (sender.view.frame.origin.y + sender.view.frame.size.height)));
nextYScale = (nextScale * (adjustedHeight)) / scaledHeight;
}
else
{
CGFloat adjustedHeight = sender.view.frame.size.height - fabsf((bottomBoundary - sender.view.frame.origin.y));
nextYScale = (nextScale * (adjustedHeight)) / scaledHeight;
}
}
if (nextXScale >= nextYScale)
{
nextScale = nextXScale;
}
else
{
nextScale = nextYScale;
}
currentScale = nextScale - 1 + previousScale;
}
CGAffineTransform transform = CGAffineTransformScale([[sender view] transform], nextScale, nextScale);
[[sender view] setTransform: transform];
previousScale = currentScale;
}