在 UIScrollView 中绘制 UIBezierPath

Drawing UIBezierPath in a UIScrollView

提问人:arturdev 提问时间:10/31/2020 最后编辑:arturdev 更新时间:10/31/2020 访问量:178

问:

我正在尝试在可缩放的 UIScrollView 中绘制 UIBezierPath(例如 800x300)。缩放完成后,我将相应地调整路径图层的比例值,以绘制平滑的路径(否则会模糊)。 一切都很顺利,直到我放大到一个非常高的值(比如 100 倍)。缩放后,绘制路径的结果图层的大小为 80,000x30,000,显然它会在控制台中抛出警告,指出“忽略虚假的图层大小”,并且不再调用 drawRect,也不会绘制。如果这是一个常规的图像绘制,我将使用 CATiledLayer 并实现平铺绘制。但是如何处理UIBezierPath绘图呢?在如此大的可缩放画布中绘制路径的最佳/最佳方法是什么(除了从路径制作图像并实现平铺绘制)?

iOS Objective-C Swift UIscrollView 核心图形

评论

0赞 Ol Sen 10/31/2020
看看 Adam Wulf 在 Github 上的开源,特别是他的 PerformanceBezier 项目

答:

1赞 skaak 10/31/2020 #1

一旦缩放突破某个阈值,就可以绘制到 UIImage。在那里,您可以应用比例变换,如下所示。然后将图像传输到滚动视图。

这是一个小测试,它双向工作都没有问题。

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView * zoomImage;
@property (weak, nonatomic) IBOutlet UILabel     * zoomLabel;

@property (nonatomic)                CGFloat       zoomFactor;

@end

@implementation ViewController

// Bezier path
// Draws a little cross
- ( void ) drawIt:( CGContextRef ) cr
{
    CGContextBeginPath( cr );
    CGContextMoveToPoint( cr, 0, 0 );
    CGContextAddLineToPoint( cr, 10, 10 );
    CGContextMoveToPoint( cr, 0, 10 );
    CGContextAddLineToPoint( cr, 10, 0 );
    CGContextClosePath( cr );
    CGContextStrokePath( cr );
}

- ( void ) setZoomFactor:( CGFloat ) zoomFactor
{
    _zoomFactor = zoomFactor;

    self.zoomLabel.text = [NSString stringWithFormat:@"Now %f", zoomFactor];

    CGSize srcSz = CGSizeMake ( 10 * zoomFactor, 10 * zoomFactor );
    CGSize dstSz = self.zoomImage.bounds.size;

    // Aspect ratio
    CGFloat sx = dstSz.width  / srcSz.width;
    CGFloat sy = dstSz.height / srcSz.height;

    self.zoomImage.image = [[[UIGraphicsImageRenderer alloc] initWithSize:dstSz] imageWithActions: ^ ( UIGraphicsImageRendererContext * ctx ) {
        
        CGContextRef cr = ctx.CGContext;

        // Aspect
        if ( sx < sy )
        {
            CGContextScaleCTM ( cr, sx, sx );
        }
        else
        {
            CGContextScaleCTM ( cr, sy, sy );
        }

        // Offset
        CGContextTranslateCTM ( cr, srcSz.width / 2 - 5, srcSz.height / 2 - 5 );

        // Draw
        [self drawIt:cr];
    }];
}

- ( void ) viewDidAppear:( BOOL ) animated
{
    [super viewDidAppear:animated];

    if ( ! self.zoomFactor )
    {
        self.zoomFactor = 1;
    }
}

- ( IBAction ) zoomInButtonAction:( id ) sender
{
    if ( self.zoomFactor > 1e-12 )
    {
        self.zoomFactor /= 2;
    }
}

- ( IBAction ) zoomOutButtonAction:( id ) sender
{
    if ( self.zoomFactor < 1e12 )
    {
        self.zoomFactor *= 2;
    }
}

@end

故事板供参考enter image description here

评论

1赞 arturdev 10/31/2020
从图层创建 uiimage 不会提供最佳性能,尤其是当有许多绘制路径的图层时
1赞 skaak 10/31/2020
我认为您遇到与滚动视图相同的性能问题?