分三部分實現,在drawrect方法里畫出灰色背景,根據pageCount創建對應個數的dotView放置在對應位置,並隱藏,創建一個CAShapeView類型的layer,根據scrollView的偏移量 構建貝塞爾曲線,畫出紅色線條,以及形變的大圓。大圓的形變以及構建思路:(圖引用自:http:...
分三部分實現,在drawrect方法里畫出灰色背景,根據pageCount創建對應個數的dotView放置在對應位置,並隱藏,創建一個CAShapeView類型的layer,根據scrollView的偏移量 構建貝塞爾曲線,畫出紅色線條,以及形變的大圓。
大圓的形變以及構建思路:
(圖引用自:http://kittenyang.com/deformationandgooey/)
下麵就是構建A、B、C、D、c1、c2、c3、c4、c5、c6、c7、c8這些點,給A、B、C、D、四個點,一個關於contentOffset的形變數,以達到園形變的效果。value = (半徑 * 比例)*形變因素,其中形變因素於contentOffset相關(在滑動一個頁面時會形成這樣的關係:0~0.5~0);CGFloat factor = MIN(0.5, MAX(0, (ABS(scrollView.contentOffset.x - last) / scrollView.frame.size.width)));,構建好點後,根據偏移量,更新點的坐標,生成新的貝塞爾曲線,便生成形變的 圓了。
下麵是部分代碼:
/** 根據scrollView 更新貝塞爾曲線 */ - (void)updateDotLayerScrollView:(UIScrollView *)scrollView{ // 判斷滑動方向 BOOL left = (scrollView.contentOffset.x - self.lastOffsetX) >= 0?YES:NO; // 向左滑動就顯示dotView if (left) { [self setDotViewShowWithScrollView:scrollView]; } CGPoint dotCenter = [self calculateDotCenterWithScrollView:scrollView]; // 計算當前偏移量的 歸屬地(超過一半 就歸屬後者,反之前者) int count = (int)(scrollView.contentOffset.x / scrollView.frame.size.width+0.5); // 根據count 計算歸屬地 的偏移量 CGFloat last = scrollView.frame.size.width * count; CGFloat factor = MIN(0.5, MAX(0, (ABS(scrollView.contentOffset.x - last) / scrollView.frame.size.width))); // extra 是 A、B、C、D四點的 位移量,跟factor有關。而factor跟contentOffset相關,其關係為0~0.5~0; CGFloat extra = self.SeletedDotRadiu * 4 / 5 * factor; // 構成貝塞爾曲線的相關點 的計算 A = CGPointMake(dotCenter.x, dotCenter.y - self.SeletedDotRadiu+extra); B = CGPointMake(left?(dotCenter.x+self.SeletedDotRadiu):(dotCenter.x+self.SeletedDotRadiu+extra * 2), dotCenter.y); C = CGPointMake(dotCenter.x, dotCenter.y+self.SeletedDotRadiu-extra); D = CGPointMake(left?(dotCenter.x-self.SeletedDotRadiu-extra*2):(dotCenter.x-self.SeletedDotRadiu), dotCenter.y); // 1.8 的得來應該是能計算出來的,不過不知道咋算,試出來 CGFloat offset = self.SeletedDotRadiu / 1.8; c1 = CGPointMake(A.x + offset, A.y); c2 = CGPointMake(B.x, B.y - offset); c3 = CGPointMake(B.x, B.y + offset); c4 = CGPointMake(C.x + offset, C.y); c5 = CGPointMake(C.x - offset, C.y); c6 = CGPointMake(D.x, D.y + offset); c7 = CGPointMake(D.x, D.y - offset); c8 = CGPointMake(A.x - offset, A.y); UIBezierPath* ovalPath = [UIBezierPath bezierPath]; CGPoint startPoint = CGPointMake(self.SeletedDotRadiu, CGRectGetHeight(self.frame) / 2.0); [ovalPath moveToPoint: startPoint]; [ovalPath addLineToPoint:D]; [ovalPath addCurveToPoint:C controlPoint1:c6 controlPoint2:c5]; [ovalPath addCurveToPoint:B controlPoint1:c4 controlPoint2:c3]; [ovalPath addCurveToPoint:A controlPoint1:c2 controlPoint2:c1]; [ovalPath addCurveToPoint:D controlPoint1:c8 controlPoint2:c7]; [ovalPath closePath]; self.dotLayer.path = ovalPath.CGPath; self.lastOffsetX = scrollView.contentOffset.x; }
drawRect 方法:
/** 畫初始 的背景 */ - (void)drawRect:(CGRect)rect { // 控制項垂直方向中心 CGFloat verticalCenter = rect.size.height / 2.0; // 圓點 半徑 CGFloat dotR = self.dotRadiu; // 選中圓點 半徑 CGFloat selectedDotR = self.SeletedDotRadiu; // 圓心距離 CGFloat distanceCenter = (rect.size.width - 2 * selectedDotR) / (self.pageCount - 1); UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(selectedDotR, (rect.size.height - self.lineWidth) / 2.0, rect.size.width - 2 * selectedDotR, self.lineWidth)]; [self.color setFill]; for (int i = 0; i < self.pageCount; i++) { UIBezierPath *dotPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(selectedDotR + distanceCenter * i, verticalCenter) radius:dotR startAngle:0 endAngle:M_PI * 2 clockwise:YES]; [path appendPath:dotPath]; } [path fill]; }
完整代碼:http://pan.baidu.com/s/1i4y78gt