在 UIScrollView 中绘制 UIBezierPath

Posted

技术标签:

【中文标题】在 UIScrollView 中绘制 UIBezierPath【英文标题】:Drawing UIBezierPath in a UIScrollView 【发布时间】:2021-02-13 15:22:44 【问题描述】:

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

【问题讨论】:

看看 Adam Wulf's Open Source on Github 特别是他的 PerformanceBezier 项目 【参考方案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

故事板供参考

【讨论】:

从图层创建 uiimage 不会提供最佳性能,尤其是当有许多图层绘制路径时 我认为您的性能问题与滚动视图中的相同?

以上是关于在 UIScrollView 中绘制 UIBezierPath的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIScrollView 的“反弹”区域中绘制?

如何在 UIScrollView 中绘制自定义形状

试图在 uiscrollview 内部绘制

目标 C:在 UIScrollView 中触摸时绘制(写入)

在 UIScrollView 下方绘制阴影(滚动 UIView)

在 ViewController 之外的 UIScrollView 内绘制/布置宽 UIView 的内容