縮放時(shí)間軸

項(xiàng)目需求:從云端獲取視頻片段箕速,app中以時(shí)間軸展示視頻片段列表端幼,可以縮放時(shí)間軸,同時(shí)視頻片段列表也需要跟隨縮放弧满,滑動(dòng)時(shí)間軸婆跑,如果選中視頻則選擇該視頻選中的時(shí)間點(diǎn)播放,如果沒有選中視頻庭呜,則找當(dāng)前選中的時(shí)間最近的視頻播放滑进,視頻每播放一秒,時(shí)間軸向下移動(dòng)一秒募谎,將視頻長度對(duì)應(yīng)的繪制在時(shí)間軸上扶关,每個(gè)視頻封面能否顯示需要判斷前后視頻片段對(duì)應(yīng)的時(shí)間軸高度等功能。需求還是比較難做数冬。
代碼中如有不明白的可以聯(lián)系我节槐,聯(lián)系方式qq734651142,標(biāo)明時(shí)間軸縮放拐纱。
運(yùn)行效果如下:
GIF較長铜异,選取了幾張圖片


IMG_5674.PNG
IMG_5673.PNG
IMG_5672.PNG

視頻效果鏈接:http://www.iqiyi.com/v_1d07stutamw.html?social_platform=link&p1=2_22_221&_frd=J%2FH%2F%2Bxnuk92DZdUPTIw1L8wWEjd%2FupuwdxEwWJi24hLF1wovQ40WwyyJ7%2F5ho%2FvHbnxyQ8HXIZ5JqdMIGEG7UwnKfnQMSsrvjvN01wvoR%2B8%3D

目前使用起來還是非常流暢,數(shù)據(jù)特別多會(huì)有些許卡頓秸架,小伙伴們有好的優(yōu)化方式歡迎聯(lián)系我揍庄。

比較重要的4個(gè)自定義控件
1、時(shí)間軸繪制控件 OU_CAMTimeAxisView
.h文件

#import <UIKit/UIKit.h>
#import "OU_CAMPlaybackModel.h"

NS_ASSUME_NONNULL_BEGIN

@interface OU_CAMTimeAxisView : UIView

@property (nonatomic, strong)NSArray <OU_CAMPlaybackModel *>* modelArray;

@property (nonatomic, strong)OU_CAMPlaybackModel* model;

@property (assign, nonatomic) CGFloat scale;

@end

NS_ASSUME_NONNULL_END

.m文件

#import "OU_CAMTimeAxisView.h"

#define SCALE1 0.5 //顯示每分鐘
#define SCALE2 0.1 //顯示十分鐘
#define SCALE3 0.05 //顯示半小時(shí)
@implementation OU_CAMTimeAxisView

- (void)drawRect:(CGRect)rect{
    if (self.tag == 101) {///組頭
         
         ///第一組組數(shù)組东抹。只用繪畫后2個(gè)刻度(當(dāng)前視圖內(nèi)和當(dāng)前視圖下)蚂子,即可保證所有的時(shí)間都能完整
         ///當(dāng)前組頭結(jié)束對(duì)應(yīng)的時(shí)間點(diǎn)
         NSInteger cellStartTime = self.model.modelArray.firstObject.timeStamp;
     
                  
         NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
         dict[NSFontAttributeName] = [UIFont systemFontOfSize:14.0];
         dict[NSForegroundColorAttributeName] = [UIColor grayColor];

         ///小時(shí)
         NSInteger hour = (86400 - cellStartTime)/3600;
         ///分鐘
         NSInteger mintues  = ((86400 - cellStartTime)%3600)/60 + 1;
       
        if (mintues >= 60) {
            mintues = mintues - 60;
            hour ++;
        }

         NSString * string = @"00:00";

         if (self.scale >= SCALE1) {
             ///相差的間隔(秒)
             NSInteger difference = hour*3600 + mintues * 60 - (86400 - cellStartTime);
         
             
             CGFloat y = self.frame.size.height - difference/3600.0 * CELLHEIGHT * self.scale;
             [self drawRuleWithY:y];
             
             ///刻度1
             if (hour < 10) {
                 if (mintues < 10) {
                     string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                 }else{
                     string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                 }
                 
             }else{
                 if (mintues < 10) {
                     string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                 }else{
                     string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                 }
             }
             
             [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             
             
             ///刻度2
             y = self.frame.size.height - (difference-60)/3600.0 * CELLHEIGHT * self.scale;
             [self drawRuleWithY:y];
             
             if (mintues == 0) {
                 mintues = 59;
                 hour --;
             }else{
                 mintues --;
             }
             if (hour <0) {
                 hour = 23;
             }
             
             if (hour < 10) {
                 if (mintues < 10) {
                     string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                 }else{
                     string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                 }
                 
             }else{
                 if (mintues < 10) {
                     string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                 }else{
                     string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                 }
             }
             [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             
         }else if(self.scale < SCALE1 && self.scale >= SCALE2){///顯示10分鐘,每分鐘只顯示刻度
             ///相差的間隔(秒)
             NSInteger difference = hour*3600 + mintues * 60 - (86400 - cellStartTime);
             
             CGFloat y = self.frame.size.height - difference/3600.0 * CELLHEIGHT * self.scale;
             
             if (mintues%10 == 0) {
                 [self drawLengthRuleWithY:y];
                 
                 if (hour < 10) {
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                     }
                      
                 }else{
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                     }
                 }
                 
                  
                 [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             }else{
                 [self drawRuleWithY:y];
             }
    

              ///刻度2
             y = self.frame.size.height - (difference - 60)/3600.0 * CELLHEIGHT * self.scale;
             
             
              
             if (mintues == 0) {
                 mintues = 59;
                 hour --;
             }else{
                  mintues --;
             }
             if (hour <0) {
                 hour = 23;
             }
             
             
             if (mintues%10 == 0) {
                 [self drawLengthRuleWithY:y];
                 
                 if (hour < 10) {
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                     }
                     
                 }else{
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                     }
                 }
                  
                 [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             }else{
                 [self drawRuleWithY:y];
             }
             
         }else if(self.scale <= SCALE2 && self.scale >= SCALE3){

             mintues = mintues/10*10+10;
             
             if (mintues >= 60) {
                 mintues = mintues - 30;
                 hour++;
             }
             
             
             NSInteger difference = hour*3600 + mintues * 60 - (86400 - cellStartTime);
             

             CGFloat y = self.frame.size.height - difference/3600.0 * CELLHEIGHT * self.scale;
             

             if (mintues%30 == 0) {
                 
                 [self drawLengthRuleWithY:y];

                 if (hour < 10) {
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                     }

                 }else{
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                     }
                 }
                 [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             }else{
                 [self drawRuleWithY:y];
             }

             ///刻度2
             y = self.frame.size.height + (600-difference)/3600.0 * CELLHEIGHT * self.scale;



             if (mintues < 10) {
                 mintues = mintues + 50;
                 hour --;
             }else{
                 mintues = mintues - 10;
             }
             
             if (hour <0) {
                 hour = 23;
             }

             if (mintues%30 == 0) {
                 [self drawLengthRuleWithY:y];

                 if (hour < 10) {
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                     }

                 }else{
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                         }
                     }

                     [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             }else{
                 [self drawRuleWithY:y];
             }
         }else{
             
             mintues = mintues/30*30+30;
             
             if (mintues >= 60) {
                 mintues = mintues - 60;
                 hour++;
             }

             NSInteger difference = hour*3600 + mintues * 60 - (86400 - cellStartTime);
                
             CGFloat y = self.frame.size.height - difference/3600.0 * CELLHEIGHT * self.scale;

             if (mintues%60 == 0) {
                 
                 [self drawLengthRuleWithY:y];

                 if (hour < 10) {
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                     }

                 }else{
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                     }
                 }

                 [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             }else{
                 [self drawRuleWithY:y];
             }

             ///刻度2
             y = self.frame.size.height + (1800 - difference)/3600.0 * CELLHEIGHT * self.scale;


             if (mintues == 30) {
                 mintues = 0;
             }else{
                 mintues = 30;
                 hour --;
             }
             if (hour <0) {
                 hour = 23;
             }

             if (mintues%60 == 0) {
                 [self drawLengthRuleWithY:y];

                 if (hour < 10) {
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                     }

                 }else{
                     if (mintues < 10) {
                         string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                     }else{
                         string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                         }
                     }

                 [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
             }else{
                 [self drawRuleWithY:y];
             }
         }
         
     }else if (self.tag == 100) {///組尾
        
        ///最后一組數(shù)組缭黔。只用繪畫前個(gè)刻度(當(dāng)前視圖內(nèi)和當(dāng)前視圖上)食茎,即可保證所有的時(shí)間都能完整
        ///當(dāng)前組尾開始對(duì)應(yīng)的時(shí)間點(diǎn)
        NSInteger cellStartTime = self.model.modelArray.firstObject.timeStamp + self.model.spanTime;
    
     
        NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
        dict[NSFontAttributeName] = [UIFont systemFontOfSize:14.0];
        dict[NSForegroundColorAttributeName] = [UIColor grayColor];

        ///小時(shí)
        NSInteger hour = (86400 - cellStartTime)/3600;
        ///分鐘
        NSInteger mintues  = ((86400 - cellStartTime)%3600)/60 + 1;

        NSString * string = @"00:00";

        if (self.scale >= SCALE1) {
            ///相差的間隔(秒)
            NSInteger difference = cellStartTime - cellStartTime/60*60;
        
            
            NSLog(@"相差的秒數(shù):%ld",difference);
            
            
            CGFloat y = -difference/3600.0 * CELLHEIGHT * self.scale;
            [self drawRuleWithY:y];
            
            ///刻度1
            if (hour < 10) {
                if (mintues < 10) {
                    string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                }else{
                    string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                }
                
            }else{
                if (mintues < 10) {
                    string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                }else{
                    string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                }
            }
            
            [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            
            
            ///刻度2
            y = (60 - difference)/3600.0 * CELLHEIGHT * self.scale;
            [self drawRuleWithY:y];
            
            if (mintues == 0) {
                mintues = 59;
                hour --;
            }else{
                mintues --;
            }
            if (hour <0) {
                hour = 23;
            }
            
            if (hour < 10) {
                if (mintues < 10) {
                    string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                }else{
                    string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                }
                
            }else{
                if (mintues < 10) {
                    string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                }else{
                    string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                }
            }
            [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            
        }else if(self.scale < SCALE1 && self.scale >= SCALE2){///顯示10分鐘,每分鐘只顯示刻度
            ///相差的間隔(秒)
            NSInteger difference = cellStartTime - cellStartTime/60*60;
            
            CGFloat y = -difference/3600.0 * CELLHEIGHT * self.scale;
            
            if (mintues%10 == 0) {
                [self drawLengthRuleWithY:y];
                
                if (hour < 10) {
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                    }
                     
                }else{
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                    }
                }
                
                 
                [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            }else{
                [self drawRuleWithY:y];
            }
   

             ///刻度2
            y = (60 - difference)/3600.0 * CELLHEIGHT * self.scale;
            
            
             
            if (mintues == 0) {
                mintues = 59;
                hour --;
            }else{
                 mintues --;
            }
            if (hour <0) {
                hour = 23;
            }
            
            
            if (mintues%10 == 0) {
                [self drawLengthRuleWithY:y];
                
                if (hour < 10) {
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                    }
                    
                }else{
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                    }
                }
                 
                [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            }else{
                [self drawRuleWithY:y];
            }
            
        }else if(self.scale <= SCALE2 && self.scale >= SCALE3){

            NSInteger difference = cellStartTime - cellStartTime/600*600;
                     
            CGFloat y = -difference/3600.0 * CELLHEIGHT * self.scale;
            
            mintues = mintues/10*10+10;
            

            if (mintues%30 == 0) {
                
                [self drawLengthRuleWithY:y];

                if (hour < 10) {
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                    }

                }else{
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                    }
                }
                [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            }else{
                [self drawRuleWithY:y];
            }

            ///刻度2
            y = (600-difference)/3600.0 * CELLHEIGHT * self.scale;



            if (mintues < 10) {
                mintues = mintues + 50;
                hour --;
            }else{
                mintues = mintues - 10;
            }
            
            if (hour <0) {
                hour = 23;
            }

            if (mintues%30 == 0) {
                [self drawLengthRuleWithY:y];

                if (hour < 10) {
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                    }

                }else{
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                        }
                    }

                    [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            }else{
                [self drawRuleWithY:y];
            }
        }else{

            NSInteger difference = cellStartTime - cellStartTime/1800*1800;
                  
            mintues = mintues/30*30+30;

            CGFloat y = -difference/3600.0 * CELLHEIGHT * self.scale;

            if (mintues%60 == 0) {
                
                [self drawLengthRuleWithY:y];

                if (hour < 10) {
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                    }

                }else{
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                    }
                }

                [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            }else{
                [self drawRuleWithY:y];
            }

            ///刻度2
            y = (1800 - difference)/3600.0 * CELLHEIGHT * self.scale;


            if (mintues == 30) {
                mintues = 0;
            }else{
                mintues = 30;
                hour --;
            }
            if (hour <0) {
                hour = 23;
            }

            if (mintues%60 == 0) {
                [self drawLengthRuleWithY:y];

                if (hour < 10) {
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                    }

                }else{
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                        }
                    }

                    [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
            }else{
                [self drawRuleWithY:y];
            }
        }
        
    }else{
        
        ///繪制時(shí)間軸馏谨,每1分鐘繪制長度為CELLHEIGHT别渔,根據(jù)數(shù)組內(nèi)容繪制
        NSInteger cellStartTime = self.model.modelArray.firstObject.timeStamp;
        
        for (int i = 0; i < self.model.modelArray.count; i++) {

            OU_CAMPlaybackModel * model = self.model.modelArray[I];
            
            ///開始時(shí)間(秒)
            NSInteger startTime = model.timeStamp + model.timeLength - cellStartTime;
            ///結(jié)束時(shí)間(秒)
            NSInteger stopTime = model.timeStamp - cellStartTime;

            ///開始時(shí)間點(diǎn)位
            CGFloat startPoint = startTime/3600.0 * CELLHEIGHT * self.scale;
            
            ///結(jié)束時(shí)間點(diǎn)位
            CGFloat stopPoint = stopTime/3600.0 * CELLHEIGHT * self.scale;
            
            [self drawLineWithForm:startPoint To:stopPoint];
      
        }
        
        ///繪制時(shí)間,計(jì)算當(dāng)前cell的刻度
        
        ///與0點(diǎn)的時(shí)間間隔,計(jì)算時(shí)間
        NSInteger zoneTime = (86400 - cellStartTime);
         
        ///當(dāng)前cell最大對(duì)應(yīng)的時(shí)間(單位:分)
        NSInteger maxTime = zoneTime/60;
        
        ///當(dāng)前cell最大分鐘刻度對(duì)應(yīng)該cell頂部的時(shí)間差值,上下限各往外+1钠糊,防止字體空間不夠造成的空缺(單位:秒)
        NSInteger difference = (86400 - (maxTime * 60)) - cellStartTime;
        
        ///當(dāng)前cell所包含的時(shí)間跨度,上下限各往外+1挟秤,防止字體空間不夠造成的空缺(單位:分)
        NSInteger span = (self.model.spanTime - difference)/60.0 + 1;
        
        
        NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];
        dict[NSFontAttributeName] = [UIFont systemFontOfSize:14.0];
        dict[NSForegroundColorAttributeName] = [UIColor grayColor];
        
        ///小時(shí)
        NSInteger hour = (maxTime * 60)/3600;
        ///分鐘
        NSInteger mintues  = ((maxTime * 60)%3600)/60;
        
        
        
        
        NSString * string = @"24:00";

        if (self.scale >= SCALE1) {
            for (int i = 0; i <= span; i++) {

                CGFloat y = (i*60.0+difference)/3600.0 * CELLHEIGHT * self.scale;
                [self drawRuleWithY:y];
                
                if (hour < 10) {
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"0%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"0%ld:%ld",hour,mintues];
                    }
                    
                }else{
                    if (mintues < 10) {
                        string = [NSString stringWithFormat:@"%ld:0%ld",hour,mintues];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld",hour,mintues];
                    }
                }
                [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
                
                if (mintues == 0) {
                    mintues = 59;
                    hour --;
                }else{
                    mintues --;
                }
                
            }
            
            ///計(jì)算第一個(gè)刻度與頂部的距離
       
        }else if(self.scale < SCALE1 && self.scale >= SCALE2){///顯示10分鐘,每分鐘只顯示刻度
            
            for (int i = 0; i <= span; i++) {

                CGFloat y = (i*60.0+difference)/3600.0 * CELLHEIGHT * self.scale;
                
                [self drawRuleWithY:y];
                
                
                if (mintues%10 == 0) {
                    [self drawLengthRuleWithY:y];
                    
                    
                    if (hour < 10) {
                        string = [NSString stringWithFormat:@"0%ld:%ld0",hour,mintues/10];
                    }else{
                        string = [NSString stringWithFormat:@"%ld:%ld0",hour,mintues/10];

                    }
                    [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
                }

                if (mintues == 0) {
                    mintues = 59;
                    hour --;
                }else{
                    mintues --;
                }
                
            }

       
        }else if(self.scale <= SCALE2 && self.scale >= SCALE3){///顯示半小時(shí)抄伍,每十分鐘只顯示刻度

            for (int i = 0; i <= span; i++) {

                if (mintues%10 == 0) {
                    
                    
                    CGFloat y = (i*60.0+difference)/3600.0 * CELLHEIGHT * self.scale;
                    
                    [self drawRuleWithY:y];
                    
                    
                    if (mintues%30 == 0) {
                        
                        [self drawLengthRuleWithY:y];
                        
                        if (hour < 10) {
                            string = [NSString stringWithFormat:@"0%ld:%ld0",hour,mintues/10];
                        }else{
                            string = [NSString stringWithFormat:@"%ld:%ld0",hour,mintues/10];

                        }
                        [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
                    }
                }


                if (mintues == 0) {
                    mintues = 59;
                    hour --;
                }else{
                    mintues --;
                }
                
            }
            
        }else{///顯示每小時(shí)艘刚,每半小時(shí)只顯示刻度
            
            for (int i = 0; i <= span; i++) {

                if (mintues%30 == 0) {
                    CGFloat y = (i*60.0+difference)/3600.0 * CELLHEIGHT * self.scale;
                    
                    [self drawRuleWithY:y];
                    if (mintues%60 == 0) {
                        
                        [self drawLengthRuleWithY:y];
                        
                        
                        
                        if (hour < 10) {
                            string = [NSString stringWithFormat:@"0%ld:00",hour];
                        }else{
                            string = [NSString stringWithFormat:@"%ld:00",hour];

                        }
                        
                        [string drawInRect:CGRectMake(5, y - 10, 45, 20) withAttributes:dict];//在矩形上畫字
                    }
                }


                if (mintues == 0) {
                    mintues = 59;
                    hour --;
                }else{
                    mintues --;
                }
                
            }

        }

    }
    

}

#pragma mark 使用默認(rèn)context進(jìn)行繪圖
- (void)drawLineWithForm:(CGFloat)form To:(CGFloat)to{
    
    UIColor *color = MainColor;
    [color set]; //設(shè)置線條顏色

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(58, form)];
    [path addLineToPoint:CGPointMake(58, to)];

    path.lineWidth = 4.0;
    path.lineCapStyle = kCGLineCapButt; //線條拐角
    path.lineJoinStyle = kCGLineJoinBevel; //終點(diǎn)處理

    [path stroke];
}

#pragma mark ===============繪制長刻度===============
- (void)drawLengthRuleWithY:(CGFloat)y{

    UIColor *color = [UIColor grayColor];
    [color set]; //設(shè)置線條顏色

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(41, y)];
    [path addLineToPoint:CGPointMake(56, y)];

    path.lineWidth = 1.0;
    path.lineCapStyle = kCGLineCapButt; //線條拐角
    path.lineJoinStyle = kCGLineJoinBevel; //終點(diǎn)處理

    [path stroke];
}

#pragma mark ===============繪制刻度===============
- (void)drawRuleWithY:(CGFloat)y{
        
    UIColor *color = [UIColor grayColor];
    [color set]; //設(shè)置線條顏色

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(46, y)];
    [path addLineToPoint:CGPointMake(56, y)];

    path.lineWidth = 1.0;
    path.lineCapStyle = kCGLineCapButt; //線條拐角
    path.lineJoinStyle = kCGLineJoinBevel; //終點(diǎn)處理

    [path stroke];
}


@end

上面的代碼涉及到視頻片段的模型,模型屬性如下:
///開始時(shí)間
@property (strong, nonatomic) NSString *startTime;
///結(jié)束時(shí)間
@property (strong, nonatomic) NSString *endTime;
///封面URL
@property (strong, nonatomic) NSString *coverURL;
///視頻URL
@property (strong, nonatomic) NSString *videoURL;

///日期 2020-08-25
@property (strong, nonatomic) NSString *dateString;
///時(shí)間 12:35
@property (strong, nonatomic) NSString *timeString;

///結(jié)束時(shí)間相對(duì)于當(dāng)天24時(shí)的時(shí)間戳 0~246060
@property (assign, nonatomic) NSInteger timeStamp;
///回放時(shí)長 單位為秒
@property (assign, nonatomic) NSInteger timeLength;
///動(dòng)態(tài)刷新記錄cell高度
@property (assign, nonatomic) CGFloat cellHeight;

///記錄該cell的跨度時(shí)間長度
@property (assign, nonatomic) NSInteger spanTime;
///動(dòng)態(tài)刷新截珍,記錄在同一個(gè)cell中的模型
@property (nonatomic, strong)NSMutableArray <OU_CAMPlaybackModel > modelArray;

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface OU_CAMPlaybackModel : NSObject

///開始時(shí)間
@property (strong, nonatomic) NSString *startTime;
///結(jié)束時(shí)間
@property (strong, nonatomic) NSString *endTime;
///封面URL
@property (strong, nonatomic) NSString *coverURL;
///視頻URL
@property (strong, nonatomic) NSString *videoURL;

///日期 2020-08-25
@property (strong, nonatomic) NSString *dateString;
///時(shí)間 12:35
@property (strong, nonatomic) NSString *timeString;


///結(jié)束時(shí)間相對(duì)于當(dāng)天24時(shí)的時(shí)間戳 0~24*60*60
@property (assign, nonatomic) NSInteger timeStamp;
///回放時(shí)長 單位為秒
@property (assign, nonatomic) NSInteger timeLength;
///動(dòng)態(tài)刷新記錄cell高度
@property (assign, nonatomic) CGFloat cellHeight;

///記錄該cell的跨度時(shí)間長度
@property (assign, nonatomic) NSInteger spanTime;
///動(dòng)態(tài)刷新攀甚,記錄在同一個(gè)cell中的模型
@property (nonatomic, strong)NSMutableArray <OU_CAMPlaybackModel *>* modelArray;

+ (NSMutableArray * )setPlaybackModelWithArray:(NSArray *)array;


@end

NS_ASSUME_NONNULL_END

2、列表頭部視圖 OU_CAMPlaybackHeaderView
.h文件

#import <UIKit/UIKit.h>
#import "OU_CAMTimeAxisView.h"
NS_ASSUME_NONNULL_BEGIN

@interface OU_CAMPlaybackHeaderView : UITableViewHeaderFooterView

@property (weak, nonatomic) IBOutlet OU_CAMTimeAxisView *timeAxisView;

@end

NS_ASSUME_NONNULL_END

.m文件中無內(nèi)容岗喉,xib中添加了時(shí)間軸繪制控件秋度,做的時(shí)候怎么方便怎么來,沒用代碼布局钱床。xib布局如下:


WechatIMG95.png

3荚斯、中間cell視圖 OU_CAMPlayBackTableViewCell

#import <UIKit/UIKit.h>
#import "OU_CAMTimeAxisView.h"

NS_ASSUME_NONNULL_BEGIN


@interface OU_CAMPlayBackTableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIImageView *contentImageView;

@property (weak, nonatomic) IBOutlet OU_CAMTimeAxisView *timeAxisView;

@end
NS_ASSUME_NONNULL_END

相對(duì)于頭部多了一個(gè)封面預(yù)覽圖
xib布局如下:


WechatIMG96.png

.m文件中無內(nèi)容

4、尾部視圖 OU_CAMPlaybackFooterView

#import <UIKit/UIKit.h>
#import "OU_CAMTimeAxisView.h"

NS_ASSUME_NONNULL_BEGIN

@interface OU_CAMPlaybackFooterView : UITableViewHeaderFooterView

@property (weak, nonatomic) IBOutlet UIImageView *contentImageView;

@property (weak, nonatomic) IBOutlet OU_CAMTimeAxisView *timeAxisView;

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentImageViewLayout_Top;


@end

NS_ASSUME_NONNULL_END

xib布局如下:


image.png

.m文件中無內(nèi)容

VC中調(diào)用

#import "OU_CAMPlayBackTableViewCell.h"
#import "OU_CAMPlaybackModel.h"
#import "OU_CAMTimeAxisView.h"
#import "OU_CAMPlaybackHeaderView.h"
#import "OU_CAMPlaybackFooterView.h"
#define MaxSCale 1.0  //最大縮放比例
#define MinScale 0.02  //最小縮放比例

- (void)viewDidLoad {
    [super viewDidLoad];
    self.OU_CAMPlaybackTableView.delegate = self;
    self.OU_CAMPlaybackTableView.dataSource = self;
    self.OU_CAMPlaybackTableView.separatorColor = [UIColor clearColor];
    
    self.OU_CAMPlaybackTableView.estimatedRowHeight = 0;
    self.OU_CAMPlaybackTableView.estimatedSectionHeaderHeight = 0;
    self.OU_CAMPlaybackTableView.estimatedSectionFooterHeight = 0;
    ///監(jiān)聽滑動(dòng)手勢(shì)
    [self.OU_CAMPlaybackTableView addObserver:self forKeyPath:@"panGestureRecognizer.state" options:NSKeyValueObservingOptionNew context:nil];
    ///計(jì)算滑動(dòng)區(qū)域
    ///如果劉海屏查牌,下盤的操作按鈕留出安全區(qū)域
    CGFloat Height = 64;
    if (@available(iOS 11.0, *)) {
        CGFloat a = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom;
        if (a>0) {
            Height = 44+44+34;
        }
    } else {
        
    }
    
    CGFloat contentBottom = SCREEN_H - (SCREEN_W / 16.0 * 9.0 + 60 + 80) - Height - 80;

    self.OU_CAMPlaybackTableView.contentInset = UIEdgeInsetsMake(-20, 0, contentBottom - 100, 0);
}
#pragma mark ===============加載數(shù)據(jù)(視頻回放)===============
- (void)OU_CAMLoadPlaybackData{
    /*
     ///開始時(shí)間
     @property (strong, nonatomic) NSString *startTime;
     ///結(jié)束時(shí)間
     @property (strong, nonatomic) NSString *endTime;
     ///封面URL
     @property (strong, nonatomic) NSString *coverURL;
     ///視頻URL
     @property (strong, nonatomic) NSString *videoURL;
     ///結(jié)束時(shí)間相對(duì)于當(dāng)天0時(shí)的時(shí)間戳 0~24*60*60
     @property (assign, nonatomic) NSInteger timeStamp;
     ///回放時(shí)長 單位為秒
     @property (assign, nonatomic) NSInteger timeLength;
     */
    NSArray * array = @[@{@"startTime":@"2020-08-14 15:29:29",@"endTime":@"2020-08-14 15:30:00",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/02/04/mp4/190204084208765161.mp4"},@{@"startTime":@"2020-08-14 14:27:10",@"endTime":@"2020-08-14 14:28:49",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/21/mp4/190321153853126488.mp4"},@{@"startTime":@"2020-08-14 14:24:06",@"endTime":@"2020-08-14 14:25:05",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/19/mp4/190319222227698228.mp4"},@{@"startTime":@"2020-08-14 14:10:05",@"endTime":@"2020-08-14 14:12:32",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/19/mp4/190319212559089721.mp4"},@{@"startTime":@"2020-08-14 13:59:22",@"endTime":@"2020-08-14 14:00:43",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/14/mp4/190314102306987969.mp4"},@{@"startTime":@"2020-08-14 13:25:05",@"endTime":@"2020-08-14 13:26:26",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/17/mp4/190317150237409904.mp4"},@{@"startTime":@"2020-08-14 13:11:05",@"endTime":@"2020-08-14 13:12:38",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/19/mp4/190319125415785691.mp4"},@{@"startTime":@"2020-08-14 12:55:25",@"endTime":@"2020-08-14 12:56:34",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/19/mp4/190319104618910544.mp4"},@{@"startTime":@"2020-08-14 11:31:05",@"endTime":@"2020-08-14 11:32:14",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/18/mp4/190318214226685784.mp4"},@{@"startTime":@"2020-08-14 00:27:15",@"endTime":@"2020-08-14 00:28:15",@"coverURL":@"1",@"videoURL":@"http://vfx.mtime.cn/Video/2019/03/18/mp4/190318231014076505.mp4"}];
    
    self.OU_CAMDataArray = [OU_CAMPlaybackModel setPlaybackModelWithArray:array];
    
    ///計(jì)算
    CGFloat height = 0;
    
    int index = 0;

    
    for (int i = 0; i < self.OU_CAMDataArray.count; i++) {
    
        OU_CAMPlaybackModel * model = self.OU_CAMDataArray[i];

        [model.modelArray removeAllObjects];

        if (i == 0) {
            [self.OU_CAMDataArr addObject:model];
            [model.modelArray addObject:model];
         
        }else{///計(jì)算與前面cell的時(shí)間戳事期,判斷是否可以顯示該model
            OU_CAMPlaybackModel * model1 = self.OU_CAMDataArray[index];

            height = (model.timeStamp - model1.timeStamp)/3600.0*CELLHEIGHT;
          
            if (height > 80) {///展示該cell,同時(shí)height置0
                 
                  [self.OU_CAMDataArr addObject:model];
                  [model.modelArray addObject:model];
                 
                  model1.cellHeight = height;
                  model1.spanTime = model.timeStamp - model1.timeStamp;
                  height = 0;
                  index = i;
                 
                if (i == self.OU_CAMDataArray.count-1) {
                    model.cellHeight = model.timeLength/3600.0*CELLHEIGHT;
                    model.spanTime = model.timeLength;
                }
                 
                 
            }else{
                [model1.modelArray addObject:model];
                if (i == self.OU_CAMDataArray.count-1) {
                    model1.cellHeight = height;
                     
                    model.spanTime = model.timeStamp + model.timeLength - model1.timeStamp;
                }
            }
   
        }

    }



    [self.OU_CAMPlaybackTableView reloadData];

    [self OU_CAMComputingTimeWithY:0];

    ///添加縮放手勢(shì)
    UIPinchGestureRecognizer * ges = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(OU_CAMPinch:)];

    [self.OU_CAMBgView addGestureRecognizer:ges];
    
}

#pragma mark ===============縮放手勢(shì)===============
// 處理縮放手勢(shì)
- (void)OU_CAMPinch:(UIPinchGestureRecognizer*)ges{
    
    if (self.OU_CAMDataArray.count == 0) {
        return;
    }
 
    CGFloat scale = ges.scale;
    //放大情況
    if(scale > 1.0){
        if(self.OU_CAMZoomScaling > MaxSCale) return;
    }
    //縮小情況
    if (scale < 1.0) {
        if (self.OU_CAMZoomScaling < MinScale) return;
    }
    
    if (ges.state == UIGestureRecognizerStateBegan) {
        ///刷新滾動(dòng)位置
        self.currentTime = self.pointY/CELLHEIGHT/self.OU_CAMZoomScaling;

    }if (ges.state == UIGestureRecognizerStateChanged) {
        

        self.OU_CAMZoomScaling = scale * self.OU_CAMZoomScaling;
        
        if (self.OU_CAMZoomScaling > MaxSCale) {
            self.OU_CAMZoomScaling = MaxSCale;
        }else if(self.OU_CAMZoomScaling < MinScale){
            self.OU_CAMZoomScaling = MinScale;
        }
    
        ///計(jì)算
               
       CGFloat height = 0;
       
       int index = 0;
       
       [self.OU_CAMDataArr removeAllObjects];
       for (int i = 0; i < self.OU_CAMDataArray.count; i++) {
           OU_CAMPlaybackModel * model = self.OU_CAMDataArray[i];
           if (i == 0) {
               [self.OU_CAMDataArr addObject:model];
               [model.modelArray addObject:model];
           }else{///計(jì)算與前面cell的時(shí)間戳,判斷是否可以顯示該model
               OU_CAMPlaybackModel * model1 = self.OU_CAMDataArray[index];

               height = (model.timeStamp - model1.timeStamp)/3600.0*CELLHEIGHT*self.OU_CAMZoomScaling;
            
               if (height > 80) {///展示該cell,同時(shí)height置0
                   [self.OU_CAMDataArr addObject:model];
                   [model.modelArray addObject:model];
                   
                   model1.cellHeight = height;
                   model1.spanTime = model.timeStamp - model1.timeStamp;
                   height = 0;
                   index = i;
                   
                   if (i == self.OU_CAMDataArray.count-1) {
                       model.cellHeight = model.timeLength/3600.0*CELLHEIGHT*self.OU_CAMZoomScaling;
                       model.spanTime = model.timeLength;
                   }
               }else{
                   [model1.modelArray addObject:model];
                   if (i == self.OU_CAMDataArray.count-1) {
                       model1.cellHeight = height;
                       
                       model.spanTime = model.timeStamp + model.timeLength - model1.timeStamp;
                   }
               }
           }
       }
        
        OU_CAMPlaybackModel * model = self.OU_CAMDataArray.lastObject;
        NSLog(@"spanTime == %ld",(long)model.spanTime);

        
       [self.OU_CAMPlaybackTableView reloadData];
        
        //時(shí)間轉(zhuǎn)換為距離
        [self.OU_CAMPlaybackTableView setContentOffset:CGPointMake(0, self.currentTime/3600.0*CELLHEIGHT*self.OU_CAMZoomScaling + 20) animated:NO];
        
        
        [self.OU_CAMPlaybackTableView reloadData];

    }else if(ges.state == UIGestureRecognizerStateEnded){

        [self OU_CAMCalculationFragment];
    }
}
    
#pragma mark ===============計(jì)算滑動(dòng)&縮放后選中的時(shí)間===============
- (void)OU_CAMComputingTimeWithY:(CGFloat)y{
    
    if (self.OU_CAMDataArray.count == 0) {
        return;
    }
    
    NSInteger seconds = y/self.OU_CAMZoomScaling;
    ///距離當(dāng)天0點(diǎn)對(duì)應(yīng)的秒數(shù)
    OU_CAMPlaybackModel * model = self.OU_CAMDataArray.firstObject;
    self.OU_CAMTimeStamp = (model.timeStamp + seconds);
    NSInteger timeStamp = 86400 - self.OU_CAMTimeStamp;
    if (!self.isTiming) {///當(dāng)計(jì)時(shí)器在計(jì)時(shí)時(shí)纸颜,不用滾動(dòng)更改
        [self OU_CAMSelectTimeUI:timeStamp];
    }
}

#pragma mark ===============選中的時(shí)間展示===============
- (void)OU_CAMSelectTimeUI:(NSInteger)timeStamp{
    
    NSInteger hour = timeStamp/3600;
    NSInteger mintues = (timeStamp%3600)/60;
    NSInteger sec = timeStamp%3600%60;


    if (hour < 0) {
        hour = 0;
    }
    if (hour > 23) {
        hour = 23;
    }
    
    if (mintues < 0) {
        mintues = 0;
    }
    if (mintues > 59) {
        mintues = 59;
    }
    
    if (sec < 0) {
        sec = 0;
    }
    if (sec > 59) {
        sec = 59;
    }
    
    
    
    if (hour < 10) {
       if (mintues < 10) {
           if (sec < 10) {
               self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"0%ld:0%ld:0%ld",(long)hour,(long)mintues,(long)sec];
           }else{
               self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"0%ld:0%ld:%ld",(long)hour,(long)mintues,(long)sec];
           }
           
       }else{
           if (sec < 10) {
                self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"0%ld:%ld:0%ld",(long)hour,(long)mintues,(long)sec];
            }else{
                self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"0%ld:%ld:%ld",(long)hour,(long)mintues,(long)sec];
            }
       }
    }else{
       if (mintues < 10) {
           if (sec < 10) {
                self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"%ld:0%ld:0%ld",(long)hour,(long)mintues,(long)sec];
            }else{
                self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"%ld:0%ld:%ld",(long)hour,(long)mintues,(long)sec];
            }
       }else{
           if (sec < 10) {
                self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"%ld:%ld:0%ld",(long)hour,(long)mintues,(long)sec];
            }else{
                self.OU_CAMSelectTimeLabel.text = [NSString stringWithFormat:@"%ld:%ld:%ld",(long)hour,(long)mintues,(long)sec];
            }
           
       }
    }
    
}

#pragma mark ===============添加回放計(jì)時(shí)器===============
- (void)OU_CAMAddBackplayTimer{
    
    [self OU_CAMRemoveBackplayTimer];
    
    if (!self.OU_CAMBackplayTimer) {
        
        self.isTiming = YES;
        
        self.OU_CAMBackplayTimer = [NSTimer timerWithTimeInterval:0.2 target:self selector:@selector(OU_CAMBackplayTimerClick) userInfo:nil repeats:YES];
        
        [[NSRunLoop mainRunLoop] addTimer:self.OU_CAMBackplayTimer forMode:NSDefaultRunLoopMode];
    }
    
    
}
#pragma mark ===============移除回放計(jì)時(shí)器===============
- (void)OU_CAMRemoveBackplayTimer{
    if (self.OU_CAMBackplayTimer) {
        
        self.isTiming = NO;
        
        [self.OU_CAMBackplayTimer invalidate];
        self.OU_CAMBackplayTimer = nil;
    }
    
}
#pragma mark ===============回放計(jì)時(shí)器事件===============
- (void)OU_CAMBackplayTimerClick{
    ///獲取當(dāng)前視頻播放的進(jìn)度(已經(jīng)播放時(shí)間)
    self.OU_CAMBackPlayTimeLength = round(self.playerItem.currentTime.value/self.playerItem.currentTime.timescale);
    
//    self.OU_CAMBackPlayStartTime - currentTime
    ///選中時(shí)間展示
    [self OU_CAMSelectTimeUI:86400 - self.OU_CAMBackPlayStartTime + self.OU_CAMBackPlayTimeLength];
    ///滾動(dòng)距離
    [self OU_CAMScrollDistanceWithTimeStamp:self.OU_CAMBackPlayStartTime - self.OU_CAMBackPlayTimeLength];

}


#pragma mark ===============縮放結(jié)束&滑動(dòng)停止后需要計(jì)算指定位播放===============
- (void)OU_CAMCalculationFragment{
    if (self.OU_CAMDataArray.count == 0) {
        return;
    }
    ///優(yōu)先判斷選中的時(shí)間是否正好處于回放片段內(nèi)兽泣,是則不用滾動(dòng)到最近的回放片段
    BOOL res = NO;
    int index = 0;
    for (int i = 0; i < self.OU_CAMDataArray.count ; i++) {
        OU_CAMPlaybackModel * model = self.OU_CAMDataArray[i];
        
        if (self.OU_CAMTimeStamp >= model.timeStamp && self.OU_CAMTimeStamp <= model.timeStamp + model.timeLength) {
            
            [self OU_CAMAddBackplayTimer];

            res = YES;

            ///需要設(shè)置的播放點(diǎn)
            self.OU_CAMBackPlayTimeLength = model.timeStamp + model.timeLength - self.OU_CAMTimeStamp;
            
            index = i;
            ///判斷是否是同一個(gè)播放源,是的話直接跳進(jìn)度胁孙,如果不是唠倦,則需要先切換播放源,然后跳進(jìn)度
            if (index == self.playIndex) {///相同播放源

            }else{///不同播放源
                self.playIndex = i;
                
                self.OU_CAMBackPlayStartTime = model.timeStamp + model.timeLength;
                
                [self OU_CAMStartBackplay];
            }
            
            //讓視頻從指定的CMTime對(duì)象處播放涮较。
            CMTime startTime = CMTimeMakeWithSeconds(self.OU_CAMBackPlayTimeLength, self.playerItem.currentTime.timescale);
            //讓視頻從指定處播放
            [self.player seekToTime:startTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
            
            [self.player play];
            if (@available(iOS 10.0, *)) {
                [self.player playImmediatelyAtRate:self.OU_CAMBackplaySpeed];
            } else {
                [self.player setRate:self.OU_CAMBackplaySpeed];
            }
            
            return;
         }
    }
    
    

    NSInteger seconds = 86400;
    index = 0;
    for (int i = 0; i < self.OU_CAMDataArray.count; i++) {
        OU_CAMPlaybackModel * model = self.OU_CAMDataArray[i];
        
        
        if (abs(self.OU_CAMTimeStamp - model.timeStamp - model.timeLength) < seconds) {
            seconds = abs(self.OU_CAMTimeStamp - model.timeStamp - model.timeLength);
            index = i;
        }
    }
    
    OU_CAMPlaybackModel * model1 = self.OU_CAMDataArray[index];
    

    ///選中播放的模型
    self.playIndex = index;
    ///該模型開始時(shí)間
    self.OU_CAMBackPlayStartTime = model1.timeStamp + model1.timeLength;
    self.OU_CAMBackPlayTimeLength = 0;
    
    
    
    [self OU_CAMStartBackplay];
    
    [self OU_CAMScrollDistanceWithTimeStamp:self.OU_CAMBackPlayStartTime];

}
#pragma mark ===============根據(jù)當(dāng)前時(shí)間戳計(jì)算滾動(dòng)距離===============
- (void)OU_CAMScrollDistanceWithTimeStamp:(NSInteger)timeStamp{
    
    ///使用第一個(gè)模型的結(jié)束時(shí)間時(shí)間戳差值來計(jì)算需要滾動(dòng)的距離
    OU_CAMPlaybackModel * model = self.OU_CAMDataArray.firstObject;
    
    timeStamp = timeStamp - model.timeStamp;
    
    
    [self.OU_CAMPlaybackTableView setContentOffset:CGPointMake(0, timeStamp * self.OU_CAMZoomScaling + 20) animated:YES];
    
}

#pragma mark ===============初始化播放器===============
- (void)OU_CAMStartBackplay{
    
    [self OU_CAMNotPlayBackStatus];
    
    self.OU_CAMPlayingback = NO;

    OU_CAMPlaybackModel * model1 = self.OU_CAMDataArray[self.playIndex];
    
    
    self.OU_CAMBackplayBgView.hidden = NO;
    ///移除監(jiān)聽
    [self.playerItem removeObserver:self forKeyPath:@"status"];
    

    NSURL*playUrl = [NSURL URLWithString:model1.videoURL];

    self.playerItem = [AVPlayerItem playerItemWithURL:playUrl];//如果要切換視頻需要調(diào)AVPlayer的replaceCurrentItemWithPlayerItem:方法

    if (self.player) {
        [self.player replaceCurrentItemWithPlayerItem:self.playerItem];
    }else{
        self.player = [AVPlayer playerWithPlayerItem:self.playerItem];

        self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];

        self.playerLayer.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width/16.0*9.0);//放置播放器的視圖
        
        [self.OU_CAMPlayerBgView.layer addSublayer:self.playerLayer];
        
    }


    ///播放完成通知
    [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(OU_CAMPlayerMovieFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:[self.player currentItem]];

    ///狀態(tài)通知
    [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    
    [self OU_CAMAddBackplayTimer];

}

#pragma mark ===============監(jiān)聽回調(diào)(手勢(shì)與播放器)===============
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context{
    if([object isKindOfClass:[AVPlayerItem class]]) {
        if([keyPath isEqualToString:@"status"]) {
            switch(_playerItem.status) {
                case AVPlayerItemStatusReadyToPlay://推薦將視頻播放放這里
                    [self OU_CAMStartPlayingBackStatus];
                break;
                case AVPlayerItemStatusUnknown:
                    NSLog(@"AVPlayerItemStatusUnknown");
                break;
                case AVPlayerItemStatusFailed:
                    NSLog(@"AVPlayerItemStatusFailed");
                break;
                default:
                break;
            }
        }
    }else{///監(jiān)聽滑動(dòng)手勢(shì)稠鼻,當(dāng)手勢(shì)滑動(dòng)時(shí),關(guān)閉計(jì)時(shí)器
        [self OU_CAMRemoveBackplayTimer];
    }
}

  
#pragma mark ===============播放結(jié)束通知===============
- (void)OU_CAMPlayerMovieFinish{
    [self OU_CAMNotPlayBackStatus];
    
    if (self.playIndex <= 0) {///全部播放完
        [self OU_CAMRemoveBackplayTimer];
    }else {
        self.playIndex--;
        
        OU_CAMPlaybackModel * model1 = self.OU_CAMDataArray[self.playIndex];
        ///該模型開始時(shí)間
        self.OU_CAMBackPlayStartTime = model1.timeStamp + model1.timeLength;
        self.OU_CAMBackPlayTimeLength = 0;
        [self OU_CAMScrollDistanceWithTimeStamp:self.OU_CAMBackPlayStartTime];
        
        [self OU_CAMStartBackplay];
        
    }
    
}
#pragma mark ===============開始播放更改UI狀態(tài)===============
- (void)OU_CAMStartPlayingBackStatus{
    
    [self.player play];
    
    self.OU_CAMPlayingback = YES;
    self.OU_CAMBackplaySpeedButton.alpha = 1.0;
    self.OU_CAMBackplayStartAndSuspendButton.alpha = 1.0;
    self.OU_CAMBackplaySpeedBgView.alpha = 1.0;
    
    self.OU_CAMBackplaySpeedButton.userInteractionEnabled = YES;
    self.OU_CAMBackplayStartAndSuspendButton.userInteractionEnabled = YES;
    
    [self.OU_CAMBackplayStartAndSuspendButton setImage:[UIImage imageNamed:@"播放_(tái)灰"] forState:UIControlStateNormal];
    
    if (@available(iOS 10.0, *)) {
        [self.player playImmediatelyAtRate:self.OU_CAMBackplaySpeed];
    } else {
        [self.player setRate:self.OU_CAMBackplaySpeed];
    }

}
#pragma mark ===============未開始播放狀態(tài)===============
- (void)OU_CAMNotPlayBackStatus{
    
    self.OU_CAMPlayingback = NO;
    self.OU_CAMBackplaySpeedButton.alpha = 0.4;
    self.OU_CAMBackplayStartAndSuspendButton.alpha = 0.4;
    self.OU_CAMBackplaySpeedBgView.alpha = 0.4;
    
    self.OU_CAMBackplaySpeedButton.userInteractionEnabled = NO;
    self.OU_CAMBackplayStartAndSuspendButton.userInteractionEnabled = NO;
    
    [self.OU_CAMBackplayStartAndSuspendButton setImage:[UIImage imageNamed:@"播放_(tái)黑"] forState:UIControlStateNormal];
}

#pragma mark ===============回放暫停與播放===============
- (IBAction)OU_CAMBackplayStartAndSuspend:(id)sender {
    
    if (self.OU_CAMPlayingback) {
        [self.player pause];
        [self.OU_CAMBackplayStartAndSuspendButton setImage:[UIImage imageNamed:@"播放_(tái)黑"] forState:UIControlStateNormal];
    }else{
        [self.player play];
        if (@available(iOS 10.0, *)) {
            [self.player playImmediatelyAtRate:self.OU_CAMBackplaySpeed];
        } else {
            [self.player setRate:self.OU_CAMBackplaySpeed];
        }
        [self.OU_CAMBackplayStartAndSuspendButton setImage:[UIImage imageNamed:@"播放_(tái)灰"] forState:UIControlStateNormal];
    }
    self.OU_CAMPlayingback = !self.OU_CAMPlayingback;
}
#pragma mark ===============回放速率調(diào)整===============
- (IBAction)OU_CAMBackplaySpeed:(id)sender {
    if (self.OU_CAMBackplaySpeed == 1) {
        self.OU_CAMBackplaySpeed = 4;
    }else if (self.OU_CAMBackplaySpeed == 4) {
        self.OU_CAMBackplaySpeed = 8;
    }else if (self.OU_CAMBackplaySpeed == 8) {
        self.OU_CAMBackplaySpeed = 16;
    }else{
        self.OU_CAMBackplaySpeed = 1;
    }
    
    [self.OU_CAMBackplaySpeedButton setTitle:[NSString stringWithFormat:@"X%ld",(long)self.OU_CAMBackplaySpeed] forState:UIControlStateNormal];
    

    if (@available(iOS 10.0, *)) {
        [self.player playImmediatelyAtRate:self.OU_CAMBackplaySpeed];
    } else {
        [self.player setRate:self.OU_CAMBackplaySpeed];
    }
}

#pragma mark ===============UITableViewDelegate&UITableViewDataSource===============
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return self.OU_CAMDataArr.count;
    
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    OU_CAMPlayBackTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"OU_CAMPlayBackTableViewCell"];
     
     if (!cell) {
         cell = [[[NSBundle mainBundle] loadNibNamed:@"OU_CAMPlayBackTableViewCell" owner:self options:0] objectAtIndex:0];
         cell.selectionStyle = UITableViewCellSelectionStyleNone;
         
         [cell setValue:@"OU_CAMPlayBackTableViewCell" forKey:@"reuseIdentifier"];
     }
    cell.timeAxisView.scale = self.OU_CAMZoomScaling;
    if (self.OU_CAMDataArr.count > indexPath.row) {
        OU_CAMPlaybackModel * model = self.OU_CAMDataArr[indexPath.row];
        cell.timeAxisView.model = model;
        [cell.contentImageView sd_setImageWithURL:[NSURL URLWithString:model.coverURL] placeholderImage:[UIImage imageNamed:@"logo"]];
    }
    
    [cell.timeAxisView setNeedsDisplay];

    return cell;
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

    OU_CAMPlaybackModel * model = self.OU_CAMDataArr[indexPath.row];
    
    return model.cellHeight;

}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    
}


- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    if (self.OU_CAMDataArr.count) {
        return 100;
    }
    return 0.001;
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
    OU_CAMPlaybackFooterView * view = (OU_CAMPlaybackFooterView *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:@"OU_CAMPlaybackFooterView"];
    if (!view) {
        view = [[NSBundle mainBundle] loadNibNamed:@"OU_CAMPlaybackFooterView" owner:self options:0].firstObject;
        view.timeAxisView.tag = 100;
    }
    
    view.timeAxisView.scale = self.OU_CAMZoomScaling;
    
    if (self.OU_CAMDataArr.count) {
        OU_CAMPlaybackModel * model = self.OU_CAMDataArr.lastObject;

        view.timeAxisView.model = model;
        [view.timeAxisView setNeedsDisplay];
        
        if (view.timeAxisView.model.cellHeight < 64) {///需要補(bǔ)全圖片
            view.contentImageView.hidden = NO;
            view.contentImageViewLayout_Top.constant = -view.timeAxisView.model.cellHeight;
        }else{
            view.contentImageView.hidden = YES;
        }
        
        [view.contentImageView sd_setImageWithURL:[NSURL URLWithString:model.coverURL] placeholderImage:[UIImage imageNamed:@"logo"]];
        
    }
    return view;
}


- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    if (self.OU_CAMDataArr.count) {
        return 100;
    }
    return 0.001;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    OU_CAMPlaybackHeaderView * view = (OU_CAMPlaybackHeaderView *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:@"OU_CAMPlaybackHeaderView"];
    if (!view) {
        view = [[NSBundle mainBundle] loadNibNamed:@"OU_CAMPlaybackHeaderView" owner:self options:0].firstObject;
        view.timeAxisView.tag = 101;
    }
    
    view.timeAxisView.scale = self.OU_CAMZoomScaling;
    
    if (self.OU_CAMDataArr.count) {
        view.timeAxisView.model = self.OU_CAMDataArr.firstObject;
        [view.timeAxisView setNeedsDisplay];

    }
    return view;
}
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    if (scrollView == self.OU_CAMPlaybackTableView) {
        [self OU_CAMComputingTimeWithY:scrollView.contentOffset.y - 20];
        
        self.pointY = self.OU_CAMPlaybackTableView.contentOffset.y - 20;

    }
}

- (void)scrollViewDidEndDecelerating:(nonnull UIScrollView *)scrollView{
    // 在這里面寫scrollView停止時(shí)需要做的事情
    if (scrollView == self.OU_CAMPlaybackTableView) {
        self.OU_CAMPlayOnlineBgView.hidden = NO;
        [self OU_CAMCalculationFragment];
    }
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    
    if (scrollView == self.OU_CAMPlaybackTableView) {
        if (!decelerate) {
            if (!scrollView.dragging && !scrollView.decelerating) {
                self.OU_CAMPlayOnlineBgView.hidden = NO;
                [self OU_CAMCalculationFragment];
            }
        }
    }

}

控制器中還有別的功能法希,我就沒有復(fù)制過來枷餐,代碼比較多靶瘸,不知道是否有復(fù)制完全苫亦,如果按照代碼來的無法編譯,可以聯(lián)系我怨咪。
最后屋剑,如果覺得有用,請(qǐng)給個(gè)Star诗眨,謝謝0ω摇!!
聯(lián)系方式 qq734651142巍膘,備注時(shí)間軸縮放厂财。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市峡懈,隨后出現(xiàn)的幾起案子璃饱,更是在濱河造成了極大的恐慌,老刑警劉巖肪康,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荚恶,死亡現(xiàn)場離奇詭異,居然都是意外死亡磷支,警方通過查閱死者的電腦和手機(jī)谒撼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雾狈,“玉大人廓潜,你說我怎么就攤上這事∩崎唬” “怎么了茉帅?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锭弊。 經(jīng)常有香客問我堪澎,道長,這世上最難降的妖魔是什么味滞? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任樱蛤,我火速辦了婚禮,結(jié)果婚禮上剑鞍,老公的妹妹穿的比我還像新娘昨凡。我一直安慰自己,他們只是感情好蚁署,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布便脊。 她就那樣靜靜地躺著,像睡著了一般光戈。 火紅的嫁衣襯著肌膚如雪哪痰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天久妆,我揣著相機(jī)與錄音晌杰,去河邊找鬼。 笑死筷弦,一個(gè)胖子當(dāng)著我的面吹牛肋演,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼爹殊,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼蜕乡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起梗夸,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤异希,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后绒瘦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體称簿,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年惰帽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了憨降。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡该酗,死狀恐怖授药,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情呜魄,我是刑警寧澤悔叽,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站爵嗅,受9級(jí)特大地震影響娇澎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睹晒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一趟庄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伪很,春花似錦戚啥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呆盖,卻和暖如春拖云,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背絮短。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工江兢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丁频。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親席里。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叔磷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容