简体   繁体   English

UIPinchGestureRecognizer 中捏合缩放的最大/最小比例 - iPhone iOS

[英]Max/Min Scale of Pinch Zoom in UIPinchGestureRecognizer - iPhone iOS

How would I be able to limit the scale of the UIPinchGestureRecognizer to a min and max level?我如何能够将 UIPinchGestureRecognizer 的比例限制为最小和最大级别? The scale property below seems to be relative to the last known scale (the delta from last state) and I can't figure out how to set a limit to the size/heigh of the object being zoomed.下面的 scale 属性似乎是相对于最后一个已知比例(从最后一个状态开始的增量),我无法弄清楚如何设置被缩放对象的大小/高度的限制。

-(void)scale:(id)sender {

[self.view bringSubviewToFront:[(UIPinchGestureRecognizer*)sender view]];

if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
    lastScale = 1.0;
    return;
}

CGFloat pinchscale = [(UIPinchGestureRecognizer*)sender scale];
CGFloat scale = 1.0 - (lastScale - pinchscale);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform holderTransform = holderView.transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[[(UIPinchGestureRecognizer*)sender view] setTransform:newTransform];

lastScale = [(UIPinchGestureRecognizer*)sender scale];

} }

Here is the solution that I figured out after using Anomie's answer as a starting point.这是我在使用 Anomie 的答案作为起点后想出的解决方案。

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)gestureRecognizer {

    if([gestureRecognizer state] == UIGestureRecognizerStateBegan) {
        // Reset the last scale, necessary if there are multiple objects with different scales
        lastScale = [gestureRecognizer scale];
    }

    if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || 
        [gestureRecognizer state] == UIGestureRecognizerStateChanged) {

        CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:@"transform.scale"] floatValue];

        // Constants to adjust the max/min values of zoom
        const CGFloat kMaxScale = 2.0;
        const CGFloat kMinScale = 1.0;

        CGFloat newScale = 1 -  (lastScale - [gestureRecognizer scale]); 
        newScale = MIN(newScale, kMaxScale / currentScale);   
        newScale = MAX(newScale, kMinScale / currentScale);
        CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
        [gestureRecognizer view].transform = transform;

        lastScale = [gestureRecognizer scale];  // Store the previous scale factor for the next pinch gesture call  
    }
}

There isn't a way to limit the scale on a UIPinchGestureRecognizer .没有办法限制UIPinchGestureRecognizer的比例。 To limit the height in your code, you should be able to do something like this:要限制代码中的高度,您应该能够执行以下操作:

CGFloat scale = 1.0 - (lastScale - pinchscale);
CGRect bounds = [(UIPinchGestureRecognizer*)sender view].bounds;
scale = MIN(scale, maximumHeight / CGRectGetHeight(bounds));
scale = MAX(scale, minimumHeight / CGRectGetHeight(bounds));

To limit width, change 'Height' to 'Width' in the last two lines.要限制宽度,请将最后两行中的“高度”更改为“宽度”。

The problem with most of the other answers is that they are trying to deal with scale as a linear value, when in fact it is non-linear due to the way UIPinchGestureRecognizer calculates its scale property based on the touch distance.大多数其他答案的问题在于,他们试图将比例作为线性值处理,而实际上由于UIPinchGestureRecognizer基于触摸距离计算其比例属性的方式,它是非线性的。 When this isn't taken into account, the user must use more or less pinch distance to 'undo' the scaling applied by a previous pinch gesture.如果不考虑这一点,用户必须使用更多或更少的捏合距离来“撤消”先前捏合手势应用的缩放。

Consider: suppose transform.scale = 1.0 and I place my fingers 6cm apart on the screen, then pinch inwards to 3cm apart - the resulting gestureRecognizer.scale is 0.5 , and 0.5-1.0 is -0.5 , so transform.scale will become 1.0+(-0.5) = 0.5 .考虑:假设transform.scale = 1.0并且我将我的手指在屏幕上相距 6 厘米,然后向内捏合至相距 3 厘米 - 产生的gestureRecognizer.scale0.5 ,而0.5-1.0-0.5 ,因此transform.scale将变为1.0+(-0.5) = 0.5 Now, I lift my fingers, place them back down 3cm apart and pinch outwards to 6cm.现在,我抬起手指,将它们放回相距 3 厘米,然后向外捏合至 6 厘米。 The resulting gestureRecognizer.scale will be 2.0 , and 2.0-1.0 is 1.0 , so transform.scale will become 0.5+1.0 = 1.5 .生成的gestureRecognizer.scale将为2.0 ,而2.0-1.01.0 ,因此transform.scale将变为0.5+1.0 = 1.5 Not what I wanted to happen.不是我想要发生的。

The fix is to calculate the delta pinch scale as a proportion of its previous value.解决方法是将增量收缩比例计算为其先前值的比例。 I place my fingers down 6cm apart, and pinch inwards to 3cm, so gestureRecognizer.scale is 0.5 .我将手指向下分开 6 厘米,向内捏到 3 厘米,所以gestureRecognizer.scale器. gestureRecognizer.scale0.5 0.5/1.0 is 0.5 , so my new transform.scale is 1.0*0.5 = 0.5 . 0.5/1.00.5 ,所以我的新transform.scale1.0*0.5 = 0.5 Next, I place my fingers down 3cm apart, and pinch outwards to 6cm.接下来,我将手指向下分开 3 厘米,然后向外捏合至 6 厘米。 gestureRecognizer.scale is then 2.0 , and 2.0/1.0 is 2.0 , so my new transform.scale is 0.5*2.0 = 1.0 , which is exactly what I wanted to happen. gestureRecognizer.scale2.0 ,而2.0/1.02.0 ,所以我的新transform.scale0.5*2.0 = 1.0 ,这正是我想要发生的。

Here it is in code:这是在代码中:

in -(void)viewDidLoad :-(void)viewDidLoad

self.zoomGestureCurrentZoom = 1.0f;

in -(void)onZoomGesture:(UIPinchGestureRecognizer*)gestureRecognizer :-(void)onZoomGesture:(UIPinchGestureRecognizer*)gestureRecognizer

if ( gestureRecognizer.state == UIGestureRecognizerStateBegan )
{
    self.zoomGestureLastScale = gestureRecognizer.scale;
}
else if ( gestureRecognizer.state == UIGestureRecognizerStateChanged )
{
    // we have to jump through some hoops to clamp the scale in a way that makes the UX intuitive
    float scaleDeltaFactor = gestureRecognizer.scale/self.zoomGestureLastScale;
    float currentZoom = self.zoomGestureCurrentZoom;
    float newZoom = currentZoom * scaleDeltaFactor;
    // clamp
    float kMaxZoom = 4.0f;
    float kMinZoom = 0.5f;
    newZoom = MAX(kMinZoom,MIN(newZoom,kMaxZoom));    
    self.view.transform = CGAffineTransformScale([[gestureRecognizer view] transform], newZoom, newZoom);

    // store for next time
    self.zoomGestureCurrentZoom = newZoom;
    self.zoomGestureLastScale = gestureRecognizer.scale;
}

I took some info gleaned from Paul Solt and Anoime's answers, and added that to an existing category I have made for UIViewController to allow making any UIView draggable, to now make it pinchable using gestures and transforms.我从 Paul Solt 和 Anoime 的答案中收集了一些信息,并将其添加到我为 UIViewController 创建的现有类别中,以允许任何 UIView 可拖动,现在使用手势和变换使其可捏。

Note: this dirties the tag property of the view you are making draggable/pinchable.注意:这会弄脏您正在制作的可拖动/可捏视图的标签属性。 So if you needed the tag for something else, you can consider placing that value in the NSMutableDictionary being used by this technique.因此,如果您需要其他东西的标签,您可以考虑将该值放置在此技术使用的 NSMutableDictionary 中。 That's available as [self dictForView:theView]这可作为[self dictForView:theView]

Implementing in your project:在您的项目中实施:

You can make any subview within the view controllers "view" draggable or pinchable (or both) place a single line of code in your viewDidLoad (for example:)您可以使视图控制器中的任何子视图“查看”可拖动或可捏(或两者)在您的 viewDidLoad 中放置一行代码(例如:)

[self makeView:mySubView draggable:YES pinchable:YES minPinchScale:0.75 maxPinchScale:1.0];

turn it off in viewDidUnload (releases guestures & dictionary):在 viewDidUnload 中关闭它(发布guestures和字典):

[self makeView:mySubView draggable:NO pinchable:NO minPinchScale:1.0 maxPinchScale:1.0];

DragAndPinchScale.h file DragAndPinchScale.h 文件

#import <UIKit/UIKit.h>

@interface UIViewController (DragAndPinchScale)

-(void) makeView:(UIView*)aView 
       draggable:(BOOL)draggable 
       pinchable:(BOOL)pinchable 
   minPinchScale:(CGFloat)minPinchScale
   maxPinchScale:(CGFloat)maxPinchScale;


-(NSMutableDictionary *) dictForView:(UIView *)theView;
-(NSMutableDictionary *) dictForViewGuestures:(UIGestureRecognizer *)guesture;

@end

DragAndPinchScale.m file DragAndPinchScale.m 文件

#import "DragAndPinchScale.h"

@implementation UIViewController (DragAndPinchScale)


-(NSMutableDictionary *) dictForView:(UIView *)theView{
    NSMutableDictionary *dict = (NSMutableDictionary*) (void*) theView.tag;
    if (!dict) {
        dict = [[NSMutableDictionary dictionary ] retain];
        theView.tag = (NSInteger) (void *) dict;
    }

    return dict;

}


-(NSMutableDictionary *) dictForViewGuestures:(UIGestureRecognizer *)guesture {
    return [self dictForView:guesture.view];
}


- (IBAction)fingersDidPinchInPinchableView:(UIPinchGestureRecognizer *)fingers {
    NSMutableDictionary *dict = [self dictForViewGuestures:fingers];
    UIView *viewToZoom = fingers.view;
    CGFloat lastScale;
    if([fingers state] == UIGestureRecognizerStateBegan) {
        // Reset the last scale, necessary if there are multiple objects with different scales
        lastScale = [fingers scale];
    } else {
        lastScale = [[dict objectForKey:@"lastScale"] floatValue];
    }

    if ([fingers state] == UIGestureRecognizerStateBegan || 
        [fingers state] == UIGestureRecognizerStateChanged) {

        CGFloat currentScale = [[[fingers view].layer valueForKeyPath:@"transform.scale"] floatValue];

        // limits to adjust the max/min values of zoom
        CGFloat maxScale = [[dict objectForKey:@"maxScale"] floatValue];
        CGFloat minScale = [[dict objectForKey:@"minScale"] floatValue];

        CGFloat newScale = 1 -  (lastScale - [fingers scale]); 
        newScale = MIN(newScale, maxScale / currentScale);   
        newScale = MAX(newScale, minScale / currentScale);
        CGAffineTransform transform = CGAffineTransformScale([[fingers view] transform], newScale, newScale);
        viewToZoom.transform = transform;

        lastScale = [fingers scale];  // Store the previous scale factor for the next pinch gesture call  
    }

    [dict setObject:[NSNumber numberWithFloat:lastScale] 
             forKey:@"lastScale"];

}

- (void)fingerDidMoveInDraggableView:(UIPanGestureRecognizer *)finger {
    NSMutableDictionary *dict = [self dictForViewGuestures:finger];
    UIView *viewToDrag =  finger.view;
    if (finger.state == UIGestureRecognizerStateBegan) {

        [dict setObject:[NSValue valueWithCGPoint:viewToDrag.frame.origin] 
                 forKey:@"startDragOffset"];

        [dict setObject:[NSValue valueWithCGPoint:[finger locationInView:self.view]] 
                 forKey:@"startDragLocation"];


    }
    else if (finger.state == UIGestureRecognizerStateChanged) {

        NSMutableDictionary *dict = (NSMutableDictionary*) (void*) viewToDrag.tag;

        CGPoint stopLocation = [finger locationInView:self.view];
        CGPoint startDragLocation = [[dict valueForKey:@"startDragLocation"] CGPointValue];
        CGPoint startDragOffset = [[dict valueForKey:@"startDragOffset"] CGPointValue];
        CGFloat dx = stopLocation.x - startDragLocation.x;
        CGFloat dy = stopLocation.y - startDragLocation.y;
        //   CGFloat distance = sqrt(dx*dx + dy*dy );
        CGRect dragFrame = viewToDrag.frame;


        CGSize selfViewSize = self.view.frame.size;
        if (!UIDeviceOrientationIsPortrait(self.interfaceOrientation)) {
            selfViewSize = CGSizeMake(selfViewSize.height,selfViewSize.width);
        }

        selfViewSize.width  -= dragFrame.size.width;
        selfViewSize.height -= dragFrame.size.height;

        dragFrame.origin.x = MIN(selfViewSize.width, MAX(0,startDragOffset.x+dx));
        dragFrame.origin.y = MIN(selfViewSize.height,MAX(0,startDragOffset.y+dy));

        viewToDrag.frame = dragFrame;
    }
    else if (finger.state == UIGestureRecognizerStateEnded) {

        [dict removeObjectForKey:@"startDragLocation"];
        [dict removeObjectForKey:@"startDragOffset"];
    }
}

-(void) makeView:(UIView*)aView 
       draggable:(BOOL)draggable 
       pinchable:(BOOL)pinchable 
   minPinchScale:(CGFloat)minPinchScale
   maxPinchScale:(CGFloat)maxPinchScale{
    NSMutableDictionary *dict = (NSMutableDictionary*) (void*) aView.tag;

    if (!(pinchable || draggable)) {

        if (dict){ 
            [dict release];
            aView.tag = 0;
        }
        return;
    }

    if (dict) {

        UIPanGestureRecognizer *pan =[dict objectForKey:@"UIPanGestureRecognizer"];
        if(pan){
            if ([aView.gestureRecognizers indexOfObject:pan]!=NSNotFound) {
                [aView removeGestureRecognizer:pan];
            }
            [dict removeObjectForKey:@"UIPanGestureRecognizer"];
        }

        UIPinchGestureRecognizer *pinch =[dict objectForKey:@"UIPinchGestureRecognizer"];
        if(pinch){
            if ([aView.gestureRecognizers indexOfObject:pinch]!=NSNotFound) {
                [aView removeGestureRecognizer:pinch];
            }
            [dict removeObjectForKey:@"UIPinchGestureRecognizer"];
        }

        [dict removeObjectForKey:@"startDragLocation"];
        [dict removeObjectForKey:@"startDragOffset"];
        [dict removeObjectForKey:@"lastScale"];
        [dict removeObjectForKey:@"minScale"];
        [dict removeObjectForKey:@"maxScale"];
    }


    if (draggable) {

        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(fingerDidMoveInDraggableView:)];
        pan.minimumNumberOfTouches = 1;  
        pan.maximumNumberOfTouches = 1;  
        [aView addGestureRecognizer:pan];
        [pan release];

        dict = [self dictForViewGuestures:pan];
        [dict setObject:pan forKey:@"UIPanGestureRecognizer"];

    }

    if (pinchable) {


        CGAffineTransform initialTramsform = CGAffineTransformMakeScale(1.0, 1.0);
        aView.transform = initialTramsform;


        UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(fingersDidPinchInPinchableView:)];
        [aView addGestureRecognizer:pinch];
        [pinch release];
        dict = [self dictForViewGuestures:pinch];
        [dict setObject:pinch forKey:@"UIPinchGestureRecognizer"];
        [dict setObject:[NSNumber numberWithFloat:minPinchScale] forKey:@"minScale"];
        [dict setObject:[NSNumber numberWithFloat:maxPinchScale] forKey:@"maxScale"];


    }

}

@end

Thanks, really useful code snippet above clamping to a minimum and maximum scale.谢谢,上面的代码片段非常有用,可以限制到最小和最大比例。

I found that when I flipped the view first using:我发现当我首先使用以下方法翻转视图时:

CGAffineTransformScale(gestureRecognizer.view.transform, -1.0, 1.0); 

it would cause a flicker when scaling the view.缩放视图时会导致闪烁。

Let me know what you think but the solution for me was to update the code sample above, and if the view has been flipped (flag set via property) then invert the scale value:让我知道您的想法,但我的解决方案是更新上面的代码示例,如果视图已翻转(标志通过属性设置),则反转比例值:

if ([gestureRecognizer state] == UIGestureRecognizerStateBegan || [gestureRecognizer     state] == UIGestureRecognizerStateChanged)
{
    CGFloat currentScale = [[[gestureRecognizer view].layer valueForKeyPath:@"transform.scale"] floatValue];

    if(self.isFlipped) // (inverting)
    {
        currentScale *= -1;
    }

    CGFloat newScale = 1 -  (self.lastScale - [gestureRecognizer scale]);

    newScale = MIN(newScale, self.maximumScaleFactor / currentScale);
    newScale = MAX(newScale, self.minimumScaleFactor / currentScale);

    CGAffineTransform transform = CGAffineTransformScale([[gestureRecognizer view] transform], newScale, newScale);
    gestureRecognizer.view.transform = transform;

    self.lastScale = [gestureRecognizer scale];  // Store the previous scale factor for the next pinch gesture call

Method 1方法一

gestureRecognizer.scale start with 1.0 at the beginning of pinch (gestureRecognizer.state == .began) , and gestureRecognizer.scale in later state (.changed or .end) is always based on that, for example, if the view size is view_size at the beginning of pinch (might not be the same with the original size orig_view_size ), gestureRecognizer.scale always starts with 1.0, and if it becomes 2.0 later, it's size will be 2 * view_size , so the scale always based on that when the pinch starts. gestureRecognizer.scale在捏(gestureRecognizer.state == .began)的开头与1.0开始gestureRecognizer.scale在以后的状态(.changed或.END)总是基于,例如,如果视图大小是view_size在开始捏(可能和原来的大小不一orig_view_size ), gestureRecognizer.scale总是从 1.0 开始,如果后面变成 2.0,它的大小将是2 * view_size ,所以比例总是基于捏开始。

And we can get the scale at the beginning of pinch (gestureRecognizer.state == .began) lastScale = self.imageView.frame.width/self.imageView.bounds.size.width , so the scale of the original image now should be lastScale * gestureRecognizer.scale并且我们可以得到捏开始时的比例(gestureRecognizer.state == .began) lastScale = self.imageView.frame.width/self.imageView.bounds.size.width ,所以现在原始图像的比例应该是lastScale * gestureRecognizer.scale

  • lastScale : The scale of last round of Pinch, a round of Pinch is from state.start to state.end, and the scale is based on the original view size. lastScale :上一轮Pinch的比例,一轮Pinch是从state.start到state.end,比例以原视图大小为准。

  • gestureRecognizer.scale : current scale, based on the view size after last round of Pinch. gestureRecognizer.scale : 当前比例,基于上一轮gestureRecognizer.scale后的视图大小。

  • currentScale : current scale, based on the orignial view size. currentScale : 当前比例,基于原始视图大小。

  • newScale : new scale, based on the orignial view size . newScale : 新比例,基于原始视图大小 newScale = lastScale * gestureRecognizer.scale , and you can limit the scale of the view by comparing the limitation with newScale . newScale = lastScale * gestureRecognizer.scale ,您可以通过将限制与newScale进行比较来限制视图的newScale

``` ``

var lastScale:CGFloat = 1.0

@objc func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) {
        var newScale = gestureRecognizer.scale
        if gestureRecognizer.state == .began {
            lastScale = self.imageView.frame.width/self.imageView.bounds.size.width
        }
        newScale = newScale * lastScale

        if newScale < minScale {
            newScale = minScale
        } else if newScale > maxScale {
            newScale = maxScale
        }

        let currentScale = self.imageView.frame.width/self.imageView.bounds.size.width
        self.imageView.transform = CGAffineTransform(scaleX: newScale, y: newScale)
        print("last Scale: \(lastScale), current scale: \(currentScale), new scale: \(newScale), gestureRecognizer.scale: \(gestureRecognizer.scale)")
}

``` ``

Method 2方法二

gestureRecognizer.scale start with 1.0 on each Pinch notification , this require you reset gestureRecognizer.scale = 1 in the code in the end of each notification handler, so now gestureRecognizer.scale is based on the view size of last Pinch notification, NOT based on the view size at the beginning of pinch .在每个 Pinch 通知上gestureRecognizer.scale以 1.0 开始,这需要您在每个通知处理程序末尾的代码中重置gestureRecognizer.scale = 1 ,所以现在gestureRecognizer.scale基于上次Pinch 通知的视图大小,而不是基于pinch 开始时的视图大小 This is the most important difference with method 1. And since we don't rely on the scale of last round, we don't need lastScale anymore.这是与方法1最重要的区别。而且由于我们不依赖上一轮的规模,我们不再需要lastScale

  • currentScale : current scale, based on the orignial view size. currentScale : 当前比例,基于原始视图大小。

  • gestureRecognizer.scale : new scale, based on the view size of last Pinch (not the last round) , the scale value based on the orignial view size will be currentScale * gestureRecognizer.scale gestureRecognizer.scale : 新比例尺,基于上次gestureRecognizer.scale (不是最后一轮)视图尺寸,基于原始视图尺寸的比例尺值为currentScale * gestureRecognizer.scale

And we use transform.scaledBy now, which use the scale based on view size of last Pinch (not the last round) .我们现在使用transform.scaledBy ,它使用基于最后一个捏(不是最后一轮)的视图大小的比例。

``` ``

@objc func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) {
        let currentScale = self.imageView.frame.width/self.imageView.bounds.size.width
        var newScale = gestureRecognizer.scale
        if currentScale * gestureRecognizer.scale < minScale {
            newScale = minScale / currentScale
        } else if currentScale * gestureRecognizer.scale > maxScale {
            newScale = maxScale / currentScale
        }
        self.imageView.transform = self.imageView.transform.scaledBy(x: newScale, y: newScale)

        print("current scale: \(currentScale), new scale: \(newScale)")

        gestureRecognizer.scale = 1
}

``` ``

Other approaches mentioned here did not work for me, but taking a couple things from previous answers and (in my opinion) simplifying things, I've got this to work for me.这里提到的其他方法对我不起作用,但是从以前的答案中提取一些东西并且(在我看来)简化了事情,我已经得到了这个对我有用。 effectiveScale is an ivar set to 1.0 in viewDidLoad . effectiveScale是在伊娃设定为1.0 viewDidLoad

-(void)zoomScale:(UIPinchGestureRecognizer *)recognizer
{
    if([recognizer state] == UIGestureRecognizerStateEnded) {
        // Reset last scale
        lastScale = 1.0;
        return;
    }

    if ([recognizer state] == UIGestureRecognizerStateBegan ||
    [recognizer state] == UIGestureRecognizerStateChanged) {

        CGFloat pinchscale = [recognizer scale];
        CGFloat scaleDiff = pinchscale - lastScale;

        if (scaleDiff < 0)
            scaleDiff *= 2; // speed up zoom-out
        else
            scaleDiff *= 0.7; // slow down zoom-in

        effectiveScale += scaleDiff;
        // Limit scale between 1 and 2
        effectiveScale = effectiveScale < 1 ? 1 : effectiveScale;
        effectiveScale = effectiveScale > 2 ? 2 : effectiveScale;

        // Handle transform in separate method using new effectiveScale    
        [self makeAndApplyAffineTransform];
        lastScale = pinchscale;
    }
}
- (void)handlePinch:(UIPinchGestureRecognizer *)recognizer{

    //recognizer.scale=1;

    CGFloat pinchScale = recognizer.scale;
    pinchScale = round(pinchScale * 1000) / 1000.0;
    NSLog(@"%lf",pinchScale);

if (pinchScale < 1)

 {

 currentLabel.font = [UIFont fontWithName:currentLabel.font.fontName size:

(currentLabel.font.pointSize - pinchScale)];

   recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);

 [currentLabel sizeToFit];

  recognizer.scale=1;
    }
  else
    {
        currentLabel.font = [UIFont fontWithName:currentLabel.font.fontName size:(currentLabel.font.pointSize + pinchScale)];

         recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);

         [currentLabel sizeToFit];

        recognizer.scale=1;
    }
    //currentLabel.adjustsFontSizeToFitWidth = YES;

   // [currentLabel sizeToFit];
    NSLog(@"Font :%@",label.font);
}
- (void)pinchToZoom:(UIPinchGestureRecognizer*)gesture
{
    switch (gesture.state)
    {
        case UIGestureRecognizerStateBegan:
        {
            lastScale = gesture.scale;
        }break;
        case UIGestureRecognizerStateChanged:
        {   
            const CGFloat zoomSensitivity = 5;
            const CGFloat zoomMin = 1;
            const CGFloat zoomMax = 16;

            CGFloat objectScale = gesture.view.contentScaleFactor;
            CGFloat zoomDiff = lastScale - gesture.scale;
            CGFloat zoomDirty = objectScale - zoomDiff * zoomSensivity;
            CGFloat zoomTo = fmaxf(zoomMin, fminf(zoomDirty, zoomMax));

            // step round if needed (neutralize elusive changes)
            zoomTo = (NSInteger)(zoomTo * 10) * 0.1;

            if ( objectScale != zoomTo )
                gesture.view.contentScaleFactor = zoomTo;

            lastScale = gesture.scale;
        }break;
        default:
            break;
    }
}

I took @Paul Solt solution - that is great btw, and adapted it to Swift, for those interested我采用了@Paul Solt 解决方案 - 顺便说一句,这很棒,并将其改编为 Swift,对于那些感兴趣的人

@objc func pinchUpdated(recognizer: UIPinchGestureRecognizer) {
        
        if recognizer.state == .began {
            // Reset the last scale, necessary if there are multiple objects with different scales
            lastScale = recognizer.scale
        }

        if recognizer.state == .began || recognizer.state == .changed {

            let currentScale = recognizer.view!.layer.value(forKeyPath: "transform.scale") as! CGFloat

            // Constants to adjust the max/min values of zoom
            let maxScale: CGFloat = 4.0
            let ninScale: CGFloat = 0.9

            var newScale: CGFloat = 1 -  (lastScale - recognizer.scale)
            newScale = min(newScale, maxScale / currentScale)
            newScale = max(newScale, ninScale / currentScale)
            recognizer.view!.transform = recognizer.view!.transform.scaledBy(x: newScale, y: newScale)

            lastScale = recognizer.scale // Store the previous scale factor for the next pinch gesture call
        }
    }

Can you use a scroll view instead?你可以使用滚动视图吗? Then you could use scrollView.minimumZoomScale and scrollView.maximumZoomScale然后你可以使用 scrollView.minimumZoomScale 和 scrollView.maximumZoomScale

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

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