How We Created Animated Preloaders

How We Created Animated Preloaders

You have probably noticed, that we started putting up some cool animations on GitHub. The recent one is called Ophiuchus (they all have weird names of stars). In this article we’ll tell you a little bit about how we actually developed this animation.

Yalantis animated preloader


Ophiuchus is based on our Dribbble design project, created by Dasha Ermolova. The animation is a preloader for our website featuring Yalantis logo. Dasha’s idea was to add some sort of a visual trick, the illusion of space to make a viewer feel that Y is an axis with planets rotating around it. For that reason the animation does not only show the motion, but the progress as well. It was created with the help of After Effects and then implemented by our iOS developers, Nikita Shytyk and Igor Muzyka.

Read also: Product design in Yalantis

Development for iOS

At first our iOS developers made an attempt to build a component that would only work with one letter. Here is how:

UIBezierPath *outsidePath = ({

 CGPoint point1 = CGPointMake(halfRectWidth - halfLetterWidth, bottomY);

 CGPoint point2 = CGPointMake(halfRectWidth + halfLetterWidth, bottomY);

 // ...

 CGPoint point9 = CGPointMake(halfRectWidth - halfLetterWidth, bottomY - legHeight);

 CGPoint points[9] = {point1, point2, point3, point4, point5, point6, point7, point8, point9};

 CGMutablePathRef cgPath = CGPathCreateMutable();

 CGPathAddLines(cgPath, &CGAffineTransformIdentity, points, sizeof points / sizeof *points);


 [UIBezierPath bezierPathWithCGPath:cgPath]; 


However, the code got fouled with magic numbers and became unusable. The next idea was to create a universal component suitable for any kind of text. Igor wrote the code with the help of native CoreText framework, where NSAttributedString breaks down into letter by letter UIBezierPath:

- (NSArray *)yal_bezierPaths {

 NSMutableArray *letters = [NSMutableArray new];

 CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)self);

 CFArrayRef runArray = CTLineGetGlyphRuns(line);

 CGRect biggestBoundingBox = CGRectZero;

 for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++) {

 CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);

 CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);

 for (CFIndex glyphIndex = 0; glyphIndex < CTRunGetGlyphCount(run); glyphIndex++) {

 CFRange range = CFRangeMake(glyphIndex, 1);

 CGGlyph glyph;

 CGPoint position;

 CTRunGetGlyphs(run, range, &glyph);

 CTRunGetPositions(run, range, &position);

 CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL);

 CGAffineTransform transform = CGAffineTransformMakeTranslation(position.x, position.y);

 UIBezierPath *path = [UIBezierPath bezierPathWithCGPath:letter];

 CGRect boundingBox = CGPathGetBoundingBox(letter);

 if (CGRectGetHeight(boundingBox) > CGRectGetHeight(biggestBoundingBox)) {

 biggestBoundingBox = boundingBox;



 [path applyTransform:transform];

 [letters addObject:path];



 for (UIBezierPath *letter in letters) {




 return [NSArray arrayWithArray:letters];


We assembled the whole text label from separate UIBezierPath objects. This way we received a vector representation for each letter of any font and size, which makes the code super reusable! We simply outlined all the letters in the Ophiuchus project and used them as a mask for the progress’ layer. Now we can animate the whole word or even a sentence in a variety of different ways. We can also animate each letter separately anyway you like it:

Yalantis animated preloader

And here is another one:

Yalantis preloader

Check out the original Ophiuchus animation:

We are going to build more awesome animations like that, so follow our updates!

Performance tuning

How do you make things run faster? Check out our experiments

From JSON to Core Data Fast
Written by Dima Vorona

From JSON to Core Data Fast

In order to import data from JSON to Core Data there exist quite a number of ready solutions. However, ...

Is Swift Faster Than Objective-C?
Written by Stas Kirichok

Is Swift Faster Than Objective-C?

Little time has passed since Swift 1.0 was released especially once you compare it with the lifetime of...

Mastering UIKit Performance
Written by Eugene Goloboyar

Mastering UIKit Performance

Even though a lot of articles and WWDC sessions are devoted to UIKit performance, this topic still rema...

iOS animation designs

Rethinking menu, tab bar, pull-to-refresh, and other navigation elements in iPhone apps

How We Created Tab Bar Animation for iOS
Written by Kate Abrosimova, Igor Muzyka, and Vitaly Rubtsov

How We Created Tab Bar Animation for iOS

Today’s smartphones are becoming more like tablets, or there is even a better word – phablets. Big scre...

How We Created Guillotine Menu Animation for iOS
Written by Maksym Lazebnyi and Vitaly Rubtsov

How We Created Guillotine Menu Animation for iOS

Have you ever wondered why a sidebar in apps has to be a “side” bar? Why not to make it a “topbar,” or ...

How We Developed ColorMatchTabs Animation for iOS
Written by Sergey Butenko and Sergii Ganushchak

How We Developed ColorMatchTabs Animation for iOS

The article talks about a UI animation for a concept of a review app that we developed for iPhones

How We Built Pull To Make Soup Animation
Written by Anastasiya Gorban

How We Built Pull To Make Soup Animation

Pull-to-refresh is a great place for creativity! But we’re building cool pull-to-refresh animations not...

Creating ForceBlur Animation for iOS Messaging Apps
Written by Alexey Chernish, Kostya Trundayev, and Sergey Butenko

Creating ForceBlur Animation for iOS Messaging Apps

ForceBlur iOS animation is based on force touch feature that can be used for sensitive content

Excited to create something outstanding?

We share the same interests.

Let's team up!