PhotoView.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. //
  2. // PhotoView.m
  3. // ImageBrowser
  4. //
  5. // Created by msk on 16/9/1.
  6. // Copyright © 2016年 msk. All rights reserved.
  7. //
  8. #import "PhotoView.h"
  9. #import "SDWebImageManager.h"
  10. #import "UIImageView+WebCache.h"
  11. #import "MBProgressHUD.h"
  12. #import "SDImageCache.h"
  13. #define SD_WEBP 1
  14. #import "UIImageView+WebCache.h"
  15. #import "UIImage+WebP.h"
  16. @interface PhotoView ()<UIScrollViewDelegate>{
  17. MBProgressHUD *HUD;
  18. }
  19. @end
  20. @implementation PhotoView
  21. //-(id)initWithFrame:(CGRect)frame withPhotoUrl:(NSString *)photoUrl{
  22. // self = [super initWithFrame:frame];
  23. // if (self) {
  24. // //添加图片
  25. // SDWebImageManager *manager = [SDWebImageManager sharedManager];
  26. // NSURL *url;
  27. // if (![photoUrl hasPrefix:@"http"]) {
  28. // url = [NSURL fileURLWithPath:photoUrl];
  29. // }else{
  30. // url = [NSURL URLWithString:photoUrl];
  31. // }
  32. // [manager cachedImageExistsForURL:url completion:^(BOOL isInCache) {
  33. // if (!isInCache) {//没有缓存
  34. // HUD = [MBProgressHUD showHUDAddedTo:self animated:YES];
  35. // HUD.mode = MBProgressHUDModeDeterminate;
  36. //
  37. //
  38. // [self.imageView sd_setImageWithPreviousCachedImageWithURL:url placeholderImage:[UIImage imageNamed:@"ic-zanwu@3x"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
  39. // HUD.progress = ((float)receivedSize)/expectedSize;
  40. // } completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
  41. // self.imageView.frame=[self caculateOriginImageSizeWith:image];
  42. // NSLog(@"图片加载完成");
  43. // if ([photoUrl rangeOfString:@".gif"].location != NSNotFound) {
  44. //
  45. // HUD = [MBProgressHUD showHUDAddedTo:self animated:YES];
  46. // HUD.mode = MBProgressHUDModeDeterminate;
  47. //
  48. // [self loadAnimatedImageWithURL:url completion:^(FLAnimatedImage *animatedImage) {
  49. // self.imageView.animatedImage = animatedImage;
  50. // NSLog(@"图片加载完成");
  51. // [HUD hide:YES];
  52. // }];
  53. //
  54. // }
  55. // if (!isInCache) {
  56. // [HUD hide:YES];
  57. // }
  58. // }];
  59. // }else{//直接取出缓存的图片,减少流量消耗
  60. // UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:url.absoluteString];
  61. // self.imageView.frame=[self caculateOriginImageSizeWith:cachedImage];
  62. // self.imageView.image=cachedImage;
  63. // if ([photoUrl rangeOfString:@".gif"].location != NSNotFound) {
  64. //
  65. // HUD = [MBProgressHUD showHUDAddedTo:self animated:YES];
  66. // HUD.mode = MBProgressHUDModeDeterminate;
  67. //
  68. // [self loadAnimatedImageWithURL:[NSURL URLWithString:photoUrl] completion:^(FLAnimatedImage *animatedImage) {
  69. // self.imageView.animatedImage = animatedImage;
  70. // NSLog(@"图片加载完成");
  71. // [HUD hide:YES];
  72. // }];
  73. //
  74. // }
  75. // }
  76. // }];
  77. //
  78. //
  79. //
  80. //
  81. //// BOOL isCached = [manager cachedImageExistsForURL:[NSURL URLWithString:photoUrl]];
  82. //
  83. // }
  84. // return self;
  85. //}
  86. -(id)initWithFrame:(CGRect)frame withPhotoUrl:(NSString *)photoUrl{
  87. self = [super initWithFrame:frame];
  88. if (self) {
  89. //添加图片
  90. // SDWebImageManager *manager = [SDWebImageManager sharedManager];
  91. SDImageCache *manager = [SDImageCache sharedImageCache];
  92. NSURL *url;
  93. if (![photoUrl hasPrefix:@"http"]) {
  94. url = [NSURL fileURLWithPath:photoUrl];
  95. }else{
  96. url = [NSURL URLWithString:photoUrl];
  97. }
  98. [manager diskImageExistsWithKey:[url absoluteString] completion:^(BOOL isInCache) {
  99. if (!isInCache) {//没有缓存
  100. HUD = [MBProgressHUD showHUDAddedTo:self animated:YES];
  101. HUD.mode = MBProgressHUDModeDeterminate;
  102. if ([photoUrl rangeOfString:@".webp"].location != NSNotFound) {
  103. NSData *data = [NSData dataWithContentsOfURL:url];
  104. //UIImage *img = [UIImage sd_imageWithWebPData:data];//
  105. @try {
  106. UIImage *img = [UIImage imageWithData:data];
  107. self.webPimageView.frame=[self caculateOriginImageSizeWith:img];
  108. self.webPimageView.image = img;
  109. } @catch (NSException *exception) {
  110. } @finally {
  111. }
  112. [HUD hide:YES];
  113. }else {
  114. [self.imageView sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"ic-zanwu@3x"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
  115. HUD.progress = ((float)receivedSize)/expectedSize;
  116. } completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
  117. self.imageView.frame=[self caculateOriginImageSizeWith:image];
  118. NSLog(@"图片加载完成");
  119. if ([photoUrl rangeOfString:@".gif"].location != NSNotFound) {
  120. HUD = [MBProgressHUD showHUDAddedTo:self animated:YES];
  121. HUD.mode = MBProgressHUDModeDeterminate;
  122. [self loadAnimatedImageWithURL:url completion:^(FLAnimatedImage *animatedImage) {
  123. self.imageView.animatedImage = animatedImage;
  124. NSLog(@"图片加载完成");
  125. [HUD hide:YES];
  126. }];
  127. }
  128. if (!isInCache) {
  129. [HUD hide:YES];
  130. }
  131. }];
  132. }
  133. // [self.imageView sd_setImageWithPreviousCachedImageWithURL:url placeholderImage:[UIImage imageNamed:@"ic-zanwu@3x"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
  134. // HUD.progress = ((float)receivedSize)/expectedSize;
  135. // } completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
  136. //
  137. // }];
  138. }else{//直接取出缓存的图片,减少流量消耗
  139. UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:url.absoluteString];
  140. self.imageView.frame=[self caculateOriginImageSizeWith:cachedImage];
  141. self.imageView.image=cachedImage;
  142. if ([photoUrl rangeOfString:@".gif"].location != NSNotFound) {
  143. HUD = [MBProgressHUD showHUDAddedTo:self animated:YES];
  144. HUD.mode = MBProgressHUDModeDeterminate;
  145. [self loadAnimatedImageWithURL:[NSURL URLWithString:photoUrl] completion:^(FLAnimatedImage *animatedImage) {
  146. self.imageView.animatedImage = animatedImage;
  147. NSLog(@"图片加载完成");
  148. [HUD hide:YES];
  149. }];
  150. }
  151. }
  152. }];
  153. // [manager cachedImageExistsForURL:url completion:^(BOOL isInCache) {
  154. //
  155. // }];
  156. // BOOL isCached = [manager cachedImageExistsForURL:[NSURL URLWithString:photoUrl]];
  157. }
  158. return self;
  159. }
  160. - (void)loadAnimatedImageWithURL:(NSURL *const)url completion:(void (^)(FLAnimatedImage *animatedImage))completion
  161. {
  162. NSString *const filename = url.lastPathComponent;
  163. NSString *const diskPath = [dataFilePath stringByAppendingPathComponent:filename];
  164. NSData * __block animatedImageData = [[NSFileManager defaultManager] contentsAtPath:diskPath];
  165. FLAnimatedImage * __block animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:animatedImageData];
  166. if (animatedImage) {
  167. if (completion) {
  168. completion(animatedImage);
  169. }
  170. } else {
  171. [[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
  172. animatedImageData = data;
  173. animatedImage = [[FLAnimatedImage alloc] initWithAnimatedGIFData:animatedImageData];
  174. if (animatedImage) {
  175. if (completion) {
  176. dispatch_async(dispatch_get_main_queue(), ^{
  177. completion(animatedImage);
  178. });
  179. }
  180. [data writeToFile:diskPath atomically:YES];
  181. }
  182. }] resume];
  183. }
  184. }
  185. -(id)initWithFrame:(CGRect)frame withPhotoImage:(UIImage *)image{
  186. self = [super initWithFrame:frame];
  187. if (self) {
  188. //添加图片
  189. self.imageView.frame=[self caculateOriginImageSizeWith:image];
  190. [self.imageView setImage:image];
  191. }
  192. return self;
  193. }
  194. #pragma mark - UIScrollViewDelegate
  195. /**scroll view处理缩放和平移手势,必须需要实现委托下面两个方法,另外 maximumZoomScale和minimumZoomScale两个属性要不一样*/
  196. //1.返回要缩放的图片
  197. -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
  198. return self.imageView;
  199. }
  200. //让图片保持在屏幕中央,防止图片放大时,位置出现跑偏
  201. - (void)scrollViewDidZoom:(UIScrollView *)scrollView{
  202. CGFloat offsetX = (_scrollView.bounds.size.width > _scrollView.contentSize.width)?(_scrollView.bounds.size.width - _scrollView.contentSize.width) * 0.5 : 0.0;
  203. CGFloat offsetY = (_scrollView.bounds.size.height > _scrollView.contentSize.height)?
  204. (_scrollView.bounds.size.height - _scrollView.contentSize.height) * 0.5 : 0.0;
  205. self.imageView.center = CGPointMake(_scrollView.contentSize.width * 0.5 + offsetX,_scrollView.contentSize.height * 0.5 + offsetY);
  206. }
  207. //2.重新确定缩放完后的缩放倍数
  208. -(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{
  209. [scrollView setZoomScale:scale+0.01 animated:NO];
  210. [scrollView setZoomScale:scale animated:NO];
  211. }
  212. #pragma mark - 图片的点击,touch事件
  213. //单击
  214. -(void)handleSingleTap:(UITapGestureRecognizer *)gestureRecognizer{
  215. if (gestureRecognizer.numberOfTapsRequired == 1) {
  216. [self.delegate tapHiddenPhotoView];
  217. }
  218. }
  219. // 长按
  220. - (void)longPress:(UILongPressGestureRecognizer *)gestureRecognizer {
  221. if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
  222. if ([self.delegate respondsToSelector:@selector(longPressPhotoView:)]) {
  223. [self.delegate longPressPhotoView:self.imageView.image];
  224. }
  225. }
  226. }
  227. //双击
  228. -(void)handleDoubleTap:(UITapGestureRecognizer *)gestureRecognizer{
  229. if (gestureRecognizer.numberOfTapsRequired == 2) {
  230. if(_scrollView.zoomScale == 1){
  231. float newScale = [_scrollView zoomScale] *2;
  232. CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
  233. [_scrollView zoomToRect:zoomRect animated:YES];
  234. }else{
  235. float newScale = [_scrollView zoomScale]/2;
  236. CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
  237. [_scrollView zoomToRect:zoomRect animated:YES];
  238. }
  239. }
  240. }
  241. //2手指操作
  242. -(void)handleTwoFingerTap:(UITapGestureRecognizer *)gestureRecongnizer{
  243. // float newScale = [_scrollView zoomScale]/2;
  244. // CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecongnizer locationInView:gestureRecongnizer.view]];
  245. // [_scrollView zoomToRect:zoomRect animated:YES];
  246. }
  247. #pragma mark - 缩放大小获取方法
  248. -(CGRect)zoomRectForScale:(CGFloat)scale withCenter:(CGPoint)center{
  249. CGRect zoomRect;
  250. //大小
  251. zoomRect.size.height = [_scrollView frame].size.height/scale;
  252. zoomRect.size.width = [_scrollView frame].size.width/scale;
  253. //原点
  254. zoomRect.origin.x = center.x - zoomRect.size.width/2;
  255. zoomRect.origin.y = center.y - zoomRect.size.height/2;
  256. return zoomRect;
  257. }
  258. #pragma mark - 懒加载
  259. -(UIScrollView *)scrollView{
  260. if (_scrollView==nil) {
  261. _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
  262. _scrollView.delegate = self;
  263. _scrollView.minimumZoomScale = 1;
  264. _scrollView.maximumZoomScale = 3;
  265. _scrollView.showsHorizontalScrollIndicator = NO;
  266. _scrollView.showsVerticalScrollIndicator = NO;
  267. [_scrollView setZoomScale:1];
  268. //添加scrollView
  269. [self addSubview:_scrollView];
  270. }
  271. return _scrollView;
  272. }
  273. -(UIImageView *)webPimageView{
  274. if (_webPimageView==nil) {
  275. _webPimageView = [[UIImageView alloc] init];
  276. _webPimageView.contentMode = UIViewContentModeScaleAspectFit;
  277. _webPimageView.userInteractionEnabled=YES;
  278. //添加手势
  279. UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
  280. UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
  281. UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)];
  282. UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
  283. singleTap.numberOfTapsRequired = 1;
  284. singleTap.numberOfTouchesRequired = 1;
  285. doubleTap.numberOfTapsRequired = 2;//需要点两下
  286. twoFingerTap.numberOfTouchesRequired = 2;//需要两个手指touch
  287. [_webPimageView addGestureRecognizer:singleTap];
  288. [_webPimageView addGestureRecognizer:doubleTap];
  289. [_webPimageView addGestureRecognizer:twoFingerTap];
  290. [_webPimageView addGestureRecognizer:longPress];
  291. [singleTap requireGestureRecognizerToFail:doubleTap];//如果双击了,则不响应单击事件
  292. [self.scrollView addSubview:_webPimageView];
  293. }
  294. return _webPimageView;
  295. }
  296. -(UIImageView *)imageView{
  297. if (_imageView==nil) {
  298. _imageView = [[FLAnimatedImageView alloc] init];
  299. _imageView.contentMode = UIViewContentModeScaleAspectFit;
  300. _imageView.userInteractionEnabled=YES;
  301. //添加手势
  302. UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
  303. UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
  304. UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)];
  305. UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
  306. singleTap.numberOfTapsRequired = 1;
  307. singleTap.numberOfTouchesRequired = 1;
  308. doubleTap.numberOfTapsRequired = 2;//需要点两下
  309. twoFingerTap.numberOfTouchesRequired = 2;//需要两个手指touch
  310. [_imageView addGestureRecognizer:singleTap];
  311. [_imageView addGestureRecognizer:doubleTap];
  312. [_imageView addGestureRecognizer:twoFingerTap];
  313. [_imageView addGestureRecognizer:longPress];
  314. [singleTap requireGestureRecognizerToFail:doubleTap];//如果双击了,则不响应单击事件
  315. [self.scrollView addSubview:_imageView];
  316. }
  317. return _imageView;
  318. }
  319. #pragma mark - 计算图片原始高度,用于高度自适应
  320. -(CGRect)caculateOriginImageSizeWith:(UIImage *)image{
  321. CGFloat originImageHeight=[self imageCompressForWidth:image targetWidth:JX_SCREEN_WIDTH].size.height;
  322. if (originImageHeight>=JX_SCREEN_HEIGHT) {
  323. originImageHeight=JX_SCREEN_HEIGHT;
  324. }
  325. CGRect frame=CGRectMake(0, (JX_SCREEN_HEIGHT-originImageHeight)*0.5, JX_SCREEN_WIDTH, originImageHeight);
  326. return frame;
  327. }
  328. /**指定宽度按比例缩放图片*/
  329. -(UIImage *) imageCompressForWidth:(UIImage *)sourceImage targetWidth:(CGFloat)defineWidth{
  330. UIImage *newImage = nil;
  331. CGSize imageSize = sourceImage.size;
  332. CGFloat width = imageSize.width;
  333. CGFloat height = imageSize.height;
  334. CGFloat targetWidth = defineWidth;
  335. CGFloat targetHeight = height / (width / targetWidth);
  336. CGSize size = CGSizeMake(targetWidth, targetHeight);
  337. CGFloat scaleFactor = 0.0;
  338. CGFloat scaledWidth = targetWidth;
  339. CGFloat scaledHeight = targetHeight;
  340. CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);
  341. if(CGSizeEqualToSize(imageSize, size) == NO){
  342. CGFloat widthFactor = targetWidth / width;
  343. CGFloat heightFactor = targetHeight / height;
  344. if(widthFactor > heightFactor){
  345. scaleFactor = widthFactor;
  346. }else{
  347. scaleFactor = heightFactor;
  348. }
  349. scaledWidth = width * scaleFactor;
  350. scaledHeight = height * scaleFactor;
  351. if(widthFactor > heightFactor){
  352. thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
  353. }else if(widthFactor < heightFactor){
  354. thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
  355. }
  356. }
  357. UIGraphicsBeginImageContext(size);
  358. CGRect thumbnailRect = CGRectZero;
  359. thumbnailRect.origin = thumbnailPoint;
  360. thumbnailRect.size.width = scaledWidth;
  361. thumbnailRect.size.height = scaledHeight;
  362. [sourceImage drawInRect:thumbnailRect];
  363. newImage = UIGraphicsGetImageFromCurrentImageContext();
  364. UIGraphicsEndImageContext();
  365. return newImage;
  366. }
  367. /*
  368. // Only override drawRect: if you perform custom drawing.
  369. // An empty implementation adversely affects performance during animation.
  370. - (void)drawRect:(CGRect)rect {
  371. // Drawing code
  372. }
  373. */
  374. @end