我需要将灰色视图内的红色视图缩放到滚动视图内的给定红色边界(在这种情况下,滚动视图的边界取决于给定的宽度/高度比),同时保持视图可见尺寸不变。他们还应该始终触摸绿色边框。
我尝试通过在此视图上使用缩放变换来实现此目的,以便在放大滚动视图时,我使用公式1 / zoomScale
来缩放该视图,并更改其锚点,以使其保持绿色边框。
问题是在进行所有这些操作后,我不知道如何为红色视图计算目标边界rect,因此我可以使用适当的zoomScale
滚动到它。
Please see full demo project here
编辑
灰色视图可能会缩小滚动视图的边框(请参阅上一张图片),主要是要使绿色矩形包围着红色视图(您可能会认为它们是绿色区域的负插图)在滚动视图边界内,因此我们实际上应该考虑将绿色视图的“开始”和“结束”大小(红色视图应“固定”到该区域)进行计算。
基本方法
- (void)adjustScrollPositionAndZoomToFrame:(CGRect)frame
{
CGFloat viewWidth = frame.size.width;
CGFloat viewHeight = frame.size.height;
CGFloat scrollViewWidth = self.scrollView.frame.size.width;
CGFloat scrollViewHeight = self.scrollView.frame.size.height;
CGSize newSize = [self scaleSize:frame.size toHeight:scrollViewHeight];
if (newSize.width > scrollViewWidth) {
newSize = [self scaleSize:frame.size toWidth:scrollViewWidth];
}
CGFloat scaleFactor = newSize.height == scrollViewHeight
? scrollViewHeight / viewHeight
: scrollViewWidth / viewWidth;
[self scrollRect:frame toCenterInScrollView:self.scrollView animated:NO];
self.scrollView.zoomScale = scaleFactor;
}
缩放
- (void)handleZoom:(CGFloat)zoom
{
NSArray *anchorPoints = @[[NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)],
[NSValue valueWithCGPoint:CGPointMake(0.5, 1.0)],
[NSValue valueWithCGPoint:CGPointMake(0.0, 1.0)],
[NSValue valueWithCGPoint:CGPointMake(1.0, 0.5)],
[NSValue valueWithCGPoint:CGPointMake(0.5, 0.5)],
[NSValue valueWithCGPoint:CGPointMake(0.0, 0.5)],
[NSValue valueWithCGPoint:CGPointMake(1.0, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(0.5, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(0.0, 0.0)]
];
for (UILabel *label in _labels) {
[self setViewAnchorPoint:label value:[anchorPoints[[_labels indexOfObject:label]] CGPointValue]];
label.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1 / zoom, 1 / zoom);
}
}
/**
* @see https://stackoverflow.com/a/9649399/3004003
* @param value See view.layer.anchorPoint
*/
- (void)setViewAnchorPoint:(UIView *)view value:(CGPoint)value
{
CGPoint newPoint = CGPointMake(view.bounds.size.width * value.x,
view.bounds.size.height * value.y);
CGPoint oldPoint = CGPointMake(view.bounds.size.width * view.layer.anchorPoint.x,
view.bounds.size.height * view.layer.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, view.transform);
oldPoint = CGPointApplyAffineTransform(oldPoint, view.transform);
CGPoint position = view.layer.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
view.layer.position = position;
view.layer.anchorPoint = value;
}
缩放前的初始场景:
缩放后我有什么:
缩放后我需要什么:
答案 0 :(得分:1)
我下载了您的项目,发现了以下问题:
初始化zoomingView
时,请设置其帧的原点,以使zoomingView
位于scrollView
的中间。然后缩放scrollView
时,它还会将偏移量缩放到原点,必须正确考虑缩放的zoomingView
的正确位置。
我认为将原点设置为0会更清楚:
self.zoomingView = [[ZoomingView alloc] initWithFrame:CGRectMake(0, 0, kZoomingViewWidth, kZoomingViewHeight)];
缩放zoomingView
后,您必须将其居中。这可以例如完成通过
self.scrollView.zoomScale = scaleFactor;
CGRect svb = self.scrollView.bounds;
CGRect zvf = self.zoomingView.frame;
self.scrollView.bounds = CGRectMake((zvf.size.width - svb.size.width)/2.0, (zvf.size.height - svb.size.height)/2.0, svb.size.width, svb.size.height);
然后,以下功能变得非常简单:
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
[self.zoomingView handleZoom:scrollView.zoomScale];
}
使用这些修改,缩放后的zoomingView
正确居中。
但是,缩放比例仍然错误,因为内部绿色矩形已缩放以填充可用空间。原因是必须考虑另外必须看到2个大小为30的盒子,即用于缩放的可用空间较小。这可以例如完成通过
CGFloat scaleFactor = newSize.height == scrollViewHeight
? (scrollViewHeight - 60.0) / viewHeight
: (scrollViewWidth - 60.0) / viewWidth;
当然,以后必须将常量替换为变量。
通过这些修改,您的代码可以为我正确运行。
另一件事:This excellent post详细讨论了滚动视图。
答案 1 :(得分:0)
如果将anchorPoints更改为值怎么办?
NSArray *anchorPoints = @[[NSValue valueWithCGPoint:CGPointMake(0.0, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(0.5, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(1.0, 0.0)],
[NSValue valueWithCGPoint:CGPointMake(0.0, 0.5)],
[NSValue valueWithCGPoint:CGPointMake(0.5, 0.5)],
[NSValue valueWithCGPoint:CGPointMake(1.0, 0.5)],
[NSValue valueWithCGPoint:CGPointMake(0.0, 1.0)],
[NSValue valueWithCGPoint:CGPointMake(0.5, 1.0)],
[NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)]
];
因此,您可以将视图调整到缩放视图的边缘并获得所需的内容: