gpt4 book ai didi

objective-c - 使用 UIPinchGestureRecognizer 改变圆的大小

转载 作者:行者123 更新时间:2023-11-28 22:45:28 25 4
gpt4 key购买 nike

我在屏幕中央画了一个简单的圆:

int radius = 100;

- (void)addCircle {
self.circle = [CAShapeLayer layer];
self.circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius)
cornerRadius:radius].CGPath;
self.circle.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius,
CGRectGetMidY(self.view.frame)-radius);

self.circle.fillColor = [UIColor clearColor].CGColor;
self.circle.strokeColor = [UIColor blackColor].CGColor;
self.circle.lineWidth = 5;

[self.view.layer addSublayer:self.circle];
}

使用捏合手势,我允许用户增加/减少形状的半径:

- (void)scale:(UIPinchGestureRecognizer *)gestureRecognizer {    
if (gestureRecognizer.state != UIGestureRecognizerStateBegan) {
if (gestureRecognizer.scale < lastScale) {
--radius;
}
else if (gestureRecognizer.scale > lastScale) {
++radius;
}
// Center the shape in self.view
self.circle.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius, CGRectGetMidY(self.view.frame)-radius);

self.circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;
}

lastScale = gestureRecognizer.scale;
}

但是,圆圈​​不会停留在死点。相反,它会在中间弹跳,直到手势完成才稳定下来。

有谁知道为什么会发生这种情况,如果是这样,我该如何预防?

最佳答案

您的代码中存在一些问题。作为@tc。说,你没有设置形状图层的框架(或边界)。默认层大小为 CGSizeZero,这就是为什么每次更改半径时都必须按半径偏移层的位置。

此外,形状图层的 positionpath 属性是可动画的。所以默认情况下,当您更改它们时,Core Animation 会将它们动画化为它们的新值。路径动画会助长您的不良行为。

此外,您应该根据self.view.bounds而不是self.view.frame设置图层的位置或框架,因为图层的位置/框架是self.view的坐标系,不是self.view.superview的坐标系。如果 self.view 是顶级 View 并且您支持界面自动旋转,这将很重要。

我建议修改您的实现方式。使 radius 成为 CGFloat 属性,并使设置属性更新图层的 boundspath:

@interface ViewController ()

@property (nonatomic, strong) CAShapeLayer *circle;
@property (nonatomic) CGFloat radius;

@end

@implementation ViewController

- (void)setRadius:(CGFloat)radius {
_radius = radius;
self.circle.bounds = CGRectMake(0, 0, 2 * radius, 2 * radius);
self.circle.path = [UIBezierPath bezierPathWithOvalInRect:self.circle.bounds].CGPath;
}

如果您真的想强制半径为整数,我建议无论如何在内部将其跟踪为 float ,因为如果它是 float ,用户交互会更顺畅。在为边界和路径创建 CGRect 之前,只需将它四舍五入到一个临时变量中:

    CGFloat intRadius = roundf(radius);
self.circle.bounds = CGRectMake(0, 0, 2 * intRadius, 2 * intRadius);
self.circle.path = [UIBezierPath bezierPathWithOvalInRect:self.circle.bounds].CGPath;

addCircle 中,只需设置 radius 属性并让该 setter 负责设置图层的边界和路径。也推迟设置层的位置,直到系统的布局阶段。这样,您将在界面旋转后再次将圆圈重新定位在中心。

- (void)viewDidLoad {
[super viewDidLoad];
[self addCircle];
}

- (void)addCircle {
self.circle = [CAShapeLayer layer];
self.circle.fillColor = nil;
self.circle.strokeColor = [UIColor blackColor].CGColor;
self.circle.lineWidth = 5;
self.radius = 100;
[self.view.layer addSublayer:self.circle];
[self.view setNeedsLayout];
}

- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
self.circle.position = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
}

最后,要处理捏合手势,只需将新半径设置为旧半径乘以手势比例即可。 radius setter 将负责更新层的路径和边界。然后将手势的比例重置为 1。这比跟踪手势的先前比例更简单。此外,使用 CATransaction 禁用 path 属性的动画。

- (IBAction)pinchGestureWasRecognized:(UIPinchGestureRecognizer *)recognizer {
[CATransaction begin]; {
[CATransaction setDisableActions:YES];
self.radius *= recognizer.scale;
recognizer.scale = 1;
} [CATransaction commit];
}

关于objective-c - 使用 UIPinchGestureRecognizer 改变圆的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13314779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com