假如你有一張超級大的圖片幾十m的那種,你會怎么做呢?
直接使用UIImageview嗎?那樣內(nèi)存會瞬間爆掉的。蘋果提供了一個類來專門干這個事,CATiledLayer。
思想很簡單,就是把大圖切割成很多個小圖,然后在CATiledLayer的drawRect方法里決定哪一部分該加載哪一張小圖,因為是實時繪制的,即繪制完一張圖片就釋放掉一張圖片,所以內(nèi)存方面基本沒有增長,當你放大或者縮小時,就會觸發(fā)CATiledLayer的drawRect方法。
關(guān)鍵點:
首先,你需要有一個自定義的CATiledLayer
圖片切割,取得指定行列的小圖:
func prepareForSource(atCol col: Int, row: Int) -> UIImage? {
var width = tileSize
var height = tileSize
//最后一列
if col == totalCol-1 {
width = lastColWidth
}
if row == totalRow-1 {
height = lastRowHeight
}
if width == 0 || height == 0 {
return nil
}
let tileImage: CGImage = cgSourceImage!.cropping(to: CGRect(x: CGFloat(
CGFloat(col) * tileSize), y: CGFloat(CGFloat(row) * tileSize), width: width, height: tileSize))!
return UIImage(cgImage: tileImage)
}
drawRect計算哪張圖片繪制到那個rect
override func draw(_ rect: CGRect) {
let ctx: CGContext? = UIGraphicsGetCurrentContext()
let bounds: CGRect = rect
//draw tile
let blockSize: CGSize = self.blockSize
let firstCol = Int(bounds.origin.x / blockSize.width)
let lastCol = Int((bounds.origin.x + bounds.size.width) / blockSize.width - 1)
let firstRow = Int(bounds.origin.y / blockSize.height)
let lastRow = Int((bounds.origin.y + bounds.size.height) / blockSize.height - 1)
//防止過度放大
if (firstRow >= lastRow || firstCol >= lastCol) && (firstCol != totalCol - 1 && lastCol != totalCol - 1 && firstRow != totalRow - 1 && lastRow != totalRow - 1) {
return
}
var i = 0
for row in firstRow...lastRow {
UIGraphicsPushContext(ctx!)
for col in firstCol...lastCol {
//load tile image
let tileImage: UIImage? = prepareForSource(atCol: col, row: row)
if tileImage == nil {
continue
}
let drawRect = CGRect(x: CGFloat(col * Int(blockSize.width)), y: CGFloat(row * Int(blockSize.height)), width: CGFloat(blockSize.width), height: CGFloat(blockSize.height))
tileImage?.draw(in: drawRect)
I+=1
}
UIGraphicsPopContext()
}
當然要實現(xiàn)縮放,你得把視圖放在一個scrollview上面,然后實現(xiàn)對應(yīng)的方法就好了。