VideoRangeSlider.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. //
  2. // VideoRangeSlider.m
  3. // SAVideoRangeSliderExample
  4. //
  5. // Created by annidyfeng on 2017/4/18.
  6. // Copyright © 2017年 Andrei Solovjev. All rights reserved.
  7. //
  8. #import "VideoRangeSlider.h"
  9. #import "UIView+Additions.h"
  10. #import "UIView+CustomAutoLayout.h"
  11. #import "VideoRangeConst.h"
  12. @implementation VideoColorInfo
  13. @end
  14. @interface VideoRangeSlider()<RangeContentDelegate, UIScrollViewDelegate>
  15. @property BOOL disableSeek;
  16. @end
  17. @implementation VideoRangeSlider
  18. {
  19. NSMutableArray <VideoColorInfo *> *_colorInfos;
  20. ColorType _colorType;
  21. VideoColorInfo *_selectColorInfo;
  22. BOOL _startColor;
  23. }
  24. /*
  25. // Only override drawRect: if you perform custom drawing.
  26. // An empty implementation adversely affects performance during animation.
  27. - (void)drawRect:(CGRect)rect {
  28. // Drawing code
  29. }
  30. */
  31. - (instancetype)initWithFrame:(CGRect)frame
  32. {
  33. self = [super initWithFrame:frame];
  34. self.bgScrollView = ({
  35. UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectZero];
  36. [self addSubview:scroll];
  37. scroll.showsVerticalScrollIndicator = NO;
  38. scroll.showsHorizontalScrollIndicator = NO;
  39. scroll.scrollsToTop = NO;
  40. scroll.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  41. scroll.delegate = self;
  42. scroll;
  43. });
  44. self.middleLine = ({
  45. UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"mline.png"]];
  46. [self addSubview:imageView];
  47. imageView;
  48. });
  49. _colorInfos = [NSMutableArray array];
  50. return self;
  51. }
  52. - (void)layoutSubviews {
  53. [super layoutSubviews];
  54. self.bgScrollView.width = self.width;
  55. self.middleLine.center = self.bgScrollView.center = CGPointMake(self.width/2, self.height/2);
  56. self.middleLine.bounds = CGRectMake(0, 0, 0, self.height + 4);
  57. }
  58. - (void)setAppearanceConfig:(RangeContentConfig *)appearanceConfig
  59. {
  60. _appearanceConfig = appearanceConfig;
  61. }
  62. - (void)setImageList:(NSArray *)images
  63. {
  64. if (self.rangeContent) {
  65. [self.rangeContent removeFromSuperview];
  66. }
  67. if (_appearanceConfig) {
  68. self.rangeContent = [[RangeContent alloc] initWithImageList:images config:_appearanceConfig];
  69. } else {
  70. self.rangeContent = [[RangeContent alloc] initWithImageList:images];
  71. }
  72. self.rangeContent.delegate = self;
  73. [self.bgScrollView addSubview:self.rangeContent];
  74. self.bgScrollView.contentSize = [self.rangeContent intrinsicContentSize];
  75. self.bgScrollView.height = self.bgScrollView.contentSize.height;
  76. self.bgScrollView.contentInset = UIEdgeInsetsMake(0, self.width/2-self.rangeContent.pinWidth,
  77. 0, self.width/2-self.rangeContent.pinWidth);
  78. [self setCurrentPos:0];
  79. }
  80. - (void)updateImage:(UIImage *)image atIndex:(NSUInteger)index;
  81. {
  82. self.rangeContent.imageViewList[index].image = image;
  83. }
  84. - (void)setLeftPanHidden:(BOOL)isHidden
  85. {
  86. self.rangeContent.leftPin.hidden = isHidden;
  87. [self.rangeContent unpdateBorder];
  88. }
  89. - (void)setCenterPanHidden:(BOOL)isHidden
  90. {
  91. self.rangeContent.centerPin.hidden = isHidden;
  92. }
  93. - (void)setRightPanHidden:(BOOL)isHidden
  94. {
  95. self.rangeContent.rightPin.hidden = isHidden;
  96. [self.rangeContent unpdateBorder];
  97. }
  98. - (void)setLeftPanFrame:(CGFloat)time
  99. {
  100. _leftPos = time;
  101. self.rangeContent.leftPinCenterX = time / _durationMs * self.rangeContent.imageListWidth + self.rangeContent.pinWidth / 2;
  102. self.rangeContent.leftPin.center = CGPointMake(self.rangeContent.leftPinCenterX, self.rangeContent.leftPin.center.y);
  103. [self.rangeContent unpdateBorder];
  104. }
  105. - (void)setCenterPanFrame:(CGFloat)time
  106. {
  107. self.rangeContent.centerPinCenterX = time / _durationMs * self.rangeContent.imageListWidth + self.rangeContent.pinWidth;
  108. self.rangeContent.centerPin.center = CGPointMake(self.rangeContent.centerPinCenterX, self.rangeContent.centerPin.center.y);
  109. }
  110. - (void)setRightPanFrame:(CGFloat)time
  111. {
  112. _rightPos = time;
  113. self.rangeContent.rightPinCenterX = time / _durationMs * self.rangeContent.imageListWidth + self.rangeContent.pinWidth * 3 / 2;
  114. self.rangeContent.rightPin.center = CGPointMake(self.rangeContent.rightPinCenterX, self.rangeContent.rightPin.center.y);
  115. [self.rangeContent unpdateBorder];
  116. }
  117. - (void)setColorType:(ColorType)colorType
  118. {
  119. _colorType = colorType;
  120. if (_colorType == ColorType_Cut) {
  121. [self setLeftPanHidden:NO];
  122. [self setRightPanHidden:NO];
  123. }else{
  124. [self setLeftPanHidden:YES];
  125. [self setRightPanHidden:YES];
  126. [self setLeftPanFrame:0];
  127. [self setRightPanFrame:_rightPos];
  128. [self.rangeContent unpdateBorder];
  129. self.rangeContent.leftCover.hidden = YES;
  130. self.rangeContent.rightCover.hidden = YES;
  131. }
  132. for (VideoColorInfo *info in _colorInfos) {
  133. if (info.colorType != _colorType) {
  134. info.colorView.hidden = YES;
  135. }else{
  136. info.colorView.hidden = NO;
  137. }
  138. }
  139. }
  140. - (void)startColoration:(UIColor *)color alpha:(CGFloat)alpha
  141. {
  142. VideoColorInfo *info = [[VideoColorInfo alloc] init];
  143. info.colorView = [UIView new];
  144. info.colorView.backgroundColor = color;
  145. info.colorView.alpha = alpha;
  146. info.colorType = _colorType;
  147. [_colorInfos addObject:info];
  148. if (_colorType == ColorType_Effect) {
  149. info.startPos = _currentPos;
  150. }else{
  151. info.startPos = _leftPos;
  152. info.endPos = _rightPos;
  153. CGFloat x = self.rangeContent.pinWidth + _leftPos * self.rangeContent.imageListWidth / _durationMs;
  154. CGFloat width = fabs(_leftPos - _rightPos) * self.rangeContent.imageListWidth / _durationMs;
  155. info.colorView.frame = CGRectMake(x, 0, width, self.height);
  156. }
  157. UITapGestureRecognizer *tapGes = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
  158. [info.colorView addGestureRecognizer:tapGes];
  159. [self.rangeContent insertSubview:info.colorView belowSubview:self.rangeContent.leftPin];
  160. _startColor = YES;
  161. _selectColorInfo = info;
  162. }
  163. - (void)stopColoration
  164. {
  165. if (_colorType == ColorType_Effect) {
  166. VideoColorInfo *info = [_colorInfos lastObject];
  167. info.endPos = _currentPos;
  168. if (_currentPos + 1.5/ _fps >= _durationMs) {
  169. info.colorView.frame = [self coloredFrameForStartTime:info.startPos endTime:_durationMs];
  170. info.endPos = _durationMs;
  171. } else {
  172. info.endPos = _currentPos;
  173. }
  174. }
  175. _startColor = NO;
  176. }
  177. - (VideoColorInfo *)removeLastColoration:(ColorType)colorType;
  178. {
  179. for (NSInteger i = _colorInfos.count - 1; i >= 0; i --) {
  180. VideoColorInfo *info = (VideoColorInfo *)_colorInfos[i];
  181. if (info.colorType == colorType) {
  182. [info.colorView removeFromSuperview];
  183. [_colorInfos removeObject:info];
  184. return info;
  185. }
  186. }
  187. return nil;
  188. }
  189. - (void)removeColoration:(ColorType)colorType index:(NSInteger)index;
  190. {
  191. NSInteger count = 0;
  192. for (NSInteger i = 0; i < _colorInfos.count; i ++) {
  193. VideoColorInfo *info = (VideoColorInfo *)_colorInfos[i];
  194. if (info.colorType == colorType) {
  195. if (count == index) {
  196. [info.colorView removeFromSuperview];
  197. [_colorInfos removeObject:info];
  198. break;
  199. }
  200. count++;
  201. }
  202. }
  203. }
  204. - (CGRect)coloredFrameForStartTime:(float)start endTime:(float)end {
  205. CGFloat boxWidth = self.rangeContent.imageListWidth / _durationMs; // 帧的宽度
  206. return CGRectMake(self.rangeContent.pinWidth + start * boxWidth, 0, (end - start) * boxWidth, self.rangeContent.height);
  207. }
  208. - (void)setDurationMs:(CGFloat)durationMs {
  209. //duration 发生变化的时候,更新下特效所在的位置
  210. if (_durationMs != durationMs) {
  211. for (VideoColorInfo *info in _colorInfos) {
  212. CGFloat x = self.rangeContent.pinWidth + info.startPos * self.rangeContent.imageListWidth / durationMs;
  213. CGFloat width = fabs(info.endPos - info.startPos) * self.rangeContent.imageListWidth / durationMs;
  214. info.colorView.frame = CGRectMake(x, 0, width, self.height);
  215. }
  216. _durationMs = durationMs;
  217. }
  218. _leftPos = 0;
  219. _rightPos = _durationMs;
  220. [self setCurrentPos:_currentPos];
  221. _leftPos = self.durationMs * self.rangeContent.leftScale;
  222. _centerPos = self.durationMs * self.rangeContent.centerScale;
  223. _rightPos = self.durationMs * self.rangeContent.rightScale;
  224. }
  225. - (void)setCurrentPos:(CGFloat)currentPos
  226. {
  227. _currentPos = currentPos;
  228. if (_durationMs <= 0) {
  229. return;
  230. }
  231. CGFloat off = currentPos * self.rangeContent.imageListWidth / _durationMs;
  232. // off += self.rangeContent.leftPin.width;
  233. off -= self.bgScrollView.contentInset.left;
  234. self.disableSeek = YES;
  235. self.bgScrollView.contentOffset = CGPointMake(off, 0);
  236. VideoColorInfo *info = [_colorInfos lastObject];
  237. if (_colorType == ColorType_Effect && _startColor) {
  238. CGRect frame;
  239. if (_currentPos > info.startPos) {
  240. frame = [self coloredFrameForStartTime:info.startPos endTime:_currentPos];
  241. }else{
  242. frame = [self coloredFrameForStartTime:_currentPos endTime:info.startPos];
  243. }
  244. info.colorView.frame = frame;
  245. }
  246. self.disableSeek = NO;
  247. }
  248. - (void)handleTap:(UITapGestureRecognizer *)gesture
  249. {
  250. if (gesture.state == UIGestureRecognizerStateEnded) {
  251. CGPoint point = [gesture locationInView:self.rangeContent];
  252. CGFloat tapTime = (point.x - self.rangeContent.pinWidth) / self.rangeContent.imageListWidth * _durationMs;
  253. for (VideoColorInfo *info in _colorInfos) {
  254. if (info.colorType == _colorType && tapTime >= info.startPos && tapTime <= info.endPos) {
  255. _selectColorInfo = info;
  256. break;
  257. }
  258. }
  259. [self.delegate onVideoRangeTap:tapTime];
  260. }
  261. }
  262. #pragma mark TXVideoRangeContentDelegate
  263. - (void)onRangeLeftChanged:(RangeContent *)sender
  264. {
  265. _leftPos = self.durationMs * sender.leftScale;
  266. _rightPos = self.durationMs * sender.rightScale;
  267. [self.delegate onVideoRangeLeftChanged:self];
  268. if (_colorType == ColorType_Paster || _colorType == ColorType_Text) {
  269. CGFloat x = self.rangeContent.pinWidth + _leftPos * self.rangeContent.imageListWidth / _durationMs;
  270. CGFloat width = fabs(_leftPos - _rightPos) * self.rangeContent.imageListWidth / _durationMs;
  271. _selectColorInfo.startPos = _leftPos;
  272. _selectColorInfo.colorView.frame = CGRectMake(x, 0, width, self.height);
  273. }
  274. }
  275. - (void)onRangeLeftChangeEnded:(RangeContent *)sender
  276. {
  277. _leftPos = self.durationMs * sender.leftScale;
  278. _rightPos = self.durationMs * sender.rightScale;
  279. [self.delegate onVideoRangeLeftChangeEnded:self];
  280. }
  281. - (void)onRangeCenterChanged:(RangeContent *)sender
  282. {
  283. _leftPos = self.durationMs * sender.leftScale;
  284. _rightPos = self.durationMs * sender.rightScale;
  285. _centerPos = self.durationMs * sender.centerScale;
  286. [self.delegate onVideoRangeCenterChanged:self];
  287. }
  288. - (void)onRangeCenterChangeEnded:(RangeContent *)sender
  289. {
  290. _leftPos = self.durationMs * sender.leftScale;
  291. _rightPos = self.durationMs * sender.rightScale;
  292. _centerPos = self.durationMs * sender.centerScale;
  293. [self.delegate onVideoRangeCenterChangeEnded:self];
  294. }
  295. - (void)onRangeRightChanged:(RangeContent *)sender
  296. {
  297. _leftPos = self.durationMs * sender.leftScale;
  298. _rightPos = self.durationMs * sender.rightScale;
  299. [self.delegate onVideoRangeRightChanged:self];
  300. if (_colorType == ColorType_Paster || _colorType == ColorType_Text) {
  301. CGFloat x = self.rangeContent.pinWidth + _leftPos * self.rangeContent.imageListWidth / _durationMs;
  302. CGFloat width = fabs(_leftPos - _rightPos) * self.rangeContent.imageListWidth / _durationMs;
  303. _selectColorInfo.endPos = _rightPos;
  304. _selectColorInfo.colorView.frame = CGRectMake(x, 0, width, self.height);
  305. }
  306. }
  307. - (void)onRangeRightChangeEnded:(RangeContent *)sender
  308. {
  309. _leftPos = self.durationMs * sender.leftScale;
  310. _rightPos = self.durationMs * sender.rightScale;
  311. [self.delegate onVideoRangeRightChangeEnded:self];
  312. }
  313. - (void)onRangeLeftAndRightChanged:(RangeContent *)sender
  314. {
  315. _leftPos = self.durationMs * sender.leftScale;
  316. _rightPos = self.durationMs * sender.rightScale;
  317. }
  318. - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  319. {
  320. CGFloat pos = scrollView.contentOffset.x;
  321. pos += scrollView.contentInset.left;
  322. if (pos < 0) pos = 0;
  323. if (pos > self.rangeContent.imageListWidth) pos = self.rangeContent.imageListWidth;
  324. _currentPos = self.durationMs * pos/self.rangeContent.imageListWidth;
  325. if (self.disableSeek == NO) {
  326. NSLog(@"seek %f", _currentPos);
  327. [self.delegate onVideoRange:self seekToPos:self.currentPos];
  328. }
  329. }
  330. @end