iOS开发:接入闪萌动图(仿qq效果)并支持webp动图解析

目标

1、接入闪萌动图
2、仿qq动图效果
3、支持webp

demo链接

https://github.com/pengwj/blogWork/tree/master/code/ShanMengTest

接入闪萌api

闪萌的api需要在他们官网http://www.weshineapp.com,找客服领取测试用的id、密钥。

仿qq动图效果

主要布局采用UICollectionView,大家可以看我demo的实现,我项目中是在输入框文字变换的回调中刷新请求接口的。另外就是需要10秒钟不操作,弹窗自动收回。

//添加定时器
- (void)refreshTimer
{
    _timerValue = 0;

    if (!_timer) {
        _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerDown) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
    }
}

//执行任务
- (void)timerDown
{
    self.timerValue++;
    if (self.timerValue >= 10) {
        [self hideSelf];
    }
}

//定时器的停止
- (void)finishedTimer
{
    self.timerValue = 0;
    
    [self.timer invalidate];
    self.timer = nil;
}

#pragma mark - UIScrollViewDelegate
- ( void)scrollViewDidScroll:( UIScrollView *)scrollView
{
    // 重新开始计时
    [self refreshTimer];
}

支持webp

这个是临时加进来的需求,开始我想着应该很简单,结果没想到还蛮坑的。

webp是谷歌在2010年推出的新一代图片格式,在压缩方面比当前JPEG格式更优越,在质量相同的情况下,WebP格式图像的体积要比JPEG格式图像小40%。

支持webp的显示

下面两个方案我都实现过,其中方案1操作起来更简单一些(demo中选择的也是这个方案),但是由于项目中的SDWebImage版本低于3.0.0,所以只好选择了修改SD的库,也就是方案2。

方案1

使用SDWebImageWebPCoder+SDWebImage即可实现webp的动图+静态图加载。但这个方案比较蛋疼的是SDWebImageWebPCoder比较依赖SDWebImage的实现,中间引用了一大堆SDWebImage的方法,完全没办法独立使用,如果SD用的老版本,那这个方案基本可以放弃了。

添加pod

pod 'SDWebImageWebPCoder'
pod 'SDWebImage', '~> 5.0'

然后执行pod install
但是库去要去拉取谷歌的libwebp文件会失败,所以需要我们进行还原操作。具体操作如下。

操作步骤:

此操作步骤来自于iOSCoder_XH,下面复制一下主要是为了备份。
1、 查看 mac 中 cocoapods 本地库路径:
pod repo
2、在本地库中, 并找到对应的 libwebp 版本的文件
find ~/.cocoapods/repos/master -iname libwebp
3、打开上一步查找的路径
open /Users/xxxxxxx/.cocoapods/repos/master/Specs/1/9/2/libwebp
4、在文件下找到之前pod install失败的libwebp版本文件夹
5、打开文件libwebp.podspec.json,修改git的地址
"source": {
"git": "https://chromium.googlesource.com/webm/libwebp",
"tag": "v1.0.2"
},
改为
"source": {
"git": "https://github.com/webmproject/libwebp.git",
"tag": "v1.0.2"
},
保存
6、重新pod install

使用方法

这里单独拎出来主要是感觉这个库的使用有点怪,官网例子也写的不太清楚。
在你需要展示webp文件的位置,添加coder

// Add coder
SDImageWebPCoder *webPCoder = [SDImageWebPCoder sharedCoder];
[[SDImageCodersManager sharedManager] addCoder:webPCoder];

然后再使用SD加载图片的方法即可支持webp图片的播放。

UIImageView *imageView;
NSURL *webpURL;
[imageView sd_setImageWithURL:webpURL];

是不是很清爽,这里也支持一下SDWebImageWebPCoder,开发者好像还是一个国内的小伙伴,感谢他们的无私奉献。

方案2

如果项目中SDWbImage的版本比较旧的时候,可以考虑一下方案2。方案2主要是修改了SDWebImage解析WebP数据的方法sd_imageWithWebPData,然后用YYImage去解析数据,解析后通过SD的方法返回。

开启SDWebImage的WebP参数

Build Settings中搜索Preprocessor Macros,添加"SD_WEBP=1",添加这个参数后,SDWebImage才会执行webp相关解析代码。

添加YYImage

pod 'YYImage'

然后执行pod install

修改SDWebImage的sd_imageWithWebPData方法

// 添加YYImage头文件
#import <YYImage/YYImage.h>

修改sd_imageWithWebPData方法如下

+ (UIImage *)sd_imageWithWebPData:(NSData *)data {

    YYImage *image = [[YYImage alloc] initWithData:data scale:0];
    
    return image;
}

修改SDWebImage的SDScaledImageForKey方法

该方法在SDWebImageCompat.m文件中。
之所以修改这里,是因为SDWebImage会在这里对图片进行绘制处理,主要是为了适配不同的屏幕scale。所以我们需要在这里直接返回一下。
【注意⚠️⚠️⚠️:不同的SD版本修改的方法可能不同,需要大家自己看项目中SD源码】

inline UIImage *SDScaledImageForKey(NSString *key, UIImage *image) {
    if (!image) {
        return nil;
    }
    
// 添加的代码如下(判断是YYImage直接返回)
    if ([image isKindOfClass:NSClassFromString(@"YYImage")]) {
        return image;
    }
//  添加的代码如上   

    if ([image.images count] > 0) {
        NSMutableArray *scaledImages = [NSMutableArray array];

        for (UIImage *tempImage in image.images) {
            [scaledImages addObject:SDScaledImageForKey(key, tempImage)];
        }

        return [UIImage animatedImageWithImages:scaledImages duration:image.duration];
    }
    else {
        if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
            CGFloat scale = 1.0;
            if (key.length >= 8) {
                // Search @2x. or @3x. at the end of the string, before a 3 to 4 extension length (only if key len is 8 or more @2x./@3x. + 4 len ext)
                NSRange range = [key rangeOfString:@"@2x." options:0 range:NSMakeRange(key.length - 8, 5)];
                if (range.location != NSNotFound) {
                    scale = 2.0;
                }
                
                range = [key rangeOfString:@"@3x." options:0 range:NSMakeRange(key.length - 8, 5)];
                if (range.location != NSNotFound) {
                    scale = 3.0;
                }
            }

            UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
            image = scaledImage;
        }
        return image;
    }
}

使用如下

主要是需要替换UIImageViewYYAnimatedImageView,其他的正常使用即可。

// 引入YYAnimatedImageView.h头文件
#import <YYImage/YYAnimatedImageView.h>

// 初始化YYAnimatedImageView
@property (nonatomic, strong) YYAnimatedImageView *gifImageView;
    NSURL *url  = [NSURL URLWithString:@"闪萌动图webp地址"];
    [self.gifImageView sd_setImageWithURL:url completed:nil];

将webp转换成gif并保存到本地

核心代码如下:

        YYImageDecoder *decoder = [YYImageDecoder decoderWithData:self.gifImageView.animatedImageData scale:0];
        NSData *gifData = [YYImageEncoder encodeImageWithDecoder:decoder type:YYImageTypeGIF quality:1];

使用YYImageDecoder先解压webp图片,然后用YYImageEncoderencodeImageWithDecoder方法将webp格式的动图转换成gif格式的Data,然后保存到相册中。

全部代码如下:

        
        YYImageDecoder *decoder = [YYImageDecoder decoderWithData:self.emojiImage.animatedImageData scale:0];
        NSData *gifData = [YYImageEncoder encodeImageWithDecoder:decoder type:YYImageTypeGIF quality:1];
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            [[PHAssetCreationRequest creationRequestForAsset] addResourceWithType:PHAssetResourceTypePhoto data:gifData options:nil];
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                
                if(success && !error){
                    [SVProgressHUD showSuccessWithStatus:@"保存动图成功"];
                }else
                    [SVProgressHUD showErrorWithStatus:@"保存动图失败,请重试"];
            });
            
        }];
        
    });

总结

遇到各个博客没有比较成熟的解决方案时,记得优先看开源库、系统库的相关头文件。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容