WMZBannerOverLayout.m 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. @end
  13. @implementation WMZBannerOverLayout
  14. - (instancetype)initConfigureWithModel:(WMZBannerParam *)param{
  15. if (self = [super init]) {
  16. self.param = param;
  17. }
  18. return self;
  19. }
  20. - (void)prepareLayout
  21. {
  22. [super prepareLayout];
  23. if (self.param.wCardOverLapCount<=0) {
  24. self.param.wCardOverLapCount = 4;
  25. }
  26. self.collectionView.pagingEnabled = YES;
  27. self.itemSize = self.param.wVertical?
  28. CGSizeMake(self.param.wItemSize.width , (self.param.wItemSize.height - (self.param.wCardOverLapCount - 1)*self.param.wLineSpacing)):
  29. CGSizeMake(self.param.wItemSize.width - (self.param.wCardOverLapCount - 1)*self.param.wLineSpacing, self.param.wItemSize.height);
  30. self.minimumInteritemSpacing = (self.param.wFrame.size.height-self.param.wItemSize.height)/2;
  31. self.sectionInset = self.param.wSectionInset;
  32. self.scrollDirection = self.param.wVertical? UICollectionViewScrollDirectionVertical
  33. :UICollectionViewScrollDirectionHorizontal;
  34. }
  35. - (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
  36. return [self cardOverLapTypeInRect:rect];
  37. }
  38. //卡片重叠
  39. - (NSArray<UICollectionViewLayoutAttributes *> *)cardOverLapTypeInRect:(CGRect)rect{
  40. NSInteger itemsCount = [self.collectionView numberOfItemsInSection:0];
  41. if (itemsCount <= 0) {
  42. return nil;
  43. }
  44. self.param.myCurrentPath = self.param.wVertical?
  45. MAX(floor(self.collectionContenOffset.y / (int)self.collectionContenSize.height ), 0):
  46. MAX(floor(self.collectionContenOffset.x / (int)self.collectionContenSize.width ), 0);
  47. NSInteger minVisibleIndex = MAX(self.param.myCurrentPath, 0);
  48. NSInteger contentOffset = self.param.wVertical?
  49. self.collectionContenOffset.y:self.collectionContenOffset.x;
  50. NSInteger collectionBounds = self.param.wVertical?
  51. self.collectionContenSize.height:self.collectionContenSize.width;
  52. CGFloat offset = contentOffset % collectionBounds;
  53. CGFloat offsetProgress = offset / (self.param.wVertical?self.collectionContenSize.height:self.collectionContenSize.width)*1.0f;
  54. NSInteger maxVisibleIndex = MAX(MIN(itemsCount - 1, self.param.myCurrentPath + self.param.wCardOverLapCount), minVisibleIndex);
  55. NSMutableArray *mArr = [[NSMutableArray alloc] init];
  56. for (NSInteger i = minVisibleIndex; i<=maxVisibleIndex; i++) {
  57. NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
  58. UICollectionViewLayoutAttributes *attributes = [[self layoutAttributesForItemAtIndexPath:indexPath] copy];
  59. NSInteger visibleIndex = MAX(indexPath.item - self.param.myCurrentPath + 1, 0);
  60. attributes.size = self.itemSize;
  61. CGFloat topCardMidX = self.param.wVertical?
  62. (self.collectionContenOffset.y + self.collectionContenSize.height / 2):
  63. (self.collectionContenOffset.x + self.collectionContenSize.width / 2);
  64. attributes.center = self.param.wVertical?
  65. CGPointMake(self.collectionContenSize.width/2, topCardMidX + self.param.wLineSpacing * (visibleIndex - 1)):
  66. CGPointMake(topCardMidX + self.param.wLineSpacing * (visibleIndex - 1), self.collectionContenSize.height/2);
  67. attributes.zIndex = 925457662 - visibleIndex;
  68. CGFloat scale = [self parallaxProgressForVisibleIndex:visibleIndex offsetProgress:offsetProgress minScale:self.param.wScaleFactor];
  69. attributes.transform = CGAffineTransformMakeScale(scale, scale);
  70. if (visibleIndex == 1) {
  71. if (self.param.wVertical) {
  72. if (minVisibleIndex != maxVisibleIndex) {
  73. if (self.collectionContenOffset.y >= 0) {
  74. attributes.center = CGPointMake(attributes.center.x, attributes.center.y - offset);
  75. }else{
  76. attributes.center = CGPointMake(attributes.center.x , attributes.center.y + attributes.size.height * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress);
  77. }
  78. }
  79. }else{
  80. if (minVisibleIndex != maxVisibleIndex) {
  81. if (self.collectionContenOffset.x >= 0) {
  82. attributes.center = CGPointMake(attributes.center.x - offset, attributes.center.y);
  83. }else{
  84. attributes.center = CGPointMake(attributes.center.x + attributes.size.width * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress, attributes.center.y);
  85. }
  86. }
  87. }
  88. }else if (visibleIndex == self.param.wCardOverLapCount + 1){
  89. attributes.center = self.param.wVertical?
  90. CGPointMake(attributes.center.x, attributes.center.y + attributes.size.height * (1 - scale)/2 - self.param.wLineSpacing):
  91. CGPointMake(attributes.center.x + attributes.size.width * (1 - scale)/2 - self.param.wLineSpacing, attributes.center.y);
  92. }else{
  93. attributes.center = self.param.wVertical?
  94. CGPointMake(attributes.center.x , attributes.center.y + attributes.size.height * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress):
  95. CGPointMake(attributes.center.x + attributes.size.width * (1 - scale)/2 - self.param.wLineSpacing * offsetProgress, attributes.center.y);
  96. }
  97. [mArr addObject:attributes];
  98. }
  99. return mArr;
  100. }
  101. - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
  102. return YES;
  103. }
  104. - (CGFloat)parallaxProgressForVisibleIndex:(NSInteger)visibleIndex
  105. offsetProgress:(CGFloat)offsetProgress
  106. minScale:(CGFloat)minScale
  107. {
  108. CGFloat step = (1.0 - minScale) / (self.param.wCardOverLapCount-1)*1.0;
  109. return (1.0 - (visibleIndex - 1) * step + step * offsetProgress);
  110. }
  111. - (CGSize)collectionContenSize{
  112. return CGSizeMake((int)self.collectionView.bounds.size.width, (int)self.collectionView.bounds.size.height);
  113. }
  114. - (CGPoint)collectionContenOffset{
  115. return CGPointMake((int)self.collectionView.contentOffset.x, (int)self.collectionView.contentOffset.y);
  116. }
  117. @end