iOS - 第三方库 SAVideoRangeSlider 的代码学习记录

来源:互联网 发布:淘宝店需要购买软件吗 编辑:程序博客网 时间:2024/06/05 23:04

今天,工作当中用到了第三方代码SAVideoRangeSlider,现在特此记录一下学习的内容


整体来说这个代码还是比较简单的


这是结果:



下面是我对代码的注释理解

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. - (void)viewDidLoad  
  2. {  
  3.     [super viewDidLoad];  
  4.       
  5.     self.myActivityIndicator.hidden = YES;  
  6.       
  7.     //临时路径  
  8.     NSString *tempDir = NSTemporaryDirectory();  
  9.     self.tmpVideoPath = [tempDir stringByAppendingPathComponent:@"tmpMov.mov"];  
  10.       
  11.     //加载本地mov  
  12.     NSBundle *mainBundle = [NSBundle mainBundle];  
  13.     self.originalVideoPath = [mainBundle pathForResource@"thaiPhuketKaronBeach" ofType@"MOV"];  
  14.     NSURL *videoFileUrl = [NSURL fileURLWithPath:self.originalVideoPath];  
  15.       
  16.     //创建SAVideoRangeSlider  
  17.     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {  
  18.           
  19.         self.mySAVideoRangeSlider = [[SAVideoRangeSlider alloc] initWithFrame:CGRectMake(10200self.view.frame.size.width-2070) videoUrl:videoFileUrl ];  
  20.         [self.mySAVideoRangeSlider setPopoverBubbleSize:200 height:100];  
  21.           
  22.     } else {  
  23.           
  24.         self.mySAVideoRangeSlider = [[SAVideoRangeSlider alloc] initWithFrame:CGRectMake(10100self.view.frame.size.width-2050) videoUrl:videoFileUrl ];  
  25.           
  26.         //设置字体大小,泡泡大小  
  27.         self.mySAVideoRangeSlider.bubleText.font = [UIFont systemFontOfSize:12];  
  28.         [self.mySAVideoRangeSlider setPopoverBubbleSize:120 height:60];  
  29.           
  30.     }  
  31.       
  32.     // Yellow 设置颜色  
  33.     self.mySAVideoRangeSlider.topBorder.backgroundColor = [UIColor colorWithRed0.996 green0.951 blue0.502 alpha: 1];  
  34.     self.mySAVideoRangeSlider.bottomBorder.backgroundColor = [UIColor colorWithRed0.992 green0.902 blue0.004 alpha: 1];  
  35.       
  36.     //设置代理  
  37.     self.mySAVideoRangeSlider.delegate = self;  
  38.       
  39.     //加入视图  
  40.     [self.view addSubview:self.mySAVideoRangeSlider];  
  41. }  
  42.   
  43. - (void)didReceiveMemoryWarning  
  44. {  
  45.     [super didReceiveMemoryWarning];  
  46.     // Dispose of any resources that can be recreated.  
  47. }  
  48.   
  49.   
  50.   
  51. #pragma mark - IBAction  
  52. //播放视频  
  53. - (IBAction)showOriginalVideo:(id)sender {  
  54.       
  55.     [self playMovie:self.originalVideoPath];  
  56.       
  57. }  
  58.   
  59. //播放剪裁好的视频  
  60. - (IBAction)showTrimmedVideo:(UIButton *)sender {  
  61.       
  62.     //如果有 删除临时文件  
  63.     [self deleteTmpFile];  
  64.       
  65.     //把文件地址转为url  
  66.     NSURL *videoFileUrl = [NSURL fileURLWithPath:self.originalVideoPath];  
  67.       
  68.     //转为AVAsset资源对象  
  69.     AVAsset *anAsset = [[AVURLAsset alloc] initWithURL:videoFileUrl options:nil];  
  70.       
  71.       
  72.     NSArray *compatiblePresets = [AVAssetExportSession exportPresetsCompatibleWithAsset:anAsset];  
  73.       
  74.     if ([compatiblePresets containsObject:AVAssetExportPresetMediumQuality]) {  
  75.           
  76.         //创建一个输出  
  77.         self.exportSession = [[AVAssetExportSession alloc]  
  78.                               initWithAsset:anAsset presetName:AVAssetExportPresetPassthrough];  
  79.         // Implementation continues.  
  80.           
  81.         //设置url以及类型  
  82.         NSURL *furl = [NSURL fileURLWithPath:self.tmpVideoPath];  
  83.           
  84.         self.exportSession.outputURL = furl;  
  85.         self.exportSession.outputFileType = AVFileTypeQuickTimeMovie;  
  86.           
  87.         //设置剪裁时间  
  88.         CMTime start = CMTimeMakeWithSeconds(self.startTime, anAsset.duration.timescale);  
  89.         CMTime duration = CMTimeMakeWithSeconds(self.stopTime-self.startTime, anAsset.duration.timescale);  
  90.         CMTimeRange range = CMTimeRangeMake(start, duration);  
  91.         self.exportSession.timeRange = range;  
  92.           
  93.         self.trimBtn.hidden = YES;  
  94.         self.myActivityIndicator.hidden = NO;  
  95.         [self.myActivityIndicator startAnimating];  
  96.         [self.exportSession exportAsynchronouslyWithCompletionHandler:^{  
  97.               
  98.             switch ([self.exportSession status]) {  
  99.                 case AVAssetExportSessionStatusFailed:  
  100.                     NSLog(@"Export failed: %@", [[self.exportSession error] localizedDescription]);  
  101.                     break;  
  102.                 case AVAssetExportSessionStatusCancelled:  
  103.                     NSLog(@"Export canceled");  
  104.                     break;  
  105.                 default:  
  106.                     NSLog(@"NONE");  
  107.                     dispatch_async(dispatch_get_main_queue(), ^{  
  108.                         [self.myActivityIndicator stopAnimating];  
  109.                         self.myActivityIndicator.hidden = YES;  
  110.                         self.trimBtn.hidden = NO;  
  111.                         [self playMovie:self.tmpVideoPath];  
  112.                     });  
  113.                       
  114.                     break;  
  115.             }  
  116.         }];  
  117.           
  118.     }  
  119.       
  120. }  
  121.   
  122.   
  123. #pragma mark - Other  
  124. //如果有文件 删除临时文件  
  125. -(void)deleteTmpFile{  
  126.       
  127.     NSURL *url = [NSURL fileURLWithPath:self.tmpVideoPath];  
  128.     NSFileManager *fm = [NSFileManager defaultManager];  
  129.     BOOL exist = [fm fileExistsAtPath:url.path];  
  130.     NSError *err;  
  131.     if (exist) {  
  132.         [fm removeItemAtURL:url error:&err];  
  133.         NSLog(@"file deleted");  
  134.         if (err) {  
  135.             NSLog(@"file remove error, %@", err.localizedDescription );  
  136.         }  
  137.     } else {  
  138.         NSLog(@"no file by that name");  
  139.     }  
  140. }  
  141.   
  142.   
  143. -(void)playMovie: (NSString *) path{  
  144.     NSURL *url = [NSURL fileURLWithPath:path];  
  145.     MPMoviePlayerViewController *theMovie = [[MPMoviePlayerViewController alloc] initWithContentURL:url];  
  146.     [self presentMoviePlayerViewControllerAnimated:theMovie];  
  147.     theMovie.moviePlayer.movieSourceType = MPMovieSourceTypeFile;  
  148.     [theMovie.moviePlayer play];  
  149. }  
  150.   
  151.   
  152. #pragma mark - SAVideoRangeSliderDelegate  
  153.   
  154. - (void)videoRange:(SAVideoRangeSlider *)videoRange didChangeLeftPosition:(CGFloat)leftPosition rightPosition:(CGFloat)rightPosition  
  155. {  
  156.     self.startTime = leftPosition;  
  157.     self.stopTime = rightPosition;  
  158.     self.timeLabel.text = [NSString stringWithFormat:@"%f - %f", leftPosition, rightPosition];  
  159.   
  160. }  
  161.   
  162.   
  163. - (void)viewDidUnload {  
  164.     [self setMyActivityIndicator:nil];  
  165.     [self setTrimBtn:nil];  
  166.     [super viewDidUnload];  
  167. }  


下面是其内部代码,我修改了其中的一个bug

在此贴出部分,剩余的都可以自己理解了

SAVideoRangeSlider.h

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. @protocol SAVideoRangeSliderDelegate;  
  2.   
  3. @interface SAVideoRangeSlider : UIView  
  4.   
  5. @property (nonatomic, weak) id <SAVideoRangeSliderDelegate> delegate;   //代理  
  6. @property (nonatomic) CGFloat leftPosition;                             //左边位置  
  7. @property (nonatomic) CGFloat rightPosition;                            //右边位置  
  8. @property (nonatomicstrongUILabel *bubleText;                       //泡泡上显示的label  
  9. @property (nonatomicstrongUIView *topBorder;                        //顶部view  
  10. @property (nonatomicstrongUIView *bottomBorder;                     //底部view  
  11. @property (nonatomic, assign) NSInteger maxGap;  
  12. @property (nonatomic, assign) NSInteger minGap;  
  13.   
  14. //初始化方法  
  15. - (id)initWithFrame:(CGRect)frame videoUrl:(NSURL *)videoUrl;  
  16.   
  17. //设置泡泡的大小  
  18. - (void)setPopoverBubbleSize: (CGFloat) width height:(CGFloat)height;  
  19.   
  20. @end  
  21.   
  22. @protocol SAVideoRangeSliderDelegate <NSObject>  
  23.   
  24. @optional  
  25. //显示时间的代理  
  26. - (void)videoRange:(SAVideoRangeSlider *)videoRange didChangeLeftPosition:(CGFloat)leftPosition rightPosition:(CGFloat)rightPosition;  
  27.   
  28. //拖动结束后的代理  
  29. - (void)videoRange:(SAVideoRangeSlider *)videoRange didGestureStateEndedLeftPosition:(CGFloat)leftPosition rightPosition:(CGFloat)rightPosition;  
  30.   
  31. @end  

SAVideoRangeSlider.m

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #import "SAVideoRangeSlider.h"  
  2.   
  3. @interface SAVideoRangeSlider ()  
  4.   
  5. @property (nonatomicstrongAVAssetImageGenerator *imageGenerator;//获得Asset的图像缩略图,预览图  
  6. @property (nonatomicstrongUIView *bgView;  
  7. @property (nonatomicstrongUIView *centerView;  
  8. @property (nonatomicstrongNSURL *videoUrl;  
  9. @property (nonatomicstrongSASliderLeft *leftThumb;//左边框  
  10. @property (nonatomicstrongSASliderRight *rightThumb;//右边框  
  11. @property (nonatomic) CGFloat frame_width;  
  12. @property (nonatomic) Float64 durationSeconds;  
  13. @property (nonatomicstrongSAResizibleBubble *popoverBubble;//泡泡label  
  14.   
  15. @end  
  16.   
  17. @implementation SAVideoRangeSlider  
  18.   
  19.   
  20. #define SLIDER_BORDERS_SIZE 6.0f  
  21. #define BG_VIEW_BORDERS_SIZE 3.0f  
  22.   
  23.   
  24. /** 
  25.     初始化方法 
  26.     @param frame        slider的范围 
  27.     @param videoUrl     视频资源的url 
  28.     @returns            实例 
  29.  */  
  30. - (id)initWithFrame:(CGRect)frame videoUrl:(NSURL *)videoUrl  
  31. {  
  32.       
  33.     self = [super initWithFrame:frame];  
  34.     if (self) {  
  35.           
  36.         _frame_width = frame.size.width;  
  37.           
  38.         int thumbWidth = ceil(frame.size.width*0.05);//返回大于或者等于指定表达式的最小整数  
  39.           
  40.         //创建背景框  
  41.         _bgView = [[UIControl alloc] initWithFrame:CGRectMake(thumbWidth-BG_VIEW_BORDERS_SIZE, 0, frame.size.width-(thumbWidth*2)+BG_VIEW_BORDERS_SIZE*2, frame.size.height)];  
  42.         _bgView.layer.borderColor = [UIColor grayColor].CGColor;  
  43.         _bgView.layer.borderWidth = BG_VIEW_BORDERS_SIZE;  
  44.         [self addSubview:_bgView];  
  45.           
  46.         _videoUrl = videoUrl;  
  47.           
  48.         _topBorder = [[UIView alloc] initWithFrame:CGRectMake(00, frame.size.width, SLIDER_BORDERS_SIZE)];  
  49.         _topBorder.backgroundColor = [UIColor colorWithRed0.996 green0.951 blue0.502 alpha: 1];  
  50.         [self addSubview:_topBorder];  
  51.           
  52.           
  53.         _bottomBorder = [[UIView alloc] initWithFrame:CGRectMake(0, frame.size.height-SLIDER_BORDERS_SIZE, frame.size.width, SLIDER_BORDERS_SIZE)];  
  54.         _bottomBorder.backgroundColor = [UIColor colorWithRed0.992 green0.902 blue0.004 alpha: 1];  
  55.         [self addSubview:_bottomBorder];  
  56.           
  57.           
  58.         //创建一个左边拖动的View,解决按不到的问题,thumbWidth+10  
  59.         _leftThumb = [[SASliderLeft alloc] initWithFrame:CGRectMake(00, thumbWidth+10, frame.size.height)];  
  60.         _leftThumb.contentMode = UIViewContentModeLeft;  
  61.         _leftThumb.userInteractionEnabled = YES;  
  62.         _leftThumb.clipsToBounds = YES;  
  63.         _leftThumb.backgroundColor = [UIColor clearColor];  
  64.         _leftThumb.layer.borderWidth = 0;  
  65.         [self addSubview:_leftThumb];  
  66.           
  67.         //添加一个拖动手势  
  68.         UIPanGestureRecognizer *leftPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftPan:)];  
  69.         [_leftThumb addGestureRecognizer:leftPan];  
  70.           
  71.         //创建一个右边拖动的View,解决按不到的问题,thumbWidth+10  
  72.         _rightThumb = [[SASliderRight alloc] initWithFrame:CGRectMake(00, thumbWidth+10, frame.size.height)];  
  73.         _rightThumb.contentMode = UIViewContentModeRight;  
  74.         _rightThumb.userInteractionEnabled = YES;  
  75.         _rightThumb.clipsToBounds = YES;  
  76.         _rightThumb.backgroundColor = [UIColor clearColor];  
  77.         [self addSubview:_rightThumb];  
  78.           
  79.         UIPanGestureRecognizer *rightPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightPan:)];  
  80.         [_rightThumb addGestureRecognizer:rightPan];  
  81.           
  82.         //初始化左右的位置  
  83.         _rightPosition = frame.size.width;  
  84.         _leftPosition = 0;  
  85.           
  86.           
  87.         //创建中心的view,加入手势  
  88.         _centerView = [[UIView alloc] initWithFrame:CGRectMake(00, frame.size.width, frame.size.height)];  
  89.         _centerView.backgroundColor = [UIColor clearColor];  
  90.         [self addSubview:_centerView];  
  91.           
  92.         //加入手势  
  93.         UIPanGestureRecognizer *centerPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCenterPan:)];  
  94.         [_centerView addGestureRecognizer:centerPan];  
  95.           
  96.           
  97.         //创建泡泡label  
  98.         _popoverBubble = [[SAResizibleBubble alloc] initWithFrame:CGRectMake(0, -5010050)];  
  99.         _popoverBubble.alpha = 0;  
  100.         _popoverBubble.backgroundColor = [UIColor clearColor];  
  101.         [self addSubview:_popoverBubble];  
  102.           
  103.           
  104.         _bubleText = [[UILabel alloc] initWithFrame:_popoverBubble.frame];  
  105.         _bubleText.font = [UIFont boldSystemFontOfSize:20];  
  106.         _bubleText.backgroundColor = [UIColor clearColor];  
  107.         _bubleText.textColor = [UIColor blackColor];  
  108.         _bubleText.textAlignment = UITextAlignmentCenter;  
  109.           
  110.         [_popoverBubble addSubview:_bubleText];  
  111.           
  112.         [self getMovieFrame];  
  113.         [self setNeedsDisplay];  
  114.     }  
  115.       
  116.     return self;  
  117. }  
  118.   
  119.   
  120. - (id)initWithFrame:(CGRect)frame  
  121. {  
  122.     self = [super initWithFrame:frame];  
  123.     if (self) {  
  124.         // Initialization code  
  125.     }  
  126.     return self;  
  127. }  
  128.   
  129. //设置泡泡的大小  
  130. -(void)setPopoverBubbleSize: (CGFloat) width height:(CGFloat)height{  
  131.       
  132.     CGRect currentFrame = _popoverBubble.frame;  
  133.     currentFrame.size.width = width;  
  134.     currentFrame.size.height = height;  
  135.     currentFrame.origin.y = -height;  
  136.     _popoverBubble.frame = currentFrame;  
  137.       
  138.     currentFrame.origin.x = 0;  
  139.     currentFrame.origin.y = 0;  
  140.     _bubleText.frame = currentFrame;  
  141.       
  142. }  
  143.   
  144. //设置最大剪裁时间  
  145. -(void)setMaxGap:(NSInteger)maxGap{  
  146.     _leftPosition = 0;  
  147.     _rightPosition = _frame_width*maxGap/_durationSeconds;  
  148.     _maxGap = maxGap;  
  149. }  
  150.   
  151. //设置最小剪裁时间  
  152. -(void)setMinGap:(NSInteger)minGap{  
  153.     _leftPosition = 0;  
  154.     _rightPosition = _frame_width*minGap/_durationSeconds;  
  155.     _minGap = minGap;  
  156. }  
  157.   
  158. //通知界面刷新截选得时间  
  159. - (void)delegateNotification  
  160. {  
  161.     if ([_delegate respondsToSelector:@selector(videoRange:didChangeLeftPosition:rightPosition:)]){  
  162.         [_delegate videoRange:self didChangeLeftPosition:self.leftPosition rightPosition:self.rightPosition];  
  163.     }  
  164.       
  165. }  
  166.   
  167. #pragma mark - Gestures  
  168.   
  169. - (void)handleLeftPan:(UIPanGestureRecognizer *)gesture  
  170. {  
  171.     if (gesture.state == UIGestureRecognizerStateBegan || gesture.state == UIGestureRecognizerStateChanged) {  
  172.           
  173.         CGPoint translation = [gesture translationInView:self];//返回偏移量  
  174.           
  175.         _leftPosition += translation.x;  
  176.         if (_leftPosition < 0) {  
  177.             _leftPosition = 0;  
  178.         }  
  179.           
  180.         //判断可否移动  
  181.         if (  
  182.             (_rightPosition-_leftPosition <= _leftThumb.frame.size.width+_rightThumb.frame.size.width) ||  
  183.             ((self.maxGap > 0) && (self.rightPosition-self.leftPosition > self.maxGap)) ||  
  184.             ((self.minGap > 0) && (self.rightPosition-self.leftPosition < self.minGap))  
  185.             ){  
  186.             _leftPosition -= translation.x;  
  187.         }  
  188.           
  189.         //  注意一旦你完成上述的移动,将translation重置为0十分重要。否则translation每次都会叠加,很快你的view就会移除屏幕!  
  190.         [gesture setTranslation:CGPointZero inView:self];  
  191.           
  192.         [self setNeedsLayout];  
  193.           
  194.         [self delegateNotification];  
  195.           
  196.     }  
  197.       
  198.     _popoverBubble.alpha = 1;  
  199.       
  200.     [self setTimeLabel];  
  201.       
  202.     if (gesture.state == UIGestureRecognizerStateEnded){  
  203.         [self hideBubble:_popoverBubble];  
  204.     }  
  205. }  
  206.   
  207.   
  208. - (void)handleRightPan:(UIPanGestureRecognizer *)gesture  
  209. {  
  210.     if (gesture.state == UIGestureRecognizerStateBegan || gesture.state == UIGestureRecognizerStateChanged) {  
  211.           
  212.           
  213.         CGPoint translation = [gesture translationInView:self];  
  214.         _rightPosition += translation.x;  
  215.         if (_rightPosition < 0) {  
  216.             _rightPosition = 0;  
  217.         }  
  218.           
  219.         if (_rightPosition > _frame_width){  
  220.             _rightPosition = _frame_width;  
  221.         }  
  222.           
  223.         if (_rightPosition-_leftPosition <= 0){  
  224.             _rightPosition -= translation.x;  
  225.         }  
  226.           
  227.         if ((_rightPosition-_leftPosition <= _leftThumb.frame.size.width+_rightThumb.frame.size.width) ||  
  228.             ((self.maxGap > 0) && (self.rightPosition-self.leftPosition > self.maxGap)) ||  
  229.             ((self.minGap > 0) && (self.rightPosition-self.leftPosition < self.minGap))){  
  230.             _rightPosition -= translation.x;  
  231.         }  
  232.           
  233.           
  234.         [gesture setTranslation:CGPointZero inView:self];  
  235.           
  236.         [self setNeedsLayout];  
  237.           
  238.         [self delegateNotification];  
  239.           
  240.     }  
  241.       
  242.     _popoverBubble.alpha = 1;  
  243.       
  244.     [self setTimeLabel];  
  245.       
  246.       
  247.     if (gesture.state == UIGestureRecognizerStateEnded){  
  248.         [self hideBubble:_popoverBubble];  
  249.     }  
  250. }  
  251.   
  252.   
  253. - (void)handleCenterPan:(UIPanGestureRecognizer *)gesture  
  254. {  
  255.       
  256.     if (gesture.state == UIGestureRecognizerStateBegan || gesture.state == UIGestureRecognizerStateChanged) {  
  257.           
  258.         CGPoint translation = [gesture translationInView:self];  
  259.           
  260.         _leftPosition += translation.x;  
  261.         _rightPosition += translation.x;  
  262.           
  263.         if (_rightPosition > _frame_width || _leftPosition < 0){  
  264.             _leftPosition -= translation.x;  
  265.             _rightPosition -= translation.x;  
  266.         }  
  267.           
  268.           
  269.         [gesture setTranslation:CGPointZero inView:self];  
  270.           
  271.         [self setNeedsLayout];  
  272.           
  273.         [self delegateNotification];  
  274.           
  275.     }  
  276.       
  277.     _popoverBubble.alpha = 1;  
  278.       
  279.     [self setTimeLabel];  
  280.       
  281.     if (gesture.state == UIGestureRecognizerStateEnded){  
  282.         [self hideBubble:_popoverBubble];  
  283.           
  284.     }  
  285.       
  286. }  
  287.   
  288. //重绘整个截选框的位置  
  289. - (void)layoutSubviews  
  290. {  
  291.     CGFloat inset = _leftThumb.frame.size.width / 2;  
  292.       
  293.     _leftThumb.center = CGPointMake(_leftPosition+inset, _leftThumb.frame.size.height/2);  
  294.       
  295.     _rightThumb.center = CGPointMake(_rightPosition-inset, _rightThumb.frame.size.height/2);  
  296.       
  297.     _topBorder.frame = CGRectMake(_leftThumb.frame.origin.x + _leftThumb.frame.size.width0, _rightThumb.frame.origin.x - _leftThumb.frame.origin.x - _leftThumb.frame.size.width/2, SLIDER_BORDERS_SIZE);  
  298.       
  299.     _bottomBorder.frame = CGRectMake(_leftThumb.frame.origin.x + _leftThumb.frame.size.width, _bgView.frame.size.height-SLIDER_BORDERS_SIZE, _rightThumb.frame.origin.x - _leftThumb.frame.origin.x - _leftThumb.frame.size.width/2, SLIDER_BORDERS_SIZE);  
  300.       
  301.       
  302.     _centerView.frame = CGRectMake(_leftThumb.frame.origin.x + _leftThumb.frame.size.width, _centerView.frame.origin.y, _rightThumb.frame.origin.x - _leftThumb.frame.origin.x - _leftThumb.frame.size.width, _centerView.frame.size.height);  
  303.       
  304.       
  305.     CGRect frame = _popoverBubble.frame;  
  306.     frame.origin.x = _centerView.frame.origin.x+_centerView.frame.size.width/2-frame.size.width/2;  
  307.     _popoverBubble.frame = frame;  
  308. }  
  309.   
  310.   
  311.   
  312.   
  313. #pragma mark - Video  
  314.   
  315. -(void)getMovieFrame{  
  316.       
  317.     //得到url的资源,转为asset  
  318.     AVAsset *myAsset = [[AVURLAsset alloc] initWithURL:_videoUrl options:nil];  
  319.       
  320.     //初始化AVAssetImageGenerator  
  321.     self.imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:myAsset];  
  322.       
  323.     //定义最大尺寸  
  324.     if ([self isRetina]){  
  325.         self.imageGenerator.maximumSize = CGSizeMake(_bgView.frame.size.width*2, _bgView.frame.size.height*2);  
  326.     } else {  
  327.         self.imageGenerator.maximumSize = CGSizeMake(_bgView.frame.size.width, _bgView.frame.size.height);  
  328.     }  
  329.       
  330.     int picWidth = 49;  
  331.       
  332.     // First image  
  333.     //创建第一张预览图  
  334.     NSError *error;  
  335.     CMTime actualTime;  
  336.     CGImageRef halfWayImage = [self.imageGenerator copyCGImageAtTime:kCMTimeZero actualTime:&actualTime error:&error];  
  337.     if (halfWayImage != NULL) {  
  338.         UIImage *videoScreen;  
  339.         if ([self isRetina]){  
  340.             videoScreen = [[UIImage alloc] initWithCGImage:halfWayImage scale:2.0 orientation:UIImageOrientationUp];  
  341.         } else {  
  342.             videoScreen = [[UIImage alloc] initWithCGImage:halfWayImage];  
  343.         }  
  344.         UIImageView *tmp = [[UIImageView alloc] initWithImage:videoScreen];  
  345.         [_bgView addSubview:tmp];  
  346.           
  347.         //得到预览图的标准宽  
  348.         picWidth = tmp.frame.size.width;  
  349.         CGImageRelease(halfWayImage);  
  350.     }  
  351.       
  352.     //得到秒数  
  353.     _durationSeconds = CMTimeGetSeconds([myAsset duration]);  
  354.       
  355.     //通过view的宽得到预览图的张数  
  356.     int picsCnt = ceil(_bgView.frame.size.width / picWidth);  
  357.     NSLog(@"%d",picsCnt);  
  358.       
  359.     //创建一个可变数组  
  360.     NSMutableArray *allTimes = [[NSMutableArray alloc] init];  
  361.       
  362.     int time4Pic = 0;  
  363.       
  364.     //得到每张预览图应该有的CMTime  
  365.     for (int i=1; i<picsCnt; i++){  
  366.         time4Pic = i*picWidth;  
  367.           
  368.         CMTime timeFrame = CMTimeMakeWithSeconds(_durationSeconds/_bgView.frame.size.width*time4Pic, 600);  
  369.           
  370.         [allTimes addObject:[NSValue valueWithCMTime:timeFrame]];  
  371.     }  
  372.       
  373.     NSArray *times = allTimes;  
  374.       
  375.     __block int i = 1;  
  376.       
  377.     //根据CMTime 取出image  
  378.     [self.imageGenerator generateCGImagesAsynchronouslyForTimes:times  
  379.       completionHandler:^(CMTime requestedTime, CGImageRef image, CMTime actualTime,  
  380.                           AVAssetImageGeneratorResult result, NSError *error) {  
  381.             
  382.           if (result == AVAssetImageGeneratorSucceeded) {  
  383.   
  384.               UIImage *videoScreen;  
  385.               if ([self isRetina]){  
  386.                   videoScreen = [[UIImage alloc] initWithCGImage:image scale:2.0 orientation:UIImageOrientationUp];  
  387.               } else {  
  388.                   videoScreen = [[UIImage alloc] initWithCGImage:image];  
  389.               }  
  390.                 
  391.               //这里修改了预览图加载慢的问题,放到主线程加载  
  392.               dispatch_async(dispatch_get_main_queue(), ^{  
  393.                     
  394.                   UIImageView *tmp = [[UIImageView alloc] initWithImage:videoScreen];  
  395.                     
  396.                   int all = (i+1)*tmp.frame.size.width;  
  397.                     
  398.                   CGRect currentFrame = tmp.frame;  
  399.                   currentFrame.origin.x = i*currentFrame.size.width;  
  400.                     
  401.                   //如果最后一张图超出范围,缩小  
  402.                   if (all > _bgView.frame.size.width){  
  403.                       int delta = all - _bgView.frame.size.width;  
  404.                       currentFrame.size.width -= delta;  
  405.                   }  
  406.                   tmp.frame = currentFrame;  
  407.                   i++;  
  408.                     
  409.                   [_bgView addSubview:tmp];  
  410.                   
  411.               });  
  412.                 
  413.           }  
  414.             
  415.           if (result == AVAssetImageGeneratorFailed) {  
  416.               NSLog(@"Failed with error: %@", [error localizedDescription]);  
  417.           }  
  418.           if (result == AVAssetImageGeneratorCancelled) {  
  419.               NSLog(@"Canceled");  
  420.           }  
  421.       }];  
  422. }  
  423.   
  424.   
  425.   
  426.   
  427. #pragma mark - Properties  
  428. //返回左边时间范围  
  429. - (CGFloat)leftPosition  
  430. {  
  431.     return _leftPosition * _durationSeconds / _frame_width;  
  432. }  
  433.   
  434. //返回右边时间范围  
  435. - (CGFloat)rightPosition  
  436. {  
  437.     return _rightPosition * _durationSeconds / _frame_width;  
  438. }  
  439.   
  440. #pragma mark - Bubble  
  441.   
  442. //隐藏泡泡的方法  
  443. - (void)hideBubble:(UIView *)popover  
  444. {  
  445.     [UIView animateWithDuration:0.4  
  446.                           delay:0  
  447.                         options:UIViewAnimationCurveEaseIn | UIViewAnimationOptionAllowUserInteraction  
  448.                      animations:^(void) {  
  449.                            
  450.                          _popoverBubble.alpha = 1.0;//取消泡泡label的消失  
  451.                            
  452.                      }  
  453.                      completion:nil];  
  454.       
  455.     //通过代理显示在界面上label的时间位置  
  456.     if ([_delegate respondsToSelector:@selector(videoRange:didGestureStateEndedLeftPosition:rightPosition:)]){  
  457.         [_delegate videoRange:self didGestureStateEndedLeftPosition:self.leftPosition rightPosition:self.rightPosition];  
  458.           
  459.     }  
  460. }  
  461.   
  462. //刷新label的时间方法  
  463. -(void) setTimeLabel{  
  464.     self.bubleText.text = [self trimIntervalStr];  
  465. }  
  466.   
  467. //显示截取时间的秒数  
  468. -(NSString *)trimDurationStr{  
  469.     int delta = floor(self.rightPosition - self.leftPosition);  
  470.     return [NSString stringWithFormat:@"%d", delta];  
  471. }  
  472.   
  473. //获得时间  
  474. -(NSString *)trimIntervalStr{  
  475.       
  476.     NSString *from = [self timeToStr:self.leftPosition];  
  477.     NSString *to = [self timeToStr:self.rightPosition];  
  478.     return [NSString stringWithFormat:@"%@ - %@", from, to];  
  479. }  
  480.   
  481. #pragma mark - Helpers  
  482. //获得时间  
  483. - (NSString *)timeToStr:(CGFloat)time  
  484. {  
  485.     // time - seconds  
  486.     NSInteger min = floor(time / 60);  
  487.     NSInteger sec = floor(time - min * 60);  
  488.     NSString *minStr = [NSString stringWithFormat:min >= 10 ? @"%i" : @"0%i", min];  
  489.     NSString *secStr = [NSString stringWithFormat:sec >= 10 ? @"%i" : @"0%i", sec];  
  490.     return [NSString stringWithFormat:@"%@:%@", minStr, secStr];  
  491. }  
  492.   
  493. //是否是高清屏  
  494. -(BOOL)isRetina{  
  495.     return ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] &&  
  496.               
  497.             ([UIScreen mainScreen].scale == 2.0));  
  498. }  
  499.   
  500.   
  501. @end  

SAResizibleBubble.m


[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #import "SAResizibleBubble.h"  
  2.   
  3. @implementation SAResizibleBubble  
  4.   
  5. - (id)initWithFrame:(CGRect)frame  
  6. {  
  7.     self = [super initWithFrame:frame];  
  8.     if (self) {  
  9.         // Initialization code  
  10.     }  
  11.     return self;  
  12. }  
  13.   
  14.   
  15.   
  16. - (void)drawRect:(CGRect)rect  
  17. {  
  18.     //// General Declarations  
  19.       
  20.     //得到颜色空间  
  21.     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();  
  22.     CGContextRef context = UIGraphicsGetCurrentContext();  
  23.       
  24.     //// Color Declarations  
  25.       
  26.     //泡泡上面的颜色  
  27.     UIColor* bubbleGradientTop = [UIColor colorWithRed1 green0.939 blue0.743 alpha: 1];  
  28.   
  29.     //泡泡底部的颜色  
  30.     UIColor* bubbleGradientBottom = [UIColor colorWithRed1 green0.817 blue0.053 alpha: 1];  
  31.   
  32.     //高亮的颜色,背景阴影  
  33.     UIColor* bubbleHighlightColor = [UIColor colorWithRed1 green1 blue1 alpha: 1];  
  34.       
  35.     //画笔颜色,一圈阴影  
  36.     UIColor* bubbleStrokeColor = [UIColor colorWithRed0.173 green0.173 blue0.173 alpha: 1];  
  37.       
  38.     //// Gradient Declarations  
  39.     NSArray* bubbleGradientColors = [NSArray arrayWithObjects:  
  40.                                      (id)bubbleGradientTop.CGColor,  
  41.                                      (id)bubbleGradientBottom.CGColor, nil nil];  
  42.     //泡泡渐变的位置  
  43.     CGFloat bubbleGradientLocations[] = {01};  
  44.       
  45.     //创建一个渐变对象  
  46.     CGGradientRef bubbleGradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)bubbleGradientColors, bubbleGradientLocations);  
  47.       
  48.     //// Shadow Declarations  
  49.     UIColor* outerShadow = [UIColor blackColor];  
  50.     CGSize outerShadowOffset = CGSizeMake(0.16.1);  
  51.     CGFloat outerShadowBlurRadius = 13;  
  52.     UIColor* highlightShadow = bubbleHighlightColor;  
  53.     CGSize highlightShadowOffset = CGSizeMake(0.12.1);  
  54.     CGFloat highlightShadowBlurRadius = 0;  
  55.       
  56.     //// Frames  
  57.     CGRect bubbleFrame = self.bounds;  
  58.       
  59.     //// Subframes  
  60.     //箭头frame  
  61.     CGRect arrowFrame = CGRectMake(CGRectGetMinX(bubbleFrame) + floor((CGRectGetWidth(bubbleFrame) - 59) * 0.50462 + 0.5), CGRectGetMinY(bubbleFrame) + CGRectGetHeight(bubbleFrame) - 465946);  
  62.   
  63.       
  64.     //// Bubble Drawing  
  65.     //画泡泡  
  66.     UIBezierPath* bubblePath = [UIBezierPath bezierPath];  
  67.     [bubblePath moveToPoint: CGPointMake(CGRectGetMaxX(bubbleFrame) - 12, CGRectGetMinY(bubbleFrame) + 28.5)];  
  68.     [bubblePath addLineToPoint: CGPointMake(CGRectGetMaxX(bubbleFrame) - 12, CGRectGetMaxY(bubbleFrame) - 27.5)];  
  69.     [bubblePath addCurveToPoint: CGPointMake(CGRectGetMaxX(bubbleFrame) - 25, CGRectGetMaxY(bubbleFrame) - 14.5) controlPoint1: CGPointMake(CGRectGetMaxX(bubbleFrame) - 12, CGRectGetMaxY(bubbleFrame) - 20.32) controlPoint2: CGPointMake(CGRectGetMaxX(bubbleFrame) - 17.82, CGRectGetMaxY(bubbleFrame) - 14.5)];  
  70.     [bubblePath addLineToPoint: CGPointMake(CGRectGetMinX(arrowFrame) + 40.5, CGRectGetMaxY(arrowFrame) - 13.5)];  
  71.     [bubblePath addLineToPoint: CGPointMake(CGRectGetMinX(arrowFrame) + 29.5, CGRectGetMaxY(arrowFrame) - 0.5)];  
  72.     [bubblePath addLineToPoint: CGPointMake(CGRectGetMinX(arrowFrame) + 18.5, CGRectGetMaxY(arrowFrame) - 13.5)];  
  73.     [bubblePath addLineToPoint: CGPointMake(CGRectGetMinX(bubbleFrame) + 26.5, CGRectGetMaxY(bubbleFrame) - 14.5)];  
  74.     [bubblePath addCurveToPoint: CGPointMake(CGRectGetMinX(bubbleFrame) + 13.5, CGRectGetMaxY(bubbleFrame) - 27.5) controlPoint1: CGPointMake(CGRectGetMinX(bubbleFrame) + 19.32, CGRectGetMaxY(bubbleFrame) - 14.5) controlPoint2: CGPointMake(CGRectGetMinX(bubbleFrame) + 13.5, CGRectGetMaxY(bubbleFrame) - 20.32)];  
  75.     [bubblePath addLineToPoint: CGPointMake(CGRectGetMinX(bubbleFrame) + 13.5, CGRectGetMinY(bubbleFrame) + 28.5)];  
  76.     [bubblePath addCurveToPoint: CGPointMake(CGRectGetMinX(bubbleFrame) + 26.5, CGRectGetMinY(bubbleFrame) + 15.5) controlPoint1: CGPointMake(CGRectGetMinX(bubbleFrame) + 13.5, CGRectGetMinY(bubbleFrame) + 21.32) controlPoint2: CGPointMake(CGRectGetMinX(bubbleFrame) + 19.32, CGRectGetMinY(bubbleFrame) + 15.5)];  
  77.     [bubblePath addLineToPoint: CGPointMake(CGRectGetMaxX(bubbleFrame) - 25, CGRectGetMinY(bubbleFrame) + 15.5)];  
  78.     [bubblePath addCurveToPoint: CGPointMake(CGRectGetMaxX(bubbleFrame) - 12, CGRectGetMinY(bubbleFrame) + 28.5) controlPoint1: CGPointMake(CGRectGetMaxX(bubbleFrame) - 17.82, CGRectGetMinY(bubbleFrame) + 15.5) controlPoint2: CGPointMake(CGRectGetMaxX(bubbleFrame) - 12, CGRectGetMinY(bubbleFrame) + 21.32)];  
  79.     [bubblePath closePath];  
  80.       
  81.     CGContextSaveGState(context);  
  82.     CGContextSetShadowWithColor(context, outerShadowOffset, outerShadowBlurRadius, outerShadow.CGColor);  
  83.     CGContextBeginTransparencyLayer(context, NULL);  
  84.     [bubblePath addClip];  
  85.     CGRect bubbleBounds = CGPathGetPathBoundingBox(bubblePath.CGPath);  
  86.     CGContextDrawLinearGradient(context, bubbleGradient,  
  87.                                 CGPointMake(CGRectGetMidX(bubbleBounds), CGRectGetMinY(bubbleBounds)),  
  88.                                 CGPointMake(CGRectGetMidX(bubbleBounds), CGRectGetMaxY(bubbleBounds)),  
  89.                                 0);  
  90.     CGContextEndTransparencyLayer(context);  
  91.       
  92.     ////// Bubble Inner Shadow  
  93.     CGRect bubbleBorderRect = CGRectInset([bubblePath bounds], -highlightShadowBlurRadius, -highlightShadowBlurRadius);  
  94.     bubbleBorderRect = CGRectOffset(bubbleBorderRect, -highlightShadowOffset.width, -highlightShadowOffset.height);  
  95.     bubbleBorderRect = CGRectInset(CGRectUnion(bubbleBorderRect, [bubblePath bounds]), -1, -1);  
  96.       
  97.     UIBezierPath* bubbleNegativePath = [UIBezierPath bezierPathWithRect: bubbleBorderRect];  
  98.     [bubbleNegativePath appendPath: bubblePath];  
  99.     bubbleNegativePath.usesEvenOddFillRule = YES;  
  100.       
  101.     CGContextSaveGState(context);  
  102.     {  
  103.         CGFloat xOffset = highlightShadowOffset.width + round(bubbleBorderRect.size.width);  
  104.         CGFloat yOffset = highlightShadowOffset.height;  
  105.         CGContextSetShadowWithColor(context,  
  106.                                     CGSizeMake(xOffset + copysign(0.1, xOffset), yOffset + copysign(0.1, yOffset)),  
  107.                                     highlightShadowBlurRadius,  
  108.                                     highlightShadow.CGColor);  
  109.           
  110.         [bubblePath addClip];  
  111.         CGAffineTransform transform = CGAffineTransformMakeTranslation(-round(bubbleBorderRect.size.width), 0);  
  112.         [bubbleNegativePath applyTransform: transform];  
  113.         [[UIColor grayColor] setFill];  
  114.         [bubbleNegativePath fill];  
  115.     }  
  116.     CGContextRestoreGState(context);  
  117.       
  118.     CGContextRestoreGState(context);  
  119.       
  120.     [bubbleStrokeColor setStroke];  
  121.     bubblePath.lineWidth = 1;  
  122.     [bubblePath stroke];  
  123.       
  124.       
  125.     //// Cleanup  
  126.     CGGradientRelease(bubbleGradient);  
  127.     CGColorSpaceRelease(colorSpace);  
  128.       
  129.   
  130. }  
  131.   
  132. @end  


参考文章:UIBezierPath贝塞尔弧线常用方法记 UIBezierPath的基本使用 UIBezierPath类 CMTimeMake和CMTimeMakeWithSeconds 详解

0 0
原创粉丝点击