iOS學習,ios學習路線
一、給原生的 UIImageView 添加類別來支援 GIF 播放
GIF 動態圖片檔案中包含了一組圖片及資訊,資訊主要記錄著每一幀圖片播放的時間,我們如果擷取到了 gif 檔案中所有的圖片同時又擷取到每一幀圖片播放的時間,就可以為 UIImageView 添加主要畫面格動畫的方法讓其播放 GIF 的內容了
1.建立一個 UIImageView 的類別
2.解析 GIF ,獲得 GIF 的資訊
#pragma mark -- 解析 DGIF-(void)gifWithUrl:(NSURL *)url returnData:(void(^)(NSArray<UIImage *> * imageArray, NSArray<NSNumber *>*timeArray, CGFloat totalTime, NSArray<NSNumber *>* widths, NSArray<NSNumber *>* heights))dataBlock{ //通過檔案的 url 來將 gif 檔案讀取為圖片資料引用 CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url,NULL); //擷取 gif 檔案中的圖片個數 size_t count = CGImageSourceGetCount(source); //定義一個變數記錄 gif 播放一輪的時間 float allTime = 0; //存放所有圖片 NSMutableArray *imageArray = [NSMutableArray array]; //存放每一幀播放的時間 NSMutableArray *timeArray = [NSMutableArray array]; //存放每張圖片的寬度(一般在一個 gif 檔案中,所有檔案的尺寸都一樣) NSMutableArray *widthArray = [NSMutableArray array]; //存放每張圖片的高度 NSMutableArray * heightArray = [NSMutableArray array]; //遍曆 for(size_t i = 0;i < count; i++){ //擷取圖片資訊 CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); [imageArray addObject:(__bridge UIImage *)(image)]; CGImageRelease(image); //擷取圖片資訊 NSDictionary *info = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, i, NULL); NSLog(@"%@",info); CGFloat width = [[info objectForKey:(__bridge NSString *)kCGImagePropertyPixelWidth]floatValue]; CGFloat height = [[info objectForKey:(__bridge NSString *)kCGImagePropertyPixelHeight]floatValue]; [widthArray addObject:[NSNumber numberWithFloat:width]]; [heightArray addObject:[NSNumber numberWithFloat:height]]; NSDictionary *timeDic = [info objectForKey:(__bridge NSString *)kCGImagePropertyGIFDictionary]; CGFloat time = [[timeDic objectForKey:(__bridge NSString *)kCGImagePropertyGIFDelayTime]floatValue]; allTime += time; [timeArray addObject:[NSNumber numberWithFloat:time]]; } dataBlock(imageArray,timeArray,allTime,widthArray,heightArray);}
3.載入 GIF
timingFunction: 控制動畫啟動並執行節奏
- kCAMediaTimingFunctionLinear(線性):勻速,給你一個相對靜態感覺
- kCAMediaTimingFunctionEaseIn(漸進):動畫緩慢進入,然後加速離開
- kCAMediaTimingFunctionEaseOut(漸出):動畫全速進入,然後減速的到達目的地
- kCAMediaTimingFunctionEaseInEaseOut(漸進漸出):動畫緩慢的進入,中間加速,然後減速的到達目的地。這個是預設的動畫行為
#pragma mark -- 載入 GIF- (void)cc_setImage:(NSURL *)imageUrl { __weak id _self = self; [self gifWithUrl:imageUrl returnData:^(NSArray<UIImage *> *imageArray, NSArray<NSNumber *> *timeArray, CGFloat totalTime, NSArray<NSNumber *> *widths, NSArray<NSNumber *> *heights) { CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"]; NSMutableArray * times = [[NSMutableArray alloc]init]; float currentTime = 0; //設定每一幀的時間佔比 for (int i = 0; i < imageArray.count; i++) { [times addObject:[NSNumber numberWithFloat:currentTime/totalTime]]; currentTime += [timeArray[i] floatValue]; } [animation setKeyTimes:times]; [animation setValues:imageArray]; [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; //設定迴圈 animation.repeatCount= MAXFLOAT; //設定播放總時間長度 animation.duration = totalTime; //Layer層添加 [[(UIImageView *)_self layer]addAnimation:animation forKey:@"gifAnimation"]; }];}