Skip to content

Latest commit

 

History

History
81 lines (61 loc) · 3.27 KB

大图显示.md

File metadata and controls

81 lines (61 loc) · 3.27 KB

大图显示

1 CATiledLayer

1.1 CATiledLayer简介

显示远超手机屏幕分辨率的大图时,传统加载方法会造成内存暴涨,主线程阻塞,甚至内存到峰值造成崩溃。可以使用CATiledLayer来显示大图,类似瓦片视图,将需要绘制的内容分割成许多小块,然后异步绘制相应的小块,这样就节约了处理时间和内存。

有以下优点

  • 不需要计算分块显示的区域,直接提供,只需要根据这个区域计算图片相应区域,然后绘制即可。
  • 在其他线程绘制,不会因为阻塞主线程而导致卡顿。
  • 实现了只在屏幕区域内显示图片,屏幕外不会显示,而且移动时会自动绘制之前未绘制的区域,当你缩放时也会自动重绘。

CATiledLayer有三个重要属性:

levelsOfDetail:指该图层缓存的缩小LOD数目,默认值为1,每进一级会对前一级分辨率的一半进行缓存,图层的levelsOfDetail最大值,对应至少一个像素点。

levelsOfDetailBias:指该图层缓存的放大LODB数目,是layer的方法级别重绘设置,默认是0,不会额外缓存放大层次,每进一级会对前一级两倍分辨率进行缓存。

tileSize:layer划分视图区域最大尺寸,影响layer的切片数量。默认是256x256。

1.2 CATiledLayer使用

需要实现layerClass和drawRect方法,才能使用CATiledLayer设置参数,即可实现瓦片绘制效果。

代码如下:

- (void)setImageName:(NSString *)imageName {
    [self lg_setImage:[UIImage imageNamed:imageName]];
}

- (void)lg_setImage:(UIImage *)image {
    if (tiledCount == 0) tiledCount = 16;
    originImage = image;
    [self setBackgroundColor:[UIColor whiteColor]];
    imageRect = CGRectMake(0.0f,
                           0.0f,
                           CGImageGetWidth(originImage.CGImage),
                           CGImageGetHeight(originImage.CGImage));
    imageScale_w = self.frame.size.width/imageRect.size.width;
    imageScale_h = self.frame.size.height/imageRect.size.height;
    CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
    
    int scale = (int)MAX(1/imageScale_w, 1/imageScale_h);
    
    int lev = ceil(scale);
    tiledLayer.levelsOfDetail = 1;
    tiledLayer.levelsOfDetailBias = lev;
    
    if(tiledCount > 0){
        NSInteger tileSizeScale = sqrt(tiledCount)/2;
        CGSize tileSize = self.bounds.size;
        tileSize.width /=tileSizeScale;
        tileSize.height /=tileSizeScale;
        tiledLayer.tileSize = tileSize;
    }
}

+ (Class)layerClass {
    return [CATiledLayer class];
}

- (void)drawRect:(CGRect)rect {
    @autoreleasepool{
        CGRect imageCutRect = CGRectMake(rect.origin.x / imageScale_w,
                                         rect.origin.y / imageScale_h,
                                         rect.size.width / imageScale_w,
                                         rect.size.height / imageScale_h);
        CGImageRef imageRef = CGImageCreateWithImageInRect(originImage.CGImage, imageCutRect);
        UIImage *tileImage = [UIImage imageWithCGImage:imageRef];
        CGContextRef context = UIGraphicsGetCurrentContext();
        UIGraphicsPushContext(context);
        [tileImage drawInRect:rect];
        CGImageRelease(imageRef);
        UIGraphicsPopContext();
    }
}