1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/Lee_Jay-UIBezierPath_CAShapeLayer

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

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:

  1. Создайте объект UIBezierPath.
  2. Используйте метод moveToPoint:, чтобы установить начальную точку линейного сегмента.
  3. Добавьте линии или кривые, чтобы определить один или несколько подпутей.
  4. Измените свойства объекта 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.
  • (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath
Далее мы рассмотрим его применение.

**Первый метод: создание объекта**

Первый метод используется чаще, потому что созданный фабричный метод можно настроить по своему усмотрению и нарисовать любую фигуру.
```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

Шестой метод: рисование дуги

Шестой метод используется для рисования дуги. Параметры метода:

  • center — координаты точки центра дуги;
  • radius — радиус окружности, на которой лежит дуга;
  • startAngle — угол начала дуги;
  • endAngle — угол конца дуги;
  • clockwise — рисовать ли дугу по часовой стрелке.
+ (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];
}

Шаги для рисования квадратичной кривой Безье:

  1. Сначала установите начальную точку, используя moveToPoint:.
  1. Вызовите 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

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

  1. drawRect: принадлежит CoreGraphics фреймворку, потребляет ресурсы процессора, производительность большая, не рекомендуется переписывать.

  2. CAShapeLayer: принадлежит CoreAnimation фреймворк, использует GPU для рендеринга графики, экономит производительность. Анимация рендерится непосредственно на графический процессор телефона, без потребления памяти.

Эти два имеют свои собственные цели использования, а не то, что с появлением CAShapeLayer больше не нужен drawRect.

Подсказка: drawRect — это всего лишь метод, принадлежащий UIView, переписав этот метод, можно реализовать функцию рисования графики.

Отношения между CAShapeLayer и UIBezierPath

  1. CAShapeLayer содержит слово «форма», поэтому ему нужна форма, чтобы иметь эффект.

  2. Кривая Безье может создавать основанный на векторе путь, а UIBezierPath является инкапсуляцией CGPathRef.

  3. Кривая Безье предоставляет путь для CAShapeLayer, который визуализируется в предоставленном пути. Путь замкнут, поэтому нарисован Shape.

  4. Используется кривая Безье для 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 )

Вы можете оставить комментарий после Вход в систему

Введение

UIBezierPath и CAShapeLayer для рисования. Развернуть Свернуть
MIT
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/Lee_Jay-UIBezierPath_CAShapeLayer.git
git@api.gitlife.ru:oschina-mirror/Lee_Jay-UIBezierPath_CAShapeLayer.git
oschina-mirror
Lee_Jay-UIBezierPath_CAShapeLayer
Lee_Jay-UIBezierPath_CAShapeLayer
master