Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/117.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在UIScrollView中缩放UIView和图形_Ios_Objective C_Uiscrollview_Drawing - Fatal编程技术网

Ios 在UIScrollView中缩放UIView和图形

Ios 在UIScrollView中缩放UIView和图形,ios,objective-c,uiscrollview,drawing,Ios,Objective C,Uiscrollview,Drawing,我有一个滚动视图(灰色),里面有一个缩放视图(橙色)。问题是如果我缩放这个视图,它上面绘制的红色形状也会被缩放,包括线宽和蓝色方块的大小。我想要的是保持恒定的线宽和蓝色方块大小(如第一张图片),根据缩放级别缩放形状本身的区域(绘制的文本仅供参考,我不关心其大小) 缩放前 缩放后的 视图控制器 #import "ViewController.h" #import "ZoomingView.h" @interface ViewController () @property (strong,

我有一个滚动视图(灰色),里面有一个缩放视图(橙色)。问题是如果我缩放这个视图,它上面绘制的红色形状也会被缩放,包括线宽和蓝色方块的大小。我想要的是保持恒定的线宽和蓝色方块大小(如第一张图片),根据缩放级别缩放形状本身的区域(绘制的文本仅供参考,我不关心其大小)

缩放前

缩放后的

视图控制器

#import "ViewController.h"
#import "ZoomingView.h"

@interface ViewController ()

@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;

@end

@implementation ViewController
{
    ZoomingView *_zoomingView;
}

- (void)viewDidLayoutSubviews
{
    [self setup];
}

- (void)setup
{
    CGFloat kViewSize = self.scrollView.frame.size.width - 40;

    self.scrollView.minimumZoomScale = 1;
    self.scrollView.maximumZoomScale = 10;
    self.scrollView.delegate = self;
    self.scrollView.contentSize = self.scrollView.bounds.size;

    _zoomingView = [[ZoomingView alloc] initWithFrame:
                    CGRectMake((self.scrollView.frame.size.width - kViewSize) / 2,
                               (self.scrollView.frame.size.height - kViewSize) / 2,
                               kViewSize,
                               kViewSize)];
    [self.scrollView addSubview:_zoomingView];
}

#pragma mark - UIScrollViewDelegate

- (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
    return _zoomingView;
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
    // zooming view position fix

    UIView *zoomView = [scrollView.delegate viewForZoomingInScrollView:scrollView];
    CGRect zvf = zoomView.frame;

    if (zvf.size.width < scrollView.bounds.size.width) {
        zvf.origin.x = (scrollView.bounds.size.width - zvf.size.width) / 2.0f;
    } else {
        zvf.origin.x = 0.0;
    }

    if (zvf.size.height < scrollView.bounds.size.height) {
        zvf.origin.y = (scrollView.bounds.size.height - zvf.size.height) / 2.0f;
    } else {
        zvf.origin.y = 0.0;
    }

    zoomView.frame = zvf;

    [_zoomingView updateWithZoomScale:scrollView.zoomScale];
}

@end

您最好将方框和线型放在
CAShapeLayer
s上,在那里您可以根据缩放比例更新线宽

您只需要创建和定义一次线型。但是,对于长方体,更改缩放时需要重新创建路径(以使长方体的宽度/高度保持恒定的非缩放点大小)

尝试一下。您应该能够简单地替换当前的
ZoomingView.m
类-无需更改视图控制器

//
//  ZoomingView.m
//
//  modified by Don Mag
//

#import "ZoomingView.h"

@interface ZoomingView()

@property (strong, nonatomic) CAShapeLayer *shapeLayer;
@property (strong, nonatomic) CAShapeLayer *boxesLayer;

@property (strong, nonatomic) NSArray *points;

@end

@implementation ZoomingView

{
    CGFloat _zoomScale;
    CGFloat _kPointSize;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (void)setup
{
    self.backgroundColor = [UIColor orangeColor];

    _points = @[[NSValue valueWithCGPoint:CGPointMake(30, 30)],
                [NSValue valueWithCGPoint:CGPointMake(200, 40)],
                [NSValue valueWithCGPoint:CGPointMake(180, 200)],
                [NSValue valueWithCGPoint:CGPointMake(70, 180)]];

    _zoomScale = 1;

    _kPointSize = 10.0;

    // create and setup boxes layer
    _boxesLayer = [CAShapeLayer new];
    [self.layer addSublayer:_boxesLayer];
    _boxesLayer.strokeColor = [UIColor redColor].CGColor;
    _boxesLayer.fillColor = [UIColor clearColor].CGColor;
    _boxesLayer.lineWidth = 1.0;
    _boxesLayer.frame = self.bounds;

    // create and setup shape layer
    _shapeLayer = [CAShapeLayer new];
    [self.layer addSublayer:_shapeLayer];
    _shapeLayer.strokeColor = [UIColor greenColor].CGColor;
    _shapeLayer.fillColor = [UIColor clearColor].CGColor;
    _shapeLayer.lineWidth = 1.0;
    _shapeLayer.frame = self.bounds;

    // new path for shape
    UIBezierPath *thePath = [UIBezierPath new];

    for (NSValue *value in _points) {

        CGPoint point = [value CGPointValue];

        if ([value isEqualToValue:_points.firstObject]) {
            [thePath moveToPoint:point];
        } else {
            [thePath addLineToPoint:point];
        }

    }

    [thePath closePath];

    [_shapeLayer setPath:thePath.CGPath];

    // trigger the boxes update
    [self updateWithZoomScale:_zoomScale];
}

- (void)drawRect:(CGRect)rect
{
    // text

    NSAttributedString *str = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", _zoomScale] attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}];
    [str drawAtPoint:CGPointMake(5, 5)];
}

- (void)updateWithZoomScale:(CGFloat)zoomScale
{
    _zoomScale = zoomScale;

    CGFloat scaledPointSize = _kPointSize * (1.0 / zoomScale);

    // create a path for the boxes
    //  needs to be done here, because the width/height of the boxes
    //  must change with the scale
    UIBezierPath *thePath = [UIBezierPath new];

    for (NSValue *value in _points) {

        CGPoint point = [value CGPointValue];

        CGRect r = CGRectMake(point.x - scaledPointSize / 2.0,
                              point.y - scaledPointSize / 2.0,
                              scaledPointSize,
                              scaledPointSize);

        [thePath appendPath:[UIBezierPath bezierPathWithRect:r]];

    }

    [_boxesLayer setPath:thePath.CGPath];

    _boxesLayer.lineWidth = 1.0 / zoomScale;
    _shapeLayer.lineWidth = 1.0 / zoomScale;

    [self setNeedsDisplay];
}

@end
结果:


注意:应该不用说,但是……这是您工作的起点,而不是“生产代码”。

非常感谢,这个解决方案很有效,请查看我编辑的答案,也许您可以简单地给出我变得模糊的原因(抱歉,如果它看起来有点离题)我实现了你的更新代码,明白了你的意思。我将试着看几件事——如果我发现了什么,我将再次发表评论。只是一个假设,也许玩
CGContextScaleCTM
会有帮助——首先缩放(到什么大小?),然后减小到所需的大小,这样也许我们可以避免模糊
- (void)drawRect:(CGRect)rect
{
    const CGFloat kPointSize = 10;

    NSArray *points = @[[NSValue valueWithCGPoint:CGPointMake(30, 30)],
                        [NSValue valueWithCGPoint:CGPointMake(200, 40)],
                        [NSValue valueWithCGPoint:CGPointMake(180, 200)],
                        [NSValue valueWithCGPoint:CGPointMake(70, 180)]];

    CGFloat scaledPointSize = kPointSize * (1.0 / _zoomScale);
    CGFloat lineWidth = 1.0 / _zoomScale;

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, lineWidth);

    // points

    [[UIColor blueColor] setStroke];

    for (NSValue *value in points) {
        CGPoint point = [value CGPointValue];
        CGContextStrokeRect(context, CGRectMake(point.x - scaledPointSize / 2,
                                                point.y - scaledPointSize / 2,
                                                scaledPointSize,
                                                scaledPointSize));
    }

    // lines

    [[UIColor redColor] setStroke];

    for (NSUInteger i = 0; i < points.count; i++) {
        CGPoint point = [points[i] CGPointValue];

        if (i == 0) {
            CGContextMoveToPoint(context, point.x, point.y);
        } else {
            CGContextAddLineToPoint(context, point.x, point.y);
        }
    }

    CGContextClosePath(context);
    CGContextStrokePath(context);

    // text

    NSAttributedString *str = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", _zoomScale] attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}];
    [str drawAtPoint:CGPointMake(5, 5)];
}

- (void)updateWithZoomScale:(CGFloat)zoomScale
{
    _zoomScale = zoomScale;

    [self setNeedsDisplay];

    [CATransaction begin];
    [CATransaction setValue:[NSNumber numberWithBool:YES]
                     forKey:kCATransactionDisableActions];
    self.layer.contentsScale = zoomScale;
    [CATransaction commit];
}
//
//  ZoomingView.m
//
//  modified by Don Mag
//

#import "ZoomingView.h"

@interface ZoomingView()

@property (strong, nonatomic) CAShapeLayer *shapeLayer;
@property (strong, nonatomic) CAShapeLayer *boxesLayer;

@property (strong, nonatomic) NSArray *points;

@end

@implementation ZoomingView

{
    CGFloat _zoomScale;
    CGFloat _kPointSize;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (void)setup
{
    self.backgroundColor = [UIColor orangeColor];

    _points = @[[NSValue valueWithCGPoint:CGPointMake(30, 30)],
                [NSValue valueWithCGPoint:CGPointMake(200, 40)],
                [NSValue valueWithCGPoint:CGPointMake(180, 200)],
                [NSValue valueWithCGPoint:CGPointMake(70, 180)]];

    _zoomScale = 1;

    _kPointSize = 10.0;

    // create and setup boxes layer
    _boxesLayer = [CAShapeLayer new];
    [self.layer addSublayer:_boxesLayer];
    _boxesLayer.strokeColor = [UIColor redColor].CGColor;
    _boxesLayer.fillColor = [UIColor clearColor].CGColor;
    _boxesLayer.lineWidth = 1.0;
    _boxesLayer.frame = self.bounds;

    // create and setup shape layer
    _shapeLayer = [CAShapeLayer new];
    [self.layer addSublayer:_shapeLayer];
    _shapeLayer.strokeColor = [UIColor greenColor].CGColor;
    _shapeLayer.fillColor = [UIColor clearColor].CGColor;
    _shapeLayer.lineWidth = 1.0;
    _shapeLayer.frame = self.bounds;

    // new path for shape
    UIBezierPath *thePath = [UIBezierPath new];

    for (NSValue *value in _points) {

        CGPoint point = [value CGPointValue];

        if ([value isEqualToValue:_points.firstObject]) {
            [thePath moveToPoint:point];
        } else {
            [thePath addLineToPoint:point];
        }

    }

    [thePath closePath];

    [_shapeLayer setPath:thePath.CGPath];

    // trigger the boxes update
    [self updateWithZoomScale:_zoomScale];
}

- (void)drawRect:(CGRect)rect
{
    // text

    NSAttributedString *str = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%f", _zoomScale] attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:12]}];
    [str drawAtPoint:CGPointMake(5, 5)];
}

- (void)updateWithZoomScale:(CGFloat)zoomScale
{
    _zoomScale = zoomScale;

    CGFloat scaledPointSize = _kPointSize * (1.0 / zoomScale);

    // create a path for the boxes
    //  needs to be done here, because the width/height of the boxes
    //  must change with the scale
    UIBezierPath *thePath = [UIBezierPath new];

    for (NSValue *value in _points) {

        CGPoint point = [value CGPointValue];

        CGRect r = CGRectMake(point.x - scaledPointSize / 2.0,
                              point.y - scaledPointSize / 2.0,
                              scaledPointSize,
                              scaledPointSize);

        [thePath appendPath:[UIBezierPath bezierPathWithRect:r]];

    }

    [_boxesLayer setPath:thePath.CGPath];

    _boxesLayer.lineWidth = 1.0 / zoomScale;
    _shapeLayer.lineWidth = 1.0 / zoomScale;

    [self setNeedsDisplay];
}

@end