2016-09-26 78 views
3

我有下面的代碼(根據this答案)創建一個'形變'圓形方形<>。UIBezierPath:在iPad上創建的控制點多於iPhone?

它在iPhone上工作的偉大:

enter image description here

但不是那麼好上的iPad(運行iOS的相同版本 - 10):

enter image description here

代碼是:

-(UIBezierPath*)circlePathWithCenter:(CGPoint)center andRadius:(CGFloat)radius { 
    UIBezierPath *circlePath = [UIBezierPath bezierPath]; 
    [circlePath addArcWithCenter:center radius:radius startAngle:-M_PI endAngle:-M_PI/2 clockwise:YES]; 
    [circlePath addArcWithCenter:center radius:radius startAngle:-M_PI/2 endAngle:0 clockwise:YES]; 
    [circlePath addArcWithCenter:center radius:radius startAngle:0 endAngle:M_PI/2 clockwise:YES]; 
    [circlePath addArcWithCenter:center radius:radius startAngle:M_PI/2 endAngle:M_PI clockwise:YES]; 
    [circlePath closePath]; 

    NSLog(@"%@", [circlePath debugDescription]); 

    return circlePath; 
} 

- (UIBezierPath *)squarePathWithCenter:(CGPoint)center andSize:(CGFloat)size 
{ 
    CGFloat startX = center.x-size/2; 
    CGFloat startY = center.y-size/2; 

    UIBezierPath *squarePath = [UIBezierPath bezierPath]; 
    [squarePath moveToPoint:CGPointMake(startX, startY)]; 
    [squarePath addLineToPoint:squarePath.currentPoint]; 
    [squarePath addLineToPoint:CGPointMake(startX+size, startY)]; 
    [squarePath addLineToPoint:squarePath.currentPoint]; 
    [squarePath addLineToPoint:CGPointMake(startX+size, startY+size)]; 
    [squarePath addLineToPoint:squarePath.currentPoint]; 
    [squarePath addLineToPoint:CGPointMake(startX, startY+size)]; 
    [squarePath addLineToPoint:squarePath.currentPoint]; 
    [squarePath closePath]; 

    NSLog(@"%@", [squarePath debugDescription]); 

    return squarePath; 
} 

動畫c頌歌是:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; 
animation.duration = 0.5; 
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 

animation.fromValue = (__bridge id)(_innerShape.path); 
animation.toValue = (__bridge id)(_innerSquare.CGPath); 
_innerShape.path = _innerSquare.CGPath; 

[_innerShape addAnimation:animation forKey:@"animatePath"]; 

在路徑的仔細檢查,我注意到有更多的「curveto」的iPad版點(運行相同的代碼)。從前一期的討論中,我認爲控制點的數量需要相同才能平穩過渡。

設備之間預期的點數是否不同?有一種更可靠的方法來達到形變的形狀嗎?

圈的iPad的調試:

<UIBezierPath: 0x6c4f0d0; <MoveTo {13.5, 45.000004}>, 
<CurveTo {44.999996, 13.5} {13.499998, 27.603035} {27.603027, 13.500002}>, 
<CurveTo {45, 13.5} {44.999996, 13.5} {45, 13.5}>, 
<LineTo {45, 13.5}>, 
<CurveTo {76.5, 45} {62.396969, 13.499999} {76.5, 27.603031}>, 
<CurveTo {76.5, 45} {76.5, 45} {76.5, 45}>, 
<LineTo {76.5, 45}>, 
<CurveTo {45, 76.5} {76.5, 62.396969} {62.396969, 76.5}>, 
<CurveTo {45, 76.5} {45, 76.5} {45, 76.5}>, 
<LineTo {45, 76.5}>, 
<CurveTo {13.5, 45} {27.603031, 76.5} {13.499999, 62.396969}>, 
<CurveTo {13.5, 44.999996} {13.5, 45} {13.5, 44.999996}>, 
<Close> 

iPhone版本:

<UIBezierPath: 0x6180000b24e0; <MoveTo {13.5, 44.999999999999993}>, 
<CurveTo {45, 13.5} {13.500000000000002, 27.603030380330004} {27.603030380330011, 13.499999999999998}>, 
<LineTo {45, 13.5}>, 
<CurveTo {76.5, 45} {62.396969619669989, 13.500000000000002} {76.5, 27.603030380330011}>, 
<LineTo {76.5, 45}>, 
<CurveTo {45, 76.5} {76.5, 62.396969619669989} {62.396969619669989, 76.5}>, 
<LineTo {45, 76.5}>, 
<CurveTo {13.5, 45.000000000000007} {27.603030380330011, 76.5} {13.500000000000002, 62.396969619669996}>, 
<Close> 

廣場兩個:

<UIBezierPath: 0x6000000b0f80; <MoveTo {29.25, 29.25}>, 
<LineTo {29.25, 29.25}>, 
<LineTo {60.75, 29.25}>, 
<LineTo {60.75, 29.25}>, 
<LineTo {60.75, 60.75}>, 
<LineTo {60.75, 60.75}>, 
<LineTo {29.25, 60.75}>, 
<LineTo {29.25, 60.75}>, 
<Close> 
+0

你爲什麼要做所有這些'[squarePath addLineToPoint:squarePath.currentPoint]'調用?如果兩條貝塞爾路徑具有不同數量的段,則在兩條不同的貝塞爾路徑之間進行動畫處理會導致怪異的中間形狀。那些使用'currentPoint'的'addLineToPoint'看起來好像會爲路徑添加不必要的點。另外,我會將這些圓弧值移動π/ 4,以便它們更好地與正方形的角部對齊。 – Rob

+0

好問題!我提到的arcWithCenter鏈接的文章是增加兩段我認爲?所以最初的修復方法是增加更多的廣場。 – Paul

回答

3

如果兩個路徑之間轉換,這一點很重要的是它們具有相同的段數。

有兩種基本方法:

  1. 一種方法是創建圓爲多個線段,然後撰寫相同數量的段的平方。你只需要使用一個足夠大的數段這樣的那個圈子會出現輪:

    static NSInteger segments = 360; 
    
    - (UIBezierPath*)circlePathWithCenter:(CGPoint)center andRadius:(CGFloat)radius { 
    
        CGFloat startAngle = -M_PI * 3.0/4.0; 
        CGPoint point = CGPointMake(radius * cos(startAngle) + center.x, radius * sinf(startAngle) + center.y); 
    
        UIBezierPath *path = [UIBezierPath bezierPath]; 
        [path moveToPoint:point]; 
    
        for (NSInteger angle = 1; angle <= segments; angle++) { 
         point = CGPointMake(radius * cos(startAngle + ((CGFloat)angle/360.0 * M_PI * 2.0)) + center.x, 
              radius * sin(startAngle + ((CGFloat)angle/360.0 * M_PI * 2.0)) + center.y); 
         [path addLineToPoint:point]; 
        } 
    
        return path; 
    } 
    
    - (UIBezierPath *)squarePathWithCenter:(CGPoint)center andSize:(CGFloat)size { 
        CGFloat startX = center.x-size/2; 
        CGFloat startY = center.y-size/2; 
    
        CGFloat endX = startX+size; 
        CGFloat endY = startY; 
    
        UIBezierPath *path = [UIBezierPath bezierPath]; 
        CGPoint point = CGPointMake(startX, startY); 
        [path moveToPoint:point]; 
    
        for (NSInteger i = 1; i <= segments/4; i++) { 
         CGPoint point = CGPointMake(startX + (endX - startX) * (CGFloat) i/90.0, 
                startY + (endY - startY) * (CGFloat) i/90.0); 
         [path addLineToPoint:point]; 
        } 
    
        startX = endX; startY = endY; 
        endY += size; 
    
        for (NSInteger i = 1; i <= segments/4; i++) { 
         CGPoint point = CGPointMake(startX + (endX - startX) * (CGFloat) i/90.0, 
                startY + (endY - startY) * (CGFloat) i/90.0); 
         [path addLineToPoint:point]; 
        } 
    
        startX = endX; startY = endY; 
        endX -= size; 
    
        for (NSInteger i = 1; i <= segments/4; i++) { 
         CGPoint point = CGPointMake(startX + (endX - startX) * (CGFloat) i/90.0, 
                startY + (endY - startY) * (CGFloat) i/90.0); 
         [path addLineToPoint:point]; 
        } 
    
        startX = endX; startY = endY; 
        endY -= size; 
    
        for (NSInteger i = 1; i <= segments/4; i++) { 
         CGPoint point = CGPointMake(startX + (endX - startX) * (CGFloat) i/90.0, 
                startY + (endY - startY) * (CGFloat) i/90.0); 
         [path addLineToPoint:point]; 
        } 
    
        return path; 
    } 
    

    option 1

  2. 或者,您可以用弧線,但你可能想確保線段和在兩條路徑中,弧線匹配一對一。例如,我可以將正方形渲染爲一系列帶有線段的零半徑圓弧,並將圓形渲染爲一系列全長圓弧,並在它們之間具有長度爲零的線段。這樣一來,有一對一一對應到每次調用moveToPointaddArcWithCenteraddLineToPoint

    - (UIBezierPath*)circlePathWithCenter:(CGPoint)center andRadius:(CGFloat)radius { 
        UIBezierPath *path = [UIBezierPath bezierPath]; 
    
        CGFloat startAngle = -M_PI; 
    
        [path moveToPoint:CGPointMake(center.x - radius, center.y)]; 
    
        for (NSInteger angle = 0; angle < 4; angle++) { 
         [path addArcWithCenter:center radius:radius startAngle:startAngle endAngle:startAngle + M_PI_2 clockwise:true]; 
         [path addLineToPoint:path.currentPoint]; 
         startAngle += M_PI_2; 
        } 
    
        return path; 
    } 
    
    - (UIBezierPath *)squarePathWithCenter:(CGPoint)center andSize:(CGFloat)size { 
        CGFloat startX = center.x-size/2; 
        CGFloat startY = center.y-size/2; 
        CGFloat angle = -M_PI; 
    
        CGFloat endX = startX+size; 
        CGFloat endY = startY; 
    
        UIBezierPath *path = [UIBezierPath bezierPath]; 
        CGPoint point = CGPointMake(startX, startY); 
        [path moveToPoint:point]; 
    
        [path addArcWithCenter:point radius:0 startAngle:angle endAngle:angle + M_PI_2 clockwise:true]; 
        point = CGPointMake(endX, endY); 
        [path addLineToPoint:point]; 
    
        angle += M_PI_2; 
        startX = endX; startY = endY; 
        endY += size; 
    
        [path addArcWithCenter:point radius:0 startAngle:angle endAngle:angle + M_PI_2 clockwise:true]; 
        point = CGPointMake(endX, endY); 
        [path addLineToPoint:point]; 
    
        angle += M_PI_2; 
        startX = endX; startY = endY; 
        endX -= size; 
    
        [path addArcWithCenter:point radius:0 startAngle:angle endAngle:angle + M_PI_2 clockwise:true]; 
        point = CGPointMake(endX, endY); 
        [path addLineToPoint:point]; 
    
        angle += M_PI_2; 
        startX = endX; startY = endY; 
        endY -= size; 
    
        [path addArcWithCenter:point radius:0 startAngle:angle endAngle:angle + M_PI_2 clockwise:true]; 
        point = CGPointMake(endX, endY); 
        [path addLineToPoint:point]; 
    
        return path; 
    } 
    

    國債收益率:

    option 2

這兩個產生不同的影響,因此這取決於你要做什麼。