Как анимировать отрисовку массива CGpath?

Я пытаюсь создать приложение, которое рисует объект для пользователя. Теперь у меня есть один из этих объектов, который состоит из массива типа [UIBezierPath]. Затем я использую цикл, чтобы изменить все UIBezierPath в массиве на CGPath, а затем хочу анимировать эти пути, рисуемые один за другим. Однако, когда я пробую этот код сейчас, он не работает, и я не могу найти никакой полезной информации об этом в Интернете. Этот код используется для преобразования массива macbookPath, состоящего из UIBezierPath, в CGPath:

for path in macbookPath {
        drawingPath.append(path.cgPath)
    }

И затем я использую этот код, чтобы попытаться нарисовать путь:

for cgPath in drawingPath {
        shapeLayer.path = cgPath
    }

Это остальная часть кода функции drawForm(), которая должна отрисовывать форму в представлении с именем aiDrawView:

@objc func drawForm() {
    var drawingPath = [CGPath]()
    var macbookPath = Forms.MacbookForm()
    let shapeLayer = CAShapeLayer()
    shapeLayer.frame = aiDrawView.bounds

    for path in macbookPath {
        drawingPath.append(path.cgPath)
    }

    for cgPath in drawingPath {
        shapeLayer.path = cgPath
    }

    let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd")
    strokeEndAnimation.duration = 2.0
    strokeEndAnimation.fromValue = 0.0

    shapeLayer.add(strokeEndAnimation, forKey: "strokeEndAnimation")
}

Я новичок в CAShapeLayer, CABasicAnimation и UIBezierPath, поэтому буду очень признателен за любую помощь!!! :D


person Thijs van der Heijden    schedule 26.03.2018    source источник
comment
Какой эффект вам нужен? Вы хотите нарисовать первый путь, начиная с начальной точки, делая путь все длиннее и длиннее, пока не будет нарисован полный путь, а затем рисуя новый путь сверху таким же образом от начала до конца, пока все пути в ваш массив виден сразу? Вы хотите проследить один путь от начала до конца, затем стереть его и нарисовать второй путь от начала до конца?   -  person Duncan C    schedule 26.03.2018
comment
Ваш текущий код не имеет смысла по нескольким причинам. 1: ваш цикл for заменит путь вашего слоя формы каждым путем в вашем массиве до тех пор, пока путь слоя формы не будет содержать последний путь, и вы не будете рисовать ни с чем, кроме последнего пути. 2: Вы создаете CAAnimation, который отправляет fromValue в 0, но никогда не устанавливаете toValue в 1. Это должно работать, но было бы безопаснее явно установить toValue в 1.0   -  person Duncan C    schedule 26.03.2018


Ответы (1)


Я бы предложил создать один UIBezierPath из вашего массива путей, а затем анимировать его:

var paths: [UIBezierPath] = ...

let path = UIBezierPath()

paths.forEach { path.append($0) }

shapeLayer.path = path.cgPath

let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = 2.0
animation.fromValue = 0.0
shapeLayer.add(animation, forKey: nil)

Например, вот 100 путей, объединенных в один путь, чей strokeEnd затем анимируется на слое формы:

введите здесь описание изображения

Предполагая, что ваш массив путей действительно образует некоторый непрерывный путь, я мог бы предложить вместо этого сохранить его как массив CGPoint. Затем вы можете построить один путь из этого. Это устраняет накладные расходы на все эти пути. Кроме того, он открывает двери для масштабирования исходного набора данных без введения каких-либо артефактов, позволяя использовать параметры соединения строк, применять алгоритмы сглаживания если у вас есть нежелательная последовательность отрезков и т. д.

person Rob    schedule 26.03.2018
comment
Классная иллюстрация. (Проголосовали.) Как вы создали 100 подпутей? Генерировать их с помощью функции sin()? И потом, как вы создали анимацию GIF из CAAnimation? - person Duncan C; 26.03.2018
comment
Что произойдет, если пути, которые вы собираете, будут прерывистыми? Будет ли анимация штриха иметь разрывы и переходить от конца одного подпути к началу следующего в одно мгновение? Это то, что я ожидал. - person Duncan C; 26.03.2018
comment
Да, просто синусоида с sin функцией. Да, прерывистый путь тоже работает нормально, хотя я считаю, что он мгновенно перескакивает. Что касается GIF-анимации, то это просто снимок экрана симулятора QuickTime, преобразованный в GIF в Photoshop. - person Rob; 26.03.2018
comment
Спасибо приятель! Это на самом деле мне очень помогло! У меня есть еще один вопрос, потому что путь теперь отображается в левом верхнем углу моего экрана, а я хочу, чтобы он отображался в центре. Масштабирование пути было простым с использованием метода .transform, но перемещение пути намного сложнее и не работает.... - person Thijs van der Heijden; 27.03.2018
comment
Ваш прерывистый путь выглядит как обычный путь с пунктирной линией. Это не совсем прерывистый путь. - person Duncan C; 27.03.2018
comment
Смешной. Это может иметь некоторое внешнее сходство с непрерывным путем с пунктирным узором, но это не то, чем он был. Это был путь линии от точки 0 до точки 3, другой от точки 5 до точки 8, еще один от точки 10 до точки 13 и т. д. И все эти разделенные пути линий были добавлены к одному UIBezierPath и обведены стандартным сплошным штрихом. . Я просто продемонстрировал, к своему собственному удовлетворению, что прерывистый UIBezierPath работает точно так, как ожидалось. Вы не обязаны мне верить, если не хотите. ;) - person Rob; 27.03.2018
comment
Я верю тебе! Однако если бы ваш результат предназначался для общественного потребления, вы могли бы выбрать более очевидный прерывистый путь. - person Duncan C; 27.03.2018