WMZBannerOverLayout.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //
  2. // WMZBannerOverLayout.m
  3. // WMZBanner
  4. //
  5. // Created by wmz on 2019/12/18.
  6. // Copyright © 2019 wmz. All rights reserved.
  7. //
  8. #import "WMZBannerOverLayout.h"
  9. @interface WMZBannerOverLayout()
  10. @property(nonatomic,assign)CGPoint collectionContenOffset;
  11. @property(nonatomic,assign)CGSize collectionContenSize;
  12. @property(nonatomic,assign)CGFloat last;
  13. @property(nonatomic,assign)BOOL right;
  14. @end
  15. @implementation WMZBannerOverLayout
  16. - (instancetype)initConfigureWithModel:(WMZBannerParam *)param{
  17. if (self = [super init]) {
  18. self.param = param;
  19. self.collectionView.bounces = NO;
  20. }
  21. return self;
  22. }
  23. - (void)prepareLayout
  24. {
  25. [super prepareLayout];
  26. if (self.param.wCardOverLapCount<=0) {
  27. self.param.wCardOverLapCount = 4;
  28. }
  29. self.collectionView.pagingEnabled = YES;
  30. self.itemSize = self.param.wVertical?
  31. CGSizeMake(self.param.wItemSize.width , (self.param.wItemSize.height - (self.param.wCardOverLapCount - 1)*self.param.wLineSpacing)):
  32. CGSizeMake(self.param.wItemSize.width - (self.param.wCardOverLapCount - 1)*self.param.wLineSpacing, self.param.wItemSize.height);
  33. self.minimumInteritemSpacing = (self.param.wCardOverLapCount - 1)*self.param.wLineSpacing*2;
  34. self.minimumLineSpacing = (self.param.wCardOverLapCount - 1)*self.param.wLineSpacing*2;
  35. self.sectionInset = self.param.wSectionInset;
  36. self.scrollDirection = self.param.wVertical? UICollectionViewScrollDirectionVertical
  37. :UICollectionViewScrollDirectionHorizontal;
  38. }
  39. - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
  40. return [self cardOverLapTypeInRect:rect];
  41. }
  42. //卡片重叠
  43. - (NSArray<UICollectionViewLayoutAttributes *> *)cardOverLapTypeInRect:(CGRect)rect{
  44. NSInteger itemsCount = [self.collectionView numberOfItemsInSection:0];
  45. if (itemsCount <= 0) {
  46. return nil;
  47. }
  48. self.param.myCurrentPath = self.param.wVertical?
  49. MAX(floor ((int)self.collectionContenOffset.y / self.collectionContenSize.height ), 0):
  50. MAX(floor((int)self.collectionContenOffset.x / self.collectionContenSize.width ), 0);
  51. // self.param.overFactPath = self.param.wVertical?
  52. // MAX(ceil ((int)self.collectionContenOffset.y / self.collectionContenSize.height ), 0):
  53. // MAX(ceil((int)self.collectionContenOffset.x / self.collectionContenSize.width ), 0);
  54. NSInteger minVisibleIndex = MAX(self.param.myCurrentPath, 0);
  55. NSInteger contentOffset = self.param.wVertical?
  56. self.collectionContenOffset.y:self.collectionContenOffset.x;
  57. NSInteger collectionBounds = self.param.wVertical?
  58. self.collectionContenSize.height:self.collectionContenSize.width;
  59. CGFloat offset = contentOffset % collectionBounds;
  60. CGFloat offsetProgress = offset / (self.param.wVertical?self.collectionContenSize.height:self.collectionContenSize.width)*1.0f;
  61. NSInteger maxVisibleIndex = MAX(MIN(itemsCount - 1, self.param.myCurrentPath + self.param.wCardOverLapCount), minVisibleIndex);
  62. NSMutableArray *mArr = [[NSMutableArray alloc] init];
  63. for (NSInteger i = minVisibleIndex; i<=maxVisibleIndex; i++) {
  64. NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
  65. UICollectionViewLayoutAttributes *attributes = [[self layoutAttributesForItemAtIndexPath:indexPath] copy];
  66. NSInteger visibleIndex = MAX(indexPath.item - self.param.myCurrentPath + 1, 0);
  67. attributes.size = self.itemSize;
  68. CGFloat topCardMidX = self.param.wVertical?
  69. (self.collectionContenOffset.y + self.collectionContenSize.height / 2):
  70. (self.collectionContenOffset.x + self.collectionContenSize.width / 2);
  71. attributes.center = self.param.wVertical?
  72. CGPointMake(self.collectionContenSize.width/2, topCardMidX + self.param.wLineSpacing * (visibleIndex - 1)):
  73. CGPointMake(topCardMidX + self.param.wLineSpacing * (visibleIndex - 1), self.collectionContenSize.height/2);
  74. attributes.zIndex = 925457662 - visibleIndex;
  75. CGFloat scale = [self parallaxProgressForVisibleIndex:visibleIndex offsetProgress:offsetProgress minScale:self.param.wScaleFactor];
  76. attributes.transform = CGAffineTransformMakeScale(scale, scale);
  77. if (visibleIndex == 1) {
  78. if (self.param.wVertical) {
  79. if (minVisibleIndex != maxVisibleIndex) {
  80. if (self.collectionContenOffset.y >= 0) {
  81. attributes.center = CGPointMake(attributes.center.x, attributes.center.y - offset);
  82. }else{
  83. attributes.center = CGPointMake(attributes.center.x , attributes.center.y + attributes.size.height * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress);
  84. }
  85. }
  86. }else{
  87. if (minVisibleIndex != maxVisibleIndex) {
  88. if (self.collectionContenOffset.x >= 0) {
  89. attributes.center = CGPointMake(attributes.center.x - offset, attributes.center.y);
  90. }else{
  91. attributes.center = CGPointMake(attributes.center.x + attributes.size.width * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress, attributes.center.y);
  92. }
  93. }
  94. }
  95. if (self.param.wCardOverAlphaOpen) {
  96. attributes.alpha = MAX(1-offsetProgress, MAX(self.param.wCardOverMinAlpha, 0));
  97. }
  98. }else if (visibleIndex == self.param.wCardOverLapCount + 1){
  99. attributes.center = self.param.wVertical?
  100. CGPointMake(attributes.center.x, attributes.center.y + attributes.size.height * (1 - scale)/2 - self.param.wLineSpacing):
  101. CGPointMake(attributes.center.x + attributes.size.width * (1 - scale)/2 - self.param.wLineSpacing, attributes.center.y);
  102. if (self.param.wCardOverAlphaOpen) {
  103. attributes.alpha = MAX(offsetProgress, MAX(self.param.wCardOverMinAlpha, 0));
  104. }
  105. }else{
  106. attributes.center = self.param.wVertical?
  107. CGPointMake(attributes.center.x , attributes.center.y + attributes.size.height * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress):
  108. CGPointMake(attributes.center.x + attributes.size.width * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress, attributes.center.y);
  109. if (self.param.wCardOverAlphaOpen) {
  110. attributes.alpha = MAX(offsetProgress, MAX(self.param.wCardOverMinAlpha*2, 0));
  111. }
  112. }
  113. [mArr addObject:attributes];
  114. }
  115. return mArr;
  116. }
  117. - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
  118. return YES;
  119. }
  120. - (CGFloat)parallaxProgressForVisibleIndex:(NSInteger)visibleIndex
  121. offsetProgress:(CGFloat)offsetProgress
  122. minScale:(CGFloat)minScale
  123. {
  124. CGFloat step = (1.0 - minScale) / (self.param.wCardOverLapCount-1)*1.0;
  125. return (1.0 - (visibleIndex - 1) * step + step * offsetProgress);
  126. }
  127. - (CGSize)collectionContenSize{
  128. return CGSizeMake((int)self.collectionView.bounds.size.width, (int)self.collectionView.bounds.size.height);
  129. }
  130. - (CGPoint)collectionContenOffset{
  131. return CGPointMake((int)self.collectionView.contentOffset.x, (int)self.collectionView.contentOffset.y);
  132. }
  133. @end