6

我的应用程序有一个带有一个子视图的 UIScrollView。子视图是一个扩展的 UIView,它使用 drawLayer 事件中的图层将 PDF 页面打印到自身。

使用内置捏合进行缩放效果很好。setZoomScale 也可以按预期工作。

我一直在努力使用 zoomToRect 函数。我在网上找到了一个示例,它从给定的 CGPoint 生成 CGRect zoomRect 变量。

在 touchesEnded 函数中,如果有双击并且它们一直被缩小,我想放大到我创建的 PDFUIView,就好像它们在他们双击的捏合中心进行捏合一样。

因此,假设我将 UITouch 变量传递给我的函数,如果他们双击则使用 zoomToRect。

我从在苹果网站上找到的以下功能开始:

http://developer.apple.com/iphone/library/documentation/WindowsViews/Conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html

以下是我的 UIScrollView 扩展类的修改版本:

- (void)zoomToCenter:(float)scale withCenter:(CGPoint)center {     

    CGRect zoomRect;
    zoomRect.size.height = self.frame.size.height / scale;
    zoomRect.size.width  = self.frame.size.width  / scale;

    zoomRect.origin.x = center.x - (zoomRect.size.width  / 2.0);
    zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0); 

    //return zoomRect;

    [self zoomToRect:zoomRect animated:YES];

} 

当我这样做时, UIScrollView 似乎使用上方 zoomRect 的右下边缘而不是中心进行缩放。

如果我像这样制作 UIView

UIView *v = [[UIView alloc] initWithFrame:zoomRect]; 
[v setBackgroundColor:[UIView redColor]];
[self addSubview:v];

红色框显示在中心,触摸点已死。

请注意:我是从我的 PC 上写这篇文章的,我记得在我的 Mac 上搞乱了除以二的部分,所以假设这会在中心绘制一个触摸点的矩形。如果 UIView 偏离中心但放大到正确的位置,那就太好了。

但是,当它执行 zoomToRect 时,它似乎使用了放大结果左上角的 zoomRect 的右下角。

另外,我注意到根据我在 UIScrollView 上单击的位置,它会锚定到不同的位置。似乎中间有一个十字架,它以某种方式反映了这些点,就好像中间左边的任何地方都是负面的反映,而中间的任何地方都是正面的反映?

这似乎很复杂,不应该只是缩放到 UIView 能够绘制的矩形吗?

我进行了大量研究来弄清楚如何创建高质量缩放的 PDF,所以我假设使用 CALayer 可能会脱离坐标系?但是对于 UIScrollView 来说,它应该将其视为具有 768x985 尺寸的视图。

这有点高级,请假设创建 zoomRect 的代码都很好。UIScrollView 中的 UIView 中的 CALayer 有一些更深层次的东西......

4

9 回答 9

5

好的另一个答案:

苹果提供的例程对我有用,但您需要让手势识别器将点击点转换为 imageView 坐标 - 而不是滚动条。

Apple 的示例是这样做的,但由于我们的应用程序工作方式不同(我们更改了 UIImageView),因此在 uiscrollview 上设置了gestureRecongnizer - 工作正常,但您需要在 handleDoubleTap 中执行此操作:

这大致基于苹果示例代码“TaptoZoom”,但正如我所说,我们需要将手势识别器连接到滚动视图。

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
    // double tap zooms in
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(handleSingleTap:) object:nil];
    float newScale = [imageScrollView zoomScale] * 1.5;
    // Note we need to get location of the tap in the imageView coords, not the imageScrollView
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:imageView]];
    [imageScrollView zoomToRect:zoomRect animated:YES];
}
于 2011-03-09T13:20:05.233 回答
4
   Declare BOOL isZoom; in .h


     -(void)handleDoubleTap:(UIGestureRecognizer *)recognizer {  
            if(isZoom){
                CGPoint Pointview=[recognizer locationInView:self];
                CGFloat newZoomscal=3.0;

                newZoomscal=MIN(newZoomscal, self.maximumZoomScale);

                CGSize scrollViewSize=self.bounds.size;

                CGFloat w=scrollViewSize.width/newZoomscal;
                CGFloat h=scrollViewSize.height /newZoomscal;
                CGFloat x= Pointview.x-(w/2.0);
                CGFloat y = Pointview.y-(h/2.0);

                CGRect rectTozoom=CGRectMake(x, y, w, h);
                [self zoomToRect:rectTozoom animated:YES]; 

                [self setZoomScale:3.0 animated:YES]; 
                isZoom=NO;
            }
            else{ 
                [self setZoomScale:1.0 animated:YES]; 
                isZoom=YES;
            }
        } 
于 2013-06-12T06:49:51.353 回答
1

就我而言,它是:

zoomRect.origin.x    = center.x / self.zoomScale - (zoomRect.size.width  / 2.0);
zoomRect.origin.y    = center.y / self.zoomScale  - (zoomRect.size.height / 2.0);
于 2011-02-16T10:20:16.770 回答
1

我注意到如果图像以小于 1 的 zoomScale 开始,则您使用的苹果无法正确缩放,因为 zoomRect 原点不正确。我对其进行了编辑以使其正常工作。这是代码:

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {

CGRect zoomRect;

// the zoom rect is in the content view's coordinates. 
//    At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
//    As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [self frame].size.height / scale;
zoomRect.size.width  = [self frame].size.width / scale;


// choose an origin so as to get the right center.
zoomRect.origin.x = (center.x * (2 - self.minimumZoomScale) - (zoomRect.size.width  / 2.0));
zoomRect.origin.y = (center.y * (2 - self.minimumZoomScale) - (zoomRect.size.height / 2.0));

return zoomRect;
}

关键是这部分将中心值乘以(2 - self.minimumZoomScale)。希望这可以帮助。

于 2010-11-23T18:45:14.297 回答
1

扩展 UIScrollView {

func getRectForVisibleView() -> CGRect {
    var visibleRect: CGRect = .zero
    
    visibleRect.origin = self.contentOffset
    visibleRect.size = self.bounds.size

    let theScale = 1.0 / self.zoomScale
    visibleRect.origin.x *= theScale
    visibleRect.origin.y *= theScale
    visibleRect.size.width *= theScale
    visibleRect.size.height *= theScale
    
    return visibleRect
}

func moveToRect(rect: CGRect) {
    let scale = self.bounds.width / rect.width
    self.zoomScale = scale
    self.contentOffset = .init(x: rect.origin.x * scale, y: rect.origin.y * scale)
}

}

于 2021-01-28T20:01:54.207 回答
0

我有类似的东西,这是因为我没有通过将它们除以比例来调整 center.x 和 center.y 值(使用 center.x/scale 和 center.y/scale)。也许我没有正确阅读您的代码。

于 2010-04-30T16:06:07.300 回答
0

我不同意上面的评论之一,即您永远不应该将中心的坐标乘以某个因子。

假设您当前在 100x100 滚动视图中显示整个 400x400 像素的图像或 PDF 文件,并希望允许用户将内容的大小加倍,直到达到 1:1。如果您双击点 (75,75),您希望放大的矩形在新的 200x200 内容视图中具有原点 100,100 和大小 100x100。所以原来的攻丝点 (75,75) 现在是 (150,150) 在新的 200x200 空间中。

现在,在缩放操作 #1 完成后,如果您再次双击新的 100x100 矩形内的 (75,75)(这是较大的 200x200 矩形的右下角),您希望用户看到底部- 右 100x100 正方形的较大图像,现在将放大到 400x400 像素。

为了在较大的 400x400 矩形内计算这个最新的 100x100 矩形的原点,您需要考虑比例和当前内容偏移(因为在最后一次缩放操作之前,我们在 200x200 内容矩形内显示右下角的 100x100 矩形) .

所以最终矩形的x坐标变为:center.x/currentScale - (scrollView.frame.size.width/2) + scrollView.contentOffset.x/currentScale = 75/.5 - 100/2 + 100/.5 = 150 - 50 + 200 = 300。

在这种情况下,作为正方形,y 坐标的计算是相同的。我们确实放大了右下角的 100x100 矩形,在较大的 400x400 内容视图中,它的原点为 300,300。

所以这里是你如何计算缩放矩形的大小和原点:zoomRect.size.height = mScrollView.frame.size.height/scale; zoomRect.size.width = mScrollView.frame.size.width/scale;

zoomRect.origin.x = center.x/currentScale - (mScrollView.frame.size.width/2) + mScrollView.contentOffset.x/currentScale;
zoomRect.origin.y = center.y/currentScale - (mScrollView.frame.size.height/2) + mScrollView.contentOffset.y/currentScale;

希望这是有道理的;如果不画出各种正方形/矩形,就很难以书面形式解释它。

干杯,拉夫·科拉桑特

于 2011-10-14T00:25:03.603 回答
0

我尝试了不同的解决方案,但这看起来是最好的解决方案它真的是直截了当和概念性的吗?

CGRect frame = [[UIScreen mainScreen] applicationFrame];
scrollView.contentInset = UIEdgeInsetsMake(frame.size.height/2,
                 frame.size.width/2,
                 frame.size.height/2,
                 frame.size.width/2); 
于 2011-04-01T15:15:36.850 回答
0

我有同样的行为,这很令人沮丧......馈送到 UIScrollView 的矩形是完美的......但我的观点,无论我做什么涉及以编程方式更改 zoomScale 总是缩放和缩放以坐标 0,0 ,无论如何。

我试过只是改变zoomScale,我试过zoomToRect,我都试过了,我在代码中触摸zoomScale的每一分钟,它都会去坐标0,0。

在缩放操作之后,我还必须向滚动视图中调整大小的图像添加显式 setContentSize,否则我无法在缩放或捏合后滚动。

这是 3.1.3 中的错误还是什么?

于 2010-08-24T05:48:02.120 回答