注:用WebView可以加载Gif 但是会需要加载的时间比较长,所以用CAKeyframeAnimation 去加载Gif文件
// 首先先创建一个UIView的子类 GifView,里面代码如下
import UIKit
import ImageIO
import QuartzCore
typealias completionBlock = ()->() // 动画完成后做的事情
class GifView: UIView, CAAnimationDelegate {
private var gifurl: URL! // 把本地图片转化成URL
private var imageArr: Array<CGImage> = [] // 图片数组(存放每一帧的图片)
private var timeArr: Array<NSNumber> = [] // 时间数组 (存放每一帧的图片的时间)
private var totalTime: Float = 0 // gif 动画时间
private var completionClosure: completionBlock?
/**
* 加载本地GIF 图片
*/
func showGIFImageWithLocalName(name: String, completionClosure:@escaping (()->())) {
self.completionClosure = completionClosure
self.gifurl = Bundle.main.url(forResource: name, withExtension: "gif")
self.createKeyFram()
}
/**
* 获取GIF 图片的每一帧有关的东西 比如:每一帧的图片、每一帧图片执行的时间
*/
private func createKeyFram() {
let url: CFURL = self.gifurl as CFURL
let gifSource = CGImageSourceCreateWithURL(url, nil)
let imageCount = CGImageSourceGetCount(gifSource!) // 总共图片张数
for i in 0..<imageCount {
let imageRef = CGImageSourceCreateImageAtIndex(gifSource!, i, nil) // 取得每一帧的图
self.imageArr.append(imageRef!)
let sourceDict = CGImageSourceCopyPropertiesAtIndex(gifSource!, i, nil) as NSDictionary!
let gifDict = sourceDict![String(kCGImagePropertyGIFDictionary)] as! NSDictionary?
let time = gifDict![String(kCGImagePropertyGIFUnclampedDelayTime)] as! NSNumber // 每一帧的动画时间
self.timeArr.append(time)
self.totalTime += time.floatValue
// 获取图片的尺寸 (适应)
let imageWidth = sourceDict![String(kCGImagePropertyPixelWidth)] as! NSNumber
let imageHeight = sourceDict![String(kCGImagePropertyPixelHeight)] as! NSNumber
if (imageWidth.floatValue / imageHeight.floatValue) != Float(self.width/self.height) {
self.fitScale(imageWidth: CGFloat(imageWidth.floatValue), imageHeight: CGFloat(imageHeight.floatValue))
}
}
self.showAnimation()
}
/**
* 适应
*/
private func fitScale(imageWidth: CGFloat, imageHeight: CGFloat) {
var newWidth: CGFloat
var newHeight: CGFloat
if imageWidth/imageHeight > self.width/self.height {
newWidth = self.width
newHeight = self.width/(imageWidth/imageHeight)
} else {
newHeight = self.height
newWidth = self.height/(imageHeight/imageWidth)
}
let point = self.center;
self.frame.size = CGSize(width: newWidth, height: newHeight)
self.center = point
}
/**
* 展示动画
*/
private func showAnimation() {
let animation = CAKeyframeAnimation(keyPath: "contents")
var current: Float = 0
var timeKeys: Array<NSNumber> = []
for time in timeArr {
timeKeys.append(NSNumber(value: current/self.totalTime))
current += time.floatValue
}
animation.keyTimes = timeKeys
animation.delegate = self
animation.values = self.imageArr
animation.repeatCount = 1;
animation.duration = TimeInterval(totalTime)
animation.isRemovedOnCompletion = false
self.layer.add(animation, forKey: "GifView")
}
// Delegate 动画结束
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
self.removeFromSuperview()
if self.completionClosure != nil {
self.completionClosure!()
}
}
}
之后再需要用动画的VC 里面 执行动画即可,代码如下
class TestViewController: UIViewControlelr {
override func viewDidLoad() {
super.viewDidLoad()
// 加载本地GIF 的View
let gifView = GifView()
gifView.frame = UIScreen.main.bounds
gifView.showGIFImageWithLocalName(name: "bootPage", completionClosure: {
// 做动画执行后的操作
})
self.view.addSubview(gifView)
}
}