2013-08-22 10 views
16

Próbuję znaleźć sposób, aby programowo rysować kształt "squircle" w stylu iOS 7, używając grafiki głównej. Nie pytam, jak narysować zaokrąglony prostokąt. Squircle jest superelipse:Rysowanie iOS 7-stylowy squircle programowo

Squircle

która jest nieco inny niż zwykły zaokrąglonego prostokąta: Rounded rectangle vs squircle

Music icon in squircle

To Dokładny wzór is readily available. Jednak nie mogę wymyślić, jak narysować to za pomocą, na przykład, CGPath, nie mówiąc już o wypełnieniu go, i być w stanie zmienić jego rozmiar raczej łatwo. Wszystko to przy zachowaniu pełnej formuły. Dowolny pomysł?

+0

Nie, wiem, jak zrobić zaokrąglony prostokąt; Naprawdę jestem superelipis typu squircle, ponieważ używają one ikon do odskoku na iOS 7. –

+2

@RemyVanherweghem Metoda 'bezierPathWithRoundedRect' została zmodyfikowana w iOS 7, aby rysować bardziej płynne rogi. Również nie wydaje się być squircle: http://blog.mikeswanson.com/post/62341902567/unleashing-genetic-algorithms-on-the-ios-7-icon – millimoose

+0

(To powiedziawszy, metody 'UIBezierPath' nie produkuj idealnie pasującego do szablonu ikony, są one po prostu bliższe niż wcześniej). – millimoose

Odpowiedz

12

cytat z Treść: Superellipse

dla N = 1/2, w szczególności każdy z czterech łuków krzywą kwadratowa Bézier wyznaczone przez dwa osie; w rezultacie każdy łuk jest segmentem paraboli.

Dlaczego więc nie spróbować przybliżać Squircle za pomocą krzywych Beziera? Obie krzywe (Bezier i Squircle) są zdefiniowane przez równania parametryczne.

UIBezierPath Class mieć metodę: addCurveToPoint:controlPoint1:controlPoint2:

Dołącza Baziera krzywą ścieżki odbiornika.

UWAGA: Użycie metody addQuadCurveToPoint:controlPoint: daje gorsze wyniki - testowane.

Użyłem tej metody, a to, co się stało w wyniku:

red line - zaokrąglony prostokąt, blue line - prostokąt z czwórki Beziera krzywe

Rounded rectangle vs cubic Bezier curve

Jeśli ten wynik jest zainteresowany - kod poniżej rysunek .

UWAGA: Aby uzyskać dokładniejsze dopasowanie, krzywa Béziera może być wymagana do zmiany współrzędnych czterech corner points (teraz odpowiadają one kątom prostokąta, w którym wpisana jest cyfra).

CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSaveGState(context); 

//set rect size for draw 
float rectSize = 275.; 
CGRect rectangle = CGRectMake(CGRectGetMidX(rect) - rectSize/2, CGRectGetMidY(rect) - rectSize/2, rectSize, rectSize); 

//Rounded rectangle 
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); 
UIBezierPath* roundedPath = [UIBezierPath bezierPathWithRoundedRect:rectangle cornerRadius:rectSize/4.7]; 
[roundedPath stroke]; 

//Rectangle from Fours Bezier Curves 
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); 
UIBezierPath *bezierCurvePath = [UIBezierPath bezierPath]; 

//set coner points 
CGPoint topLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMinY(rectangle)); 
CGPoint topRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMinY(rectangle)); 
CGPoint botLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMaxY(rectangle)); 
CGPoint botRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMaxY(rectangle)); 

//set start-end points 
CGPoint midRPoint = CGPointMake(CGRectGetMaxX(rectangle), CGRectGetMidY(rectangle)); 
CGPoint botMPoint = CGPointMake(CGRectGetMidX(rectangle), CGRectGetMaxY(rectangle)); 
CGPoint topMPoint = CGPointMake(CGRectGetMidX(rectangle), CGRectGetMinY(rectangle)); 
CGPoint midLPoint = CGPointMake(CGRectGetMinX(rectangle), CGRectGetMidY(rectangle)); 

//Four Bezier Curve 
[bezierCurvePath moveToPoint:midLPoint]; 
[bezierCurvePath addCurveToPoint:topMPoint controlPoint1:topLPoint controlPoint2:topLPoint]; 
[bezierCurvePath moveToPoint:midLPoint]; 
[bezierCurvePath addCurveToPoint:botMPoint controlPoint1:botLPoint controlPoint2:botLPoint]; 
[bezierCurvePath moveToPoint:midRPoint]; 
[bezierCurvePath addCurveToPoint:topMPoint controlPoint1:topRPoint controlPoint2:topRPoint]; 
[bezierCurvePath moveToPoint:midRPoint]; 
[bezierCurvePath addCurveToPoint:botMPoint controlPoint1:botRPoint controlPoint2:botRPoint]; 

[bezierCurvePath stroke]; 

CGContextRestoreGState(context); 
+0

Świetna odpowiedź. Dzięki! –

2

To nie jest wielki odpowiedź, ponieważ nie dostać się do centrum co pytasz co jest jak narysować superelipsa ** programowo, ale można:

  1. Pobierz SVG ikona kształt iOS7 tutaj: http://dribbble.com/shots/1127699-iOS-7-icon-shape-PSD
  2. zaimportować go do projektu Xcode
  3. Dodaj PocketSVG do projektu: https://github.com/arielelkin/PocketSVG
  4. Załaduj SVG i przekształcić go w UIBezierPath, stamtąd można skalować i przekształcać jednak lubisz:

    PocketSVG *myVectorDrawing = [[PocketSVG alloc] initFromSVGFileNamed:@"iOS_7_icon_shape"]; 
    
    UIBezierPath *myBezierPath = myVectorDrawing.bezier; 
    
    // Apply your transforms here: 
    [myBezierPath applyTransform:CGAffineTransformMakeScale(2.5, 2.5)]; 
    [myBezierPath applyTransform:CGAffineTransformMakeTranslation(10, 50)]; 
    
    CAShapeLayer *myShapeLayer = [CAShapeLayer layer]; 
    myShapeLayer.path = myBezierPath.CGPath; 
    myShapeLayer.strokeColor = [[UIColor redColor] CGColor]; 
    myShapeLayer.lineWidth = 2; 
    myShapeLayer.fillColor = [[UIColor clearColor] CGColor]; 
    
    [self.view.layer addSublayer:myShapeLayer]; 
    

** To może warto zauważyć, że kształt nie może być dokładną superelipsa anyway: http://i.imgur.com/l0ljVRo.png

0

Byłoby to dość łatwe do zrobienia w OpenGL ES z cieniującego. Po prostu narysuj quad i przekaż atrybuty xiy y vertex. W module cieniującym wtyczki x i y do równania. Jeśli wynik to < = 1, to fragment znajduje się wewnątrz kształtu. Jeśli uda mi się zdobyć trochę wolnego czasu, wypróbuję to i opublikuję tutaj.

Jeśli chcesz używać CGPath, myślę, że kluczem jest sparametryzować x i y pod względem t, który idzie od 0 do 2π. Następnie oceniaj xiy w regularnych odstępach czasu. Spróbuję to rozgryźć w wolnym czasie, ale moja matematyka jest trochę zardzewiała.

BTW, jestem pewien, że Apple jest nie używając tej formuły. Patrz link @millimoose umieszczone: http://blog.mikeswanson.com/post/62341902567/unleashing-genetic-algorithms-on-the-ios-7-icon