简体   繁体   English

iPhone UIImageView捏缩放

[英]iPhone UIImageView pinch zoom

I have been trying to implement pinch zoom/in-out for PhotoView (a UIImageView instance) using CGAffinTransformScale (planing to use rotation so can not count on frames for the zoom and will add subviews so UIScrollView would be more complicated, I think). 我一直在尝试使用CGAffinTransformScale实现PhotoView(一个UIImageView实例)的缩放缩放/输入输出(计划使用旋转因此不能指望用于缩放的帧,并且会添加子视图,因此UIScrollView会更复杂,我认为)。 Anyhow, the concept was easy enough to grasp and the code came together very quickly...Since then I have been trying to solve the same two (related?!) problems, using three different approaches, and have not be able to do so: 1- My code somehow loses track of the touch count in the middle of the zoom, from count = 2 to count = 1 and back on the iPhone, but not the simulator. 无论如何,这个概念很容易掌握并且代码很快就汇集在一起​​......从那以后我一直试图使用三种不同的方法来解决相同的两个(相关的?!)问题,并且无法做到这一点:1-我的代码以某种方式失去了在缩放过程中触摸计数的跟踪,从count = 2到count = 1并返回iPhone,但不是模拟器。 2- The touch points one and two keep jumping back and forth a few pixels on every move, causing the image to shrink and enlarge successively and rapidly, even though overall the effect is one of zooming out or zooming in as the user intended (both iPhone and simulator). 2-触摸点1和2在每次移动时保持来回跳跃几个像素,导致图像连续快速地缩小和放大,即使整体效果是用户想要的缩小或放大(两者都是iPhone和模拟器)。

here's the code: 这是代码:

#import "PhotoView.h"


@implementation PhotoView;
@synthesize originalCenter, distance, zooming;
- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
    // Initialization code
        self.userInteractionEnabled = YES;
        self.multipleTouchEnabled = YES;
        zooming = NO;
    }
    return self;
}

float distanceBetweenTwoPoints(CGPoint point1, CGPoint point2)
{
 NSLog(@"point1 x: %5.2f point 2 x: %5.2f ---- point 1 y: %5.2f  point 2 y:    %5.2f",point1.x,point2.x,point1.y,point2.y);
    return (sqrt(pow(point1.x -point2.x,2) + pow(point1.y - point2.y,2)));
}
-(void) touchesBegan: (NSSet *) touches withEvent:(UIEvent *) event {

    if ([touches count] > 1) {

      NSLog(@"^^^^^^^^^^^^^^^Tocuhes began with double touch!");

      distance = distanceBetweenTwoPoints([[[touches allObjects] objectAtIndex:0] locationInView:self], 
        [[[touches allObjects] objectAtIndex:1] locationInView:self]);
      zooming = YES;
    }
    else {
       zooming = NO;
       origianlCenter = [[[touches allObjects] objectAtIndex:0] locationInView:self];
       NSLog(@">>>>>>>>>>>>Touches began with single touch");
    }
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    if (zooming) NSLog(@"!!!!!!!!!end zoom!!!!!!!");

    zooming = NO;
    if ([[touches anyObject] tapCount] == 2) {
        UITouch *thisTouch = [touches anyObject];
        CGPoint thisPoint = [thisTouch locationInView:self];
    }
}

- (void) touchesMoved: (NSSet *) touches withEvent:(UIEvent *) event {
    if ([touches count] > 1 && zooming) { // ignore if user added a second finger touch
        float distanceNew = distanceBetweenTwoPoints([[[touches allObjects] objectAtIndex:0]     locationInView:self], 
                 [[[touches allObjects] objectAtIndex:1] locationInView:self]);  
        if (distance <= 0.f) {    // should never be true - but it is sometimes!!!
           distance = distanceNew;
        }  
        float delta = 1.0f + ((distanceNew-distance)/distance);
        self.transform = CGAffineTransformScale(self.transform, delta, delta);
        distance = distanceNew;
    }
    else {
       if (zooming) {
          NSLog(@"*************shouldn't be here********* %d",[touches count]);
          return;
       }
       CGPoint thisPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self];
       self.transform = CGAffineTransformTranslate(self.transform, thisPoint.x-originalCenter.x, thisPoint.y-originalCenter.y);

    }
}
- (void)dealloc {
    [super dealloc];
}
@end

The log sample: 日志样本:

^^^^^^^^^^^^^^^Tocuhes began with double touch!
point1 x: 87.33 point 2 x: 235.63 ---- point 1 y: 322.30  point 2 y: 117.09
point1 x: 90.76 point 2 x: 232.02 ---- point 1 y: 318.29  point 2 y: 123.51
point1 x: 86.22 point 2 x: 236.71 ---- point 1 y: 323.30  point 2 y: 117.42
point1 x: 89.51 point 2 x: 232.38 ---- point 1 y: 319.47  point 2 y: 123.47
point1 x: 84.97 point 2 x: 237.02 ---- point 1 y: 324.48  point 2 y: 116.56
*************shouldn't be here********* 1
point1 x: 88.49 point 2 x: 232.52 ---- point 1 y: 321.27  point 2 y: 122.91
*************shouldn't be here********* 1
point1 x: 83.95 point 2 x: 237.11 ---- point 1 y: 327.21  point 2 y: 116.96
!!!!!!!!!end zoom!!!!!!!

I am beginning to suspect that I am losing track of the touch points because of CGAffinTransformScale; 我开始怀疑由于CGAffinTransformScale我正在失去对触摸点的跟踪; however, I have not found anything online to suggest this to be an issue. 但是,我没有在网上找到任何建议这是一个问题。 Any clues (including 'read the documentation on xyz') would be appreciated! 任何线索(包括'阅读xyz上的文档')将不胜感激!

Thanks in advance. 提前致谢。

An answer from the left-field perhaps, but an alternative might be to place the UIImageView inside a UIScrollView, define a viewForZoomingInScrollView: method on your scroll view delegate, and set the maximumZoomScale / minimumZoomScale properties and you'll have your pinch zooming without needing to implement the calculations to set the transform yourself? 或许来自左侧字段的答案,但另一种方法可能是将UIImageView放在UIScrollView中,在滚动视图委托上定义一个viewForZoomingInScrollView:方法,并设置maximumZoomScale / minimumZoomScale属性,你可以在不需要的情况下进行缩放缩放实现计算自己设置变换? I've just done this on a recent project and it worked well. 我刚刚在最近的一个项目上完成了这项工作并且效果很好。

Generally speaking, whenever you implement a continuous UI behavior, you need to measure it against something that does not change. 一般来说,每当您实现连续的UI行为时,您需要针对不会发生变化的事情进行衡量。

So if your touches cause the View transformation to change, you should measure the touches against something that does not change - your parent view for instance. 因此,如果您的触摸导致视图转换发生变化,您应该针对不会发生变化的事物测量触摸 - 例如您的父视图。 So, instead of calling : 所以,而不是呼吁:

[touch locationInView:self]

you should use 你应该使用

[touch locationInView:[self superview]]

I am not sure if this will fix your problem, but it will eliminate one possible cause of your troubles. 我不确定这是否能解决你的问题,但它会消除你的麻烦的一个可能原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM