UIBezierPath и CAShapeLayer: рисование
UIBezierPath
Класс UIBezierPath позволяет определить путь, состоящий из прямых и изогнутых отрезков линий, и визуализировать этот путь в пользовательских представлениях. Этот класс используется для определения геометрии пути. Пути могут определять простые фигуры, такие как прямоугольники, овалы и дуги, или сложные многоугольники, состоящие из комбинации прямых и изогнутых линий. После определения формы можно использовать дополнительные методы этого класса для визуализации пути в текущем контексте рисования.
UIBezierPath состоит из геометрии пути и свойств, которые используются для рисования геометрии на этапе рендеринга, например, ширина линии. Путь и свойства полностью независимы и не зависят друг от друга, их можно настраивать отдельно. Как только вы настроите объект UIBezierPath по своему вкусу, вы можете вызвать метод, чтобы сообщить UIBezierPath, что он должен нарисовать фигуру в текущем контексте рисования. Поскольку создание, настройка и рендеринг пути — это отдельные шаги, вы можете легко повторно использовать объекты UIBezierPath в своём коде. Вы даже можете использовать один и тот же объект UIBezierPath для многократного рендеринга одной и той же фигуры или изменять свойства между рендерами, чтобы создавать пути разных стилей.
Когда вы создаёте пустой объект UIBezierPath, свойство currentPoint не определено, и вам нужно вручную установить его. Если вы хотите переместить currentPoint без рисования каких-либо линий, вы можете использовать метод moveToPoint:. Все остальные методы добавят дополнительные прямые или изогнутые линии к вашему пути. Все методы построения пути используют currentPoint текущего пути в качестве начальной точки и endPoint, который вы указываете, в качестве конечной точки. Когда рисование завершено, новая конечная точка добавленной линии становится currentPoint объекта UIBezierPath.
Простой UIBezierPath может содержать множество открытых и закрытых подпутей. Метод closePath замыкает путь, рисуя прямую линию от currentPoint до firstPoint подпути. Метод moveToPoint: завершает текущий подпуть, но не замыкает текущий путь автоматически, а перемещает currentPoint в указанную точку, которая становится начальной точкой следующего пути. Все подпути в UIBezierPath используют одни и те же свойства рисования. Если вы хотите нарисовать несколько подпутей, но с разными свойствами рисования, вам придётся создать несколько объектов UIBezierPath для каждого пути.
После настройки геометрии пути и свойств рисования для объекта UIBezierPath вы можете использовать методы stroke и fill для рисования в текущем контексте. Метод stroke использует текущие strokeColor и свойства рисования для рисования контура кривой. Аналогично, метод fill использует fillColor для заполнения фигуры, ограниченной путём (используйте методы класса UIColor для установки strokeColor и fillColor).
Шаги рисования с использованием UIBezierPath:
Введение в методы создания Давайте посмотрим, какие методы создания предоставляет класс UIBezierPath — это заводские методы, которые можно использовать напрямую.
Создание и возврат нового объекта UIBezierPath:
+ (instancetype)bezierPath
Создание и возвращение нового объекта UIBezierPath с помощью прямоугольника:
/**
* Этот метод создаст замкнутый путь, начальная точка которого является origin параметра rect, и добавит прямые линии в направлении по часовой стрелке, образуя прямоугольник.
* @param rect: рамка прямоугольного пути
*/
+ (instancetype)bezierPathWithRect:(CGRect)rect
Создание и возвращение нового объекта UIBezierPath на основе указанного прямоугольника с овальной формой:
/**
* Этот метод создаст замкнутый путь, который будет рисовать приблизительную овальную форму, используя метод рисования по часовой стрелке. Если параметр rect указывает на прямоугольник, то этот объект UIBezierPath будет описывать круглую форму.
* @param rect: рамка овального пути
*/
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect
Создание и возвращение нового объекта UIBezierPath на основе прямоугольника с закруглёнными углами:
/**
* Этот метод создаст замкнутый путь, последовательно рисуя прямые и кривые линии по часовой стрелке. Когда rect является квадратом и cornerRadius равен половине длины стороны, этот метод будет описывать круговой путь.
* @param rect: рамка пути с закругленными углами
* @param cornerRadius: радиус закругления углов прямоугольника
*/
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius
Создание и возвращение нового объекта UIBezierPath на основе прямоугольника с заданными закруглёнными углами:
/**
* Этот метод создаст замкнутый путь, последовательно рисуя прямые и кривые линии по часовой стрелке.
* @param rect: рамка пути с закруглёнными углами
* @param corners: перечисление UIRectCorner, указывающее, какой угол прямоугольника становится закруглённым
* @param cornerRadii: радиусы закругления углов прямоугольника
*/
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
Создание и возвращение нового объекта UIBezierPath на основе дугового сегмента:
/**
* Этот метод создаёт открытый путь, создавая дуговой сегмент круга. В системе координат по умолчанию начальный и конечный углы основаны на единичном круге. После вызова этого метода currentPoint будет установлен в конечную точку дугового сегмента.
* Например: если указать начальный угол равным 0 и конечный угол равным π, установив clockwise в YES, будет нарисован нижний полукруг.
* Однако, если мы не изменяем начальный и конечный углы, а просто устанавливаем clockwise в NO, будет нарисован верхний полукруг.
* @param center: центр окружности
* @param radius: радиус
* @param startAngle: начальный угол
* @param endAngle: конечный угол
* @param clockwise: рисовать ли по часовой стрелке
*/
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise **Создание и возврат нового объекта UIBezierPath с помощью CGPath**
Через один CGPath создаётся и возвращается новый объект UIBezierPath.
Далее мы рассмотрим его применение.
**Первый метод: создание объекта**
Первый метод используется чаще, потому что созданный фабричный метод можно настроить по своему усмотрению и нарисовать любую фигуру.
```objc
+ (instancetype)bezierPath
Второй метод: рисование прямоугольника
Второй метод рисует прямоугольную кривую Безье.
+ (instancetype)bezierPathWithRect:(CGRect)rect
Третий метод: рисование эллипса
Третий метод рисует эллипс внутри прямоугольника. Обычно он используется для рисования кругов или овалов.
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect
Четвёртый и пятый методы: рисование закруглённого прямоугольника
Четвёртый метод рисует прямоугольник с закруглёнными углами. Пятый метод позволяет указать, какие углы будут закруглены. Это удобно использовать для расширения UIView с закруглёнными углами.
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
Шестой метод: рисование дуги
Шестой метод используется для рисования дуги. Параметры метода:
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
Все приведённые выше методы вызываются в пользовательском классе BezierPathView в методе drawRect.
Рисование треугольника
Для рисования треугольника используется следующий код:
- (void)drawTrianglePath
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(20, 20)];
[path addLineToPoint:CGPointMake(self.frame.size.width - 40, 20)];
[path addLineToPoint:CGPointMake(self.frame.size.width / 2, self.frame.size.height - 20)];
// 最后的闭合线是可以通过调用closePath方法来自动生成的,也可以调用-addLineToPoint:方法来添加
// [path addLineToPoint:CGPointMake(20, 20)];
[path closePath];
// 设置线宽
path.lineWidth = 1.5;
// 设置填充颜色
UIColor *fillColor = [UIColor redColor];
[fillColor set];
[path fill];
// 设置画笔颜色
UIColor *strokeColor = [UIColor greenColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
Здесь мы устанавливаем цвет кисти с помощью метода set:
UIColor *strokeColor = [UIColor greenColor];
[strokeColor set];
Если нужно установить цвет заливки, например, красный, то это нужно сделать перед установкой цвета кисти. Иначе цвет заливки заменит цвет кисти. То есть, если цвета заливки и кисти должны быть разными, то порядок должен быть таким: сначала цвет заливки, потом цвет кисти.
Рисование прямоугольника
Код для рисования прямоугольника:
#pragma mark - 画矩形
- (void)drawRectPath
{
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(20, 20, self.frame.size.width - 40, self.frame.size.height - 40)];
path.lineWidth = 1.5;
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinBevel;
// 设置填充颜色
UIColor *fillColor = [UIColor redColor];
[fillColor set];
[path fill];
// 设置画笔颜色
UIColor *strokeColor = [UIColor greenColor];
[strokeColor set];
// 根据我们设置的各个点连线
[path stroke];
}
Свойства lineCapStyle и lineJoinStyle используются для установки стиля линии.
lineCapStyle — используется для установки стиля угла линии. Есть три варианта: kCGLineCapButt (по умолчанию), kCGLineCapRound (скруглённый угол) и kCGLineCapSquare (квадратный угол).
lineJoinStyle — используется для установки соединения линий. Есть три варианта: kCGLineJoinMiter (соединение под углом), kCGLineJoinRound (плавное соединение) и kCGLineJoinBevel (соединение со скосом). Данный текст написан на языке Objective-C. Это похоже на фрагмент кода, связанного с разработкой приложений для iOS.
Вот перевод этого текста на русский язык:
Рисование овалов и кругов
Мы уже рисовали круги, теперь мы можем использовать метод bezierPathWithOvalInRect:
для рисования кругов. Если мы передадим в качестве параметра rect
квадрат, то получим круг. Если же мы не передадим квадрат, то получится овал.
#pragma mark - Рисование овала
- (void)drawOvalPath {
// Передаётся не квадрат, поэтому получается овал
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(20, 20, self.frame.size.width - 80, self.frame.size.height - 40)];
// Устанавливаем цвет заливки
UIColor *fillColor = [UIColor redColor];
[fillColor set];
[path fill];
// Устанавливаем цвет контура
UIColor *strokeColor = [UIColor greenColor];
[strokeColor set];
// Соединяем точки контуром
[path stroke];
}
Рисование прямоугольников с закруглёнными углами
Первый фабричный метод рисует прямоугольник, но этот прямоугольник можно сделать с закруглёнными краями. Первый параметр — это прямоугольник, второй параметр — размер закругления. Второй фабричный метод делает то же самое, но позволяет указать, какой угол должен быть закруглён. Таким образом, мы легко можем добавить закруглённые углы к UIView
.
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
Первый параметр — это прямоугольник. Второй параметр — радиус закругления. Второй метод похож на первый, но он позволяет указать, какие углы должны быть закруглены. Мы можем легко добавить закруглённые края к UIView
таким способом.
#pragma mark - рисование прямоугольника с закруглёнными углами
- (void)drawRoundedRectPath {
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 20, self.frame.size.width - 40, self.frame.size.height - 40) byRoundingCorners:UIRectCornerTopRight cornerRadii:CGSizeMake(20, 20)];
// устанавливаем цвет заливки
UIColor *fillColor = [UIColor redColor];
[fillColor set];
[path fill];
// устанавливаем цвет контура
UIColor *strokeColor = [UIColor greenColor];
[strokeColor set];
// соединяем точки контуром
[path stroke];
}
Если мы хотим нарисовать только один угол закруглённым, мы изменим метод создания:
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 20, self.frame.size.width - 40, self.frame.size.height - 40) byRoundingCorners:UIRectCornerTopRight cornerRadii:CGSizeMake(20, 20)];
Здесь первый параметр — это всё ещё прямоугольник, второй параметр указывает, в каком направлении рисовать закруглённый угол, а третий параметр — это размер радиуса по горизонтали и вертикали.
Рисование дуг
Прежде чем рисовать дуги, нам нужно понять их систему координат, как показано на рисунке ниже:
#pragma mark - рисование дуги
- (void)drawARCPath {
CGPoint center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:100 startAngle:0 endAngle:((M_PI * 135)/ 180) clockwise:YES];
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
[path stroke];
}
Нам нужно уточнить, что параметры startAngle
и endAngle
используют радианы, а не градусы, поэтому нам нужно преобразовать обычные углы в радианы. Для эффекта на рисунке мы установили центр дуги как центр элемента управления, начальную точку дуги как 0 градусов (то есть направление на восток), а конечную точку — как положение под углом 135 градусов. Если установить clockwise:YES
, дуга будет нарисована против часовой стрелки, если установить NO
, эффект будет следующим:
Рисование квадратичных кривых Безье
Сначала давайте изучим контрольные точки, как показано на следующем рисунке:
Рисование квадратичной кривой Безье осуществляется путём вызова этого метода:
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
Описание параметров:
endPoint:
конечная точкаcontrolPoint:
контрольная точка, для квадратичной кривой Безье есть только одна контрольная точка
#pragma mark - рисование квадратичной кривой Безье
- (void)drawSecondBezierPath {
UIBezierPath *path = [UIBezierPath bezierPath];
// сначала устанавливаем начальную точку
[path moveToPoint:CGPointMake(20, self.frame.size.height - 100)];
// добавляем квадратичную кривую
[path addQuadCurveToPoint:CGPointMake(self.frame.size.width - 20, self.frame.size.height - 100) controlPoint:CGPointMake(self.frame.size.width / 2, 0)];
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
[path stroke];
}
Шаги для рисования квадратичной кривой Безье:
- Сначала установите начальную точку, используя
moveToPoint:
.
addQuadCurveToPoint:controlPoint:
, чтобы установить конечную и контрольную точки для рисования квадратичной кривой. В запросе используется язык Objective-C.В эффекте изображение начальная точка моста слева — это установленная нами начальная точка, а самая правая конечная точка — это установленный нами конечный пункт, и мы установили контрольную точку как (width / 2, 0)
, что соответствует горизонтальному направлению в центре и вертикальному направлению вверху в красном прямоугольнике.
Этот стиль выглядит очень похоже на функции sin
или cos
, но это только частные случаи, на самом деле можно нарисовать любую фигуру, просто не могу придумать, нет ничего невозможного.
Кривая Безье обязательно проходит через начальную и конечную точки, называемые концами; хотя промежуточные точки не обязательно проходят через них, они играют роль в ограничении формы кривой, называемой контрольной точкой. Что касается контрольных точек кубической кривой Безье, посмотрите на рисунок ниже:
Подсказка: его состав — начальная конечная точка + контрольная точка 1 + контрольная точка 2 + конечная конечная точка.
Следующий метод является ключевым методом рисования кубической кривой Безье с использованием трёх точек для рисования сегмента кривой, обычно в сочетании с moveToPoint:
.
- (void)addCurveToPoint:(CGPoint)endPoint
controlPoint1:(CGPoint)controlPoint1
controlPoint2:(CGPoint)controlPoint2
Реализация кода следующая:
#pragma mark - Рисование кубической кривой Безье
- (void)drawThirdBezierPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
// Устанавливаем начальную конечную точку
[path moveToPoint:CGPointMake(20, 150)];
[path addCurveToPoint:CGPointMake(300, 150)
controlPoint1:CGPointMake(160, 0)
controlPoint2:CGPointMake(160, 250)];
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
path.lineWidth = 5.0;
UIColor *strokeColor = [UIColor redColor];
[strokeColor set];
[path stroke];
}
Здесь мы должны обратить внимание на то, что определённая начальная конечная точка равна (20,150)
, конечная конечная точка равна (300, 150)
, а горизонтальное направление одинаково. Координаты контрольной точки 1 равны (160,0)
, и она находится примерно в середине горизонтального направления. Этот параметр можно настроить. Координаты контрольной точки 2 равны (160,250)
. Если взять прямую линию между двумя конечными точками за горизонтальную линию, то это будет 250-150=100
, то есть 100
ниже горизонтальной линии. Это выглядит как функция sin
.
CAShapeLayer
наследуется от CALayer
, поэтому можно использовать все свойства CALayer
. Однако CAShapeLayer
имеет смысл использовать только вместе с кривой Безье.
Официальный документ
The shape layer draws a cubic Bezier spline in its coordinate space.The spline is described using a CGPath object and may have both fill and stroke components (in which case the stroke is composited over the fill). The shape as a whole is composited between the layer's contents and its first sublayer.
Приведённое выше является лишь частью содержания, поскольку оно слишком длинное, здесь представлена только часть. Здесь говорится, что CAShapeLayer
рисует кривую Безье в своей системе координат. Поэтому при использовании CAShapeLayer
необходимо использовать UIBezierPath
.
// CAShapeLayer рисует путь
@property(nullable) CGPathRef path;
// Путь заполнения цвета
@property(nullable) CGColorRef fillColor;
// Правила заполнения
@property(copy) NSString *fillRule;
// Цвет кисти (цвет пути, цвет рамки)
@property(nullable) CGColorRef strokeColor;
// Это набор значений диапазона, диапазон начала и конца рисования пути (0 -> 1)
@property CGFloat strokeStart;
@property CGFloat strokeEnd;
// Установить начальное расстояние для отображения пунктирной линии, установить 8, чтобы отобразить линию длиной 8 после
@property CGFloat lineDashPhase;
// Установите длину и интервал сегментов пунктирной линии, @[@20,@30,@40,@50], нарисуйте 20 пробелов 30 нарисуйте 40 пробелов 50
@property(nullable, copy) NSArray *lineDashPattern;
// Следующие атрибуты см. в описании UIBezierPath.
@property CGFloat lineWidth;
@property CGFloat miterLimit;
@property(copy) NSString *lineCap;
@property(copy) NSString *lineJoin;
У него есть атрибут path
, а UIBezierPath
— это инкапсуляция типа CGPathRef
, поэтому их можно использовать вместе!
CAShapeLayer
— это слой подкласса, который рисует векторные графики вместо растровых изображений. Можно указать цвет, ширину линии и другие атрибуты, использовать CGPath
, чтобы определить график, который нужно нарисовать, и CAShapeLayer
автоматически визуализирует его. Конечно, вы также можете использовать Core Graphics
, чтобы напрямую рисовать путь к исходному содержимому CALyer
, по сравнению с этим использование CAShapeLayer
имеет следующие преимущества:
CAShapeLayer
использует аппаратное ускорение, рисование одной и той же графики намного быстрее.CAShapeLayer
не нужно создавать графику, как обычный CALayer
, поэтому независимо от того, насколько она велика, она не занимает слишком много памяти.CAShapLayer
может быть нарисована вне границы. Ваш путь слоя не будет обрезан, как в обычном CALayer
с использованием Core Graphics
.CAShapeLayer
, он не станет пиксельным, как обычная графика слоя с изображением.drawRect
drawRect:
принадлежит CoreGraphics
фреймворку, потребляет ресурсы процессора, производительность большая, не рекомендуется переписывать.
CAShapeLayer
: принадлежит CoreAnimation
фреймворк, использует GPU для рендеринга графики, экономит производительность. Анимация рендерится непосредственно на графический процессор телефона, без потребления памяти.
Эти два имеют свои собственные цели использования, а не то, что с появлением CAShapeLayer
больше не нужен drawRect
.
Подсказка:
drawRect
— это всего лишь метод, принадлежащийUIView
, переписав этот метод, можно реализовать функцию рисования графики.
CAShapeLayer
и UIBezierPath
CAShapeLayer
содержит слово «форма», поэтому ему нужна форма, чтобы иметь эффект.
Кривая Безье может создавать основанный на векторе путь, а UIBezierPath
является инкапсуляцией CGPathRef
.
Кривая Безье предоставляет путь для CAShapeLayer
, который визуализируется в предоставленном пути. Путь замкнут, поэтому нарисован Shape
.
Используется кривая Безье для CAShapeLayer
, путь которой представляет собой замкнутую кривую, даже если кривая Безье не является замкнутой кривой. Рисование круга
#pragma mark - Рисование прямоугольника
- (CAShapeLayer *)drawRect {
CAShapeLayer *circleLayer = [CAShapeLayer layer];
// Указание frame, только для установки ширины и высоты
circleLayer.frame = CGRectMake(0, 0, 100, 200);
// Установка центрированного отображения
circleLayer.position = self.view.center;
// Установка цвета заливки
circleLayer.fillColor = [UIColor greenColor].CGColor;
// Установка ширины линии
circleLayer.lineWidth = 2.0;
// Установка цвета линии
circleLayer.strokeColor = [UIColor redColor].CGColor;
// Использование UIBezierPath для создания пути
CGRect frame = CGRectMake(0, 0, 100, 200);
UIBezierPath *rectPath = [UIBezierPath bezierPathWithRect:frame];
// Настройка связи CAShapeLayer с UIBezierPath
circleLayer.path = rectPath.CGPath;
// Размещение CAShaperLayer на определённом слое для отображения
[self.view.layer addSublayer:circleLayer];
return circleLayer;
}
Обратите внимание, что здесь мы не вызываем метод drawRect:
. Мы напрямую размещаем этот CAShaperLayer
на self.view.layer
и сразу же отображаем его.
Мы создаём CAShapeLayer
, затем настраиваем соответствующие свойства, после чего используем метод класса UIBezierPath
для создания внутреннего кругового пути, а затем присваиваем путь CAShapeLayer.path
, связывая их вместе. Наконец, мы размещаем этот слой на self.view.layer
для отображения.
Эффект прогресса
#pragma mark - Эффект прогресса
- (void)drawProgress {
CAShapeLayer *grayLayer =[CAShapeLayer layer];
UIBezierPath *grayPath = [UIBezierPath bezierPathWithArcCenter:self.view.center
radius:60
startAngle:M_PI * 3 / 2
endAngle:M_PI * 7 / 2
clockwise:YES];
grayLayer.path = grayPath.CGPath;
grayLayer.strokeColor = [UIColor grayColor].CGColor;
grayLayer.fillColor = [UIColor clearColor].CGColor;
grayLayer.lineWidth = 3;
[self.view.layer addSublayer:grayLayer];
grayLayer.strokeStart = 0;
grayLayer.strokeEnd = 1;
CAShapeLayer *greenLayer = [CAShapeLayer layer];
UIBezierPath *greenPath = [UIBezierPath bezierPathWithArcCenter:self.view.center
radius:60
startAngle:M_PI * 3 / 2
endAngle:M_PI * 7 / 2
clockwise:YES];
greenLayer.path = greenPath.CGPath;
greenLayer.strokeColor = [UIColor greenColor].CGColor;
greenLayer.fillColor = [UIColor clearColor].CGColor;
greenLayer.lineWidth = 3;
[self.view.layer addSublayer:greenLayer];
greenLayer.strokeStart = 0;
greenLayer.strokeEnd = 1;
// Добавление анимации
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.duration = 3.0;
animation.fromValue = @(0);
animation.toValue = @(1);
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[greenLayer addAnimation:animation forKey:nil];
}
Простой эффект загрузки
#pragma mark - Эффект загрузки
- (void)drawLoading {
UIView *loadingView = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-50, self.view.frame.size.height/2-50, 100, 100)];
[self.view addSubview:loadingView];
// Внешняя вращающаяся анимация
CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.fromValue = @0.0;
rotationAnimation.toValue = @(2 * M_PI);
rotationAnimation.repeatCount = HUGE_VALF;
rotationAnimation.duration = 3.0;
rotationAnimation.beginTime = 0.0;
[loadingView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
// Внутренняя анимация индикатора выполнения
CABasicAnimation *strokeAnim1 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
strokeAnim1.fromValue = @0.0;
strokeAnim1.toValue = @1.0;
strokeAnim1.duration = 1.0;
``` ```
strokeAnim1.beginTime = 0.0;
strokeAnim1.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
// 内层进度条动画
CABasicAnimation *strokeAnim2 = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
strokeAnim2.fromValue = @0.0;
strokeAnim2.toValue = @1.0;
strokeAnim2.duration = 1.0;
strokeAnim2.beginTime = 1.0;
strokeAnim2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.duration = 2.0;
animGroup.repeatCount = HUGE_VALF;
animGroup.fillMode = kCAFillModeForwards;
animGroup.animations = @[strokeAnim1, strokeAnim2];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(3, 3, CGRectGetWidth(loadingView.frame)-3*2, CGRectGetHeight(loadingView.frame)-3*2)];
self.loadingLayer = [CAShapeLayer layer];
self.loadingLayer.lineWidth = 3;
self.loadingLayer.lineCap = kCALineCapRound;
self.loadingLayer.strokeColor = [UIColor greenColor].CGColor;
self.loadingLayer.fillColor = [UIColor clearColor].CGColor;
self.loadingLayer.strokeStart = 0.0;
self.loadingLayer.strokeEnd = 1.0;
self.loadingLayer.path = path.CGPath;
[self.loadingLayer addAnimation:animGroup forKey:@"strokeAnim"];
[loadingView.layer addSublayer:self.loadingLayer];
}
Мы должны реализовать этот эффект с помощью свойств strokeStar
и strokeEnd
. Давайте посмотрим официальное описание:
Эти значения определяют подобласть пути, используемую для рисования обведённого контура. Значения должны быть в диапазоне [0,1], где ноль представляет начало пути, а единица — конец. Значения между нулём и единицей линейно интерполируются по длине пути. По умолчанию
strokeStart
равен нулю, аstrokeEnd
— единице. Оба свойства можно анимировать.
Здесь указано, что диапазон этих двух значений — [0,1]. Когда значение strokeStart
равно нулю и постепенно становится равным единице, мы видим, как путь постепенно исчезает.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )