GifImageView.m 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. //
  2. // GifImageView.m
  3. // iChatView
  4. //
  5. // Created by zzl on 16/6/3.
  6. // Copyright © 2016年 ldh. All rights reserved.
  7. //
  8. #import "GifImageView.h"
  9. #import "UIImageView+WebCache.h"
  10. @interface GifImageView ()
  11. {
  12. CGFloat _top;
  13. }
  14. @property (nonatomic, weak)IBOutlet FLAnimatedImageView *gifImage;
  15. @property (nonatomic, weak)IBOutlet UILabel *nickLabel;
  16. @property (nonatomic, assign) NSUInteger currentLoopIndex; // 当前循环的次数
  17. @property (nonatomic, copy) NSString *senderName;
  18. @end
  19. @implementation GifImageView
  20. - (id)initWithModel:(AnimateConfigModel*)gift inView:(UIView*)superView andSenderName:(NSString *)senderName
  21. {
  22. self = [[[NSBundle mainBundle] loadNibNamed:@"GifImageView" owner:self options:nil] lastObject];
  23. if (self)
  24. {
  25. self.backgroundColor = [UIColor clearColor];
  26. _nickLabel.hidden = YES;
  27. [superView addSubview:self];
  28. // [superView sendSubviewToBack:self];
  29. _senderName = senderName;
  30. if ([gift isKindOfClass:[NSDictionary class]]) {
  31. AnimateConfigModel *model = [AnimateConfigModel modelWithDictionary:gift];
  32. [self cfgWithGift:model andTop:0];
  33. }else{
  34. [self cfgWithGift:gift andTop:0];
  35. }
  36. }
  37. return self;
  38. }
  39. - (id)initWithModel2:(GiftModel *)gift inView:(UIView *)superView andSenderName:(NSString *)senderName
  40. {
  41. self = [[[NSBundle mainBundle] loadNibNamed:@"GifImageView" owner:self options:nil] lastObject];
  42. if (self)
  43. {
  44. self.backgroundColor = [UIColor clearColor];
  45. _nickLabel.hidden = YES;
  46. [superView addSubview:self];
  47. _senderName = senderName;
  48. [self cfgWithGift2:gift andTop:0];
  49. }
  50. return self;
  51. }
  52. - (void)cfgWithGift:(AnimateConfigModel*)gift andTop:(CGFloat)top
  53. {
  54. _giftItem = gift;
  55. _top = top;
  56. __weak typeof(self) ws = self;
  57. [self loadAnimatedImageWithURL:[NSURL URLWithString:gift.url] completion:^(FLAnimatedImage *animatedImage) {
  58. ws.gifImage.animatedImage = animatedImage;
  59. if (ws.giftItem.delay_time)
  60. {
  61. ws.hidden = YES;
  62. [ws performSelector:@selector(setUpView:) withObject:gift afterDelay:_giftItem.delay_time/1000];
  63. }
  64. else
  65. {
  66. [ws setUpView:gift];
  67. }
  68. }];
  69. }
  70. - (void)cfgWithGift2:(GiftModel*)gift andTop:(CGFloat)top
  71. {
  72. _giftModel = gift;
  73. _top = top;
  74. __weak typeof(self) ws = self;
  75. [self.gifImage sd_setImageWithURL:[NSURL URLWithString:gift.animated_url] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
  76. //图片下载完成 在这里进行相关操作,如加到数组里 或者显示在imageView上
  77. if (ws.giftItem.delay_time)
  78. {
  79. ws.hidden = YES;
  80. [ws performSelector:@selector(setUpView:) withObject:gift afterDelay:_giftItem.delay_time/1000];
  81. }
  82. else
  83. {
  84. [ws setUpView2:gift];
  85. }
  86. }];
  87. }
  88. - (void)setUpView2:(GiftModel*)gift
  89. {
  90. self.hidden = NO;
  91. [self setUserInteractionEnabled:NO];
  92. CGRect pRect = self.superview.frame; //superview的frame
  93. CGRect vRect = self.gifImage.frame; //gifImage的frame
  94. CGSize size = self.gifImage.currentFrame.size; //图片的size
  95. CGFloat imageScale = size.width/size.height; //图片宽高比
  96. CGFloat w = size.width;
  97. CGFloat h = size.height;
  98. /**
  99. gif_gift_show_style:
  100. 0:按像素显示模式(当某条边超出手机屏幕时该条边贴边),配合位置参数使用;
  101. 1、全屏显示模式(gif图片四个角顶住手机屏幕的四个角);
  102. 2、至少两条边贴边模式(按比例缩放到手机屏幕边界的最大尺寸),配合位置参数使用;
  103. */
  104. // if (gift.gif_gift_show_style == 0)
  105. // {
  106. // if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) > 0)
  107. // { //如果图片的宽、高都超过的屏幕宽、高
  108. // if ((size.width-pRect.size.width) > (size.height-pRect.size.height))
  109. // {
  110. // w = pRect.size.width;
  111. // h = w / imageScale;
  112. // }
  113. // else
  114. // {
  115. // h = pRect.size.height;
  116. // w = h * imageScale;
  117. // }
  118. // }
  119. // else if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) < 0)
  120. // { //如果图片的宽超过的屏幕宽,但是高小于屏幕的高
  121. // w = pRect.size.width;
  122. // h = w / imageScale;
  123. // }
  124. // else if ((size.width-pRect.size.width) < 0 && (size.height-pRect.size.height) > 0)
  125. // { //如果图片的高超过的屏幕高,但是宽小于屏幕的宽
  126. // h = pRect.size.height;
  127. // w = h * imageScale;
  128. // }
  129. // vRect.size = CGSizeMake(w, h);
  130. // self.gifImage.frame = vRect;
  131. // size = vRect.size;
  132. // }
  133. // else if (gift.gif_gift_show_style == 1)
  134. // {
  135. if (_giftItem.show_user == 0)
  136. {
  137. _nickLabel.hidden = YES;
  138. _nickLabel.text = @"";
  139. vRect = CGRectMake(0, 0, pRect.size.width, pRect.size.height);
  140. }
  141. else
  142. {
  143. _nickLabel.hidden = NO;
  144. vRect.size = CGSizeMake(pRect.size.width, pRect.size.height-_nickLabel.frame.size.height);
  145. }
  146. _nickLabel.hidden = YES;
  147. self.gifImage.frame = vRect;
  148. size = vRect.size;
  149. // }
  150. // else if (gift.gif_gift_show_style == 2)
  151. // {
  152. // if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) > 0)
  153. // { //如果图片的宽、高都超过的屏幕宽、高
  154. // if ((size.width-pRect.size.width) > (size.height-pRect.size.height))
  155. // {
  156. // w = pRect.size.width;
  157. // h = w / imageScale;
  158. // }
  159. // else
  160. // {
  161. // h = pRect.size.height;
  162. // w = h * imageScale;
  163. // }
  164. // }
  165. // else if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) < 0)
  166. // { //如果图片的宽超过的屏幕宽,但是高小于屏幕的高
  167. // w = pRect.size.width;
  168. // h = w / imageScale;
  169. // }
  170. // else if ((size.width-pRect.size.width) < 0 && (size.height-pRect.size.height) > 0)
  171. // { //如果图片的高超过的屏幕高,但是宽小于屏幕的宽
  172. // h = pRect.size.height;
  173. // w = h * imageScale;
  174. // }
  175. // else if ((size.width-pRect.size.width) < 0 && (size.height-pRect.size.height) < 0)
  176. // { //如果图片的宽、高都小于屏幕的宽
  177. // if ((size.width-pRect.size.width) > (size.height-pRect.size.height))
  178. // {
  179. // w = pRect.size.width;
  180. // h = w / imageScale;
  181. // }
  182. // else
  183. // {
  184. // h = pRect.size.height;
  185. // w = h * imageScale;
  186. // }
  187. // }
  188. //
  189. // vRect.size = CGSizeMake(w, h);
  190. // self.gifImage.frame = vRect;
  191. // size = vRect.size;
  192. // }
  193. // if (_giftItem.show_user == 0)
  194. // {
  195. // _nickLabel.hidden = YES;
  196. // _nickLabel.text = @"";
  197. // self.labelHeight.constant = 0;
  198. // }
  199. // else
  200. // {
  201. _nickLabel.hidden = NO;
  202. [self bringSubviewToFront:_nickLabel];
  203. _nickLabel.text = _senderName;
  204. if (size.height - _nickLabel.frame.size.height <= pRect.size.height)
  205. {
  206. size.height += _nickLabel.frame.size.height;
  207. }
  208. self.labelHeight.constant = 21;
  209. // }
  210. _nickLabel.hidden = YES;
  211. CGRect rect = CGRectMake((pRect.size.width-size.width)/2, _top, size.width, size.height);
  212. //0:使用path路径;1:屏幕上部;2:屏幕中间;3:屏幕底部
  213. // if (_giftItem.type == 0)
  214. // {
  215. // rect.origin.y = 0;
  216. // }
  217. // else if(_giftItem.type == 1)
  218. // {
  219. // rect.origin.y = 0;
  220. // }
  221. // else if(_giftItem.type == 2)
  222. // {
  223. rect.origin.y = (pRect.size.height - size.height)/2;
  224. // }
  225. // else if(_giftItem.type == 3)
  226. // {
  227. // rect.origin.y = pRect.size.height - size.height;
  228. // }
  229. self.frame = rect;
  230. [self layoutIfNeeded];
  231. __weak typeof(self) ws = self;
  232. self.gifImage.loopCompletionBlock = ^(NSUInteger loopCountRemaining){
  233. [ws dismissSelf];
  234. // ws.currentLoopIndex ++;
  235. //
  236. // if (ws.giftItem.play_count)
  237. // {
  238. // if (ws.giftItem.play_count == ws.currentLoopIndex)
  239. // {
  240. // [ws dismissSelf];
  241. // }
  242. // }
  243. // else
  244. // {
  245. // [ws performSelector:@selector(dismissSelf) withObject:gift afterDelay:_giftItem.duration/1000];
  246. // }
  247. };
  248. }
  249. - (void)setUpView:(AnimateConfigModel*)gift
  250. {
  251. self.hidden = NO;
  252. [self setUserInteractionEnabled:NO];
  253. CGRect pRect = self.superview.frame; //superview的frame
  254. CGRect vRect = self.gifImage.frame; //gifImage的frame
  255. CGSize size = self.gifImage.currentFrame.size; //图片的size
  256. CGFloat imageScale = size.width/size.height; //图片宽高比
  257. CGFloat w = size.width;
  258. CGFloat h = size.height;
  259. /**
  260. gif_gift_show_style:
  261. 0:按像素显示模式(当某条边超出手机屏幕时该条边贴边),配合位置参数使用;
  262. 1、全屏显示模式(gif图片四个角顶住手机屏幕的四个角);
  263. 2、至少两条边贴边模式(按比例缩放到手机屏幕边界的最大尺寸),配合位置参数使用;
  264. */
  265. if (gift.gif_gift_show_style == 0)
  266. {
  267. if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) > 0)
  268. { //如果图片的宽、高都超过的屏幕宽、高
  269. if ((size.width-pRect.size.width) > (size.height-pRect.size.height))
  270. {
  271. w = pRect.size.width;
  272. h = w / imageScale;
  273. }
  274. else
  275. {
  276. h = pRect.size.height;
  277. w = h * imageScale;
  278. }
  279. }
  280. else if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) < 0)
  281. { //如果图片的宽超过的屏幕宽,但是高小于屏幕的高
  282. w = pRect.size.width;
  283. h = w / imageScale;
  284. }
  285. else if ((size.width-pRect.size.width) < 0 && (size.height-pRect.size.height) > 0)
  286. { //如果图片的高超过的屏幕高,但是宽小于屏幕的宽
  287. h = pRect.size.height;
  288. w = h * imageScale;
  289. }
  290. vRect.size = CGSizeMake(w, h);
  291. self.gifImage.frame = vRect;
  292. size = vRect.size;
  293. }
  294. else if (gift.gif_gift_show_style == 1)
  295. {
  296. if (_giftItem.show_user == 0)
  297. {
  298. _nickLabel.hidden = YES;
  299. _nickLabel.text = @"";
  300. vRect = CGRectMake(0, 0, pRect.size.width, pRect.size.height);
  301. }
  302. else
  303. {
  304. _nickLabel.hidden = NO;
  305. vRect.size = CGSizeMake(pRect.size.width, pRect.size.height-_nickLabel.frame.size.height);
  306. }
  307. self.gifImage.frame = vRect;
  308. size = vRect.size;
  309. }
  310. else if (gift.gif_gift_show_style == 2)
  311. {
  312. if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) > 0)
  313. { //如果图片的宽、高都超过的屏幕宽、高
  314. if ((size.width-pRect.size.width) > (size.height-pRect.size.height))
  315. {
  316. w = pRect.size.width;
  317. h = w / imageScale;
  318. }
  319. else
  320. {
  321. h = pRect.size.height;
  322. w = h * imageScale;
  323. }
  324. }
  325. else if ((size.width-pRect.size.width) > 0 && (size.height-pRect.size.height) < 0)
  326. { //如果图片的宽超过的屏幕宽,但是高小于屏幕的高
  327. w = pRect.size.width;
  328. h = w / imageScale;
  329. }
  330. else if ((size.width-pRect.size.width) < 0 && (size.height-pRect.size.height) > 0)
  331. { //如果图片的高超过的屏幕高,但是宽小于屏幕的宽
  332. h = pRect.size.height;
  333. w = h * imageScale;
  334. }
  335. else if ((size.width-pRect.size.width) < 0 && (size.height-pRect.size.height) < 0)
  336. { //如果图片的宽、高都小于屏幕的宽
  337. if ((size.width-pRect.size.width) > (size.height-pRect.size.height))
  338. {
  339. w = pRect.size.width;
  340. h = w / imageScale;
  341. }
  342. else
  343. {
  344. h = pRect.size.height;
  345. w = h * imageScale;
  346. }
  347. }
  348. vRect.size = CGSizeMake(w, h);
  349. self.gifImage.frame = vRect;
  350. size = vRect.size;
  351. }
  352. if (_giftItem.show_user == 0)
  353. {
  354. _nickLabel.hidden = YES;
  355. _nickLabel.text = @"";
  356. self.labelHeight.constant = 0;
  357. }
  358. else
  359. {
  360. _nickLabel.hidden = NO;
  361. [self bringSubviewToFront:_nickLabel];
  362. _nickLabel.text = _senderName;
  363. if (size.height - _nickLabel.frame.size.height <= pRect.size.height)
  364. {
  365. size.height += _nickLabel.frame.size.height;
  366. }
  367. self.labelHeight.constant = 21;
  368. }
  369. CGRect rect = CGRectMake((pRect.size.width-size.width)/2, _top, size.width, size.height);
  370. //0:使用path路径;1:屏幕上部;2:屏幕中间;3:屏幕底部
  371. if (_giftItem.type == 0)
  372. {
  373. rect.origin.y = 0;
  374. }
  375. else if(_giftItem.type == 1)
  376. {
  377. rect.origin.y = 0;
  378. }
  379. else if(_giftItem.type == 2)
  380. {
  381. rect.origin.y = (pRect.size.height - size.height)/2;
  382. }
  383. else if(_giftItem.type == 3)
  384. {
  385. rect.origin.y = pRect.size.height - size.height;
  386. }
  387. self.frame = rect;
  388. [self layoutIfNeeded];
  389. _nickLabel.hidden = YES;
  390. __weak typeof(self) ws = self;
  391. self.gifImage.loopCompletionBlock = ^(NSUInteger loopCountRemaining){
  392. ws.currentLoopIndex ++;
  393. if (ws.giftItem.play_count)
  394. {
  395. if (ws.giftItem.play_count == ws.currentLoopIndex)
  396. {
  397. [ws dismissSelf];
  398. }
  399. }
  400. else
  401. {
  402. [ws performSelector:@selector(dismissSelf) withObject:gift afterDelay:_giftItem.duration/1000];
  403. }
  404. };
  405. }
  406. - (void)dismissSelf
  407. {
  408. FWWeakify(self)
  409. [UIView animateWithDuration:0.01 animations:^{
  410. FWStrongify(self)
  411. self.alpha = 0.0;
  412. } completion:^(BOOL finished) {
  413. FWStrongify(self)
  414. if (_giftItem) {
  415. if (self.delegate && [self.delegate respondsToSelector:@selector(gifImageViewFinish:andSenderName:)])
  416. {
  417. self.giftItem.isFinishAnimate = YES;
  418. [self.delegate gifImageViewFinish:self.giftItem andSenderName:self.senderName];
  419. }
  420. [self removeFromSuperview];
  421. }else{
  422. if (self.delegate && [self.delegate respondsToSelector:@selector(gifImageViewFinish2:andSenderName:)])
  423. {
  424. self.giftItem.isFinishAnimate = YES;
  425. [self.delegate gifImageViewFinish2:self.giftModel andSenderName:self.senderName];
  426. }
  427. [self removeFromSuperview];
  428. }
  429. }];
  430. }
  431. - (void)loadAnimatedImageWithURL:(NSURL *const)url completion:(void (^)(FLAnimatedImage *animatedImage))completion
  432. {
  433. NSString *const filename = url.lastPathComponent;
  434. NSString *const diskPath = [NSHomeDirectory() stringByAppendingPathComponent:filename];
  435. NSData * __block animatedImageData = [[NSFileManager defaultManager] contentsAtPath:diskPath];
  436. FLAnimatedImage * __block animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:animatedImageData];
  437. if (animatedImage) {
  438. if (completion) {
  439. completion(animatedImage);
  440. }
  441. } else {
  442. [[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
  443. animatedImageData = data;
  444. animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:animatedImageData];
  445. if (animatedImage) {
  446. if (completion) {
  447. dispatch_async(dispatch_get_main_queue(), ^{
  448. completion(animatedImage);
  449. });
  450. }
  451. [data writeToFile:diskPath atomically:YES];
  452. }
  453. }] resume];
  454. }
  455. }
  456. @end