Мой вопрос требует небольшого пояснения. Если вы хотите перейти к вопросу, найдите вопрос, выделенный жирным шрифтом: ближе к концу.
Довольно легко создать анимацию протирания круга в iOS или Mac OS с помощью базовой анимации и масок.
Один из способов - установить CAShapeLayer в качестве маски в представлении (обычно представление изображения), установить круг в слое формы и анимировать круг от 0 размера до достаточно большого, чтобы покрыть все изображение (r = sqrt(height^2 + width^2
)
Другой способ - использовать радиальный CAGradientLayer в качестве маски, настроить центр градиента как непрозрачный цвет и иметь внезапный переход к очистке сразу за углами изображения. Затем вы анимируете значения позиций слоя градиента, чтобы переместить чистый цвет в центр изображения.
Оба этих подхода создают вытеснение круга с острыми краями, в результате чего изображение сжимается до точки и исчезает.
Этот эффект выглядит так:
Однако классическая кинематографическая анимация вытеснения круга имеет скошенный край, а не резкую границу. Внешний край круга полностью прозрачный. По мере того, как вы приближаетесь к центру, изображение становится все более и более плотным на довольно коротком расстоянии, а затем изображение становится полностью непрозрачным оттуда в центр. По мере того как круг сжимается, толщина перехода от прозрачного к непрозрачному остается постоянной, а круг воняет до точки и исчезает. (Маска представляет собой непрозрачный круг посередине и имеет слегка размытый край, а радиус круга уменьшается до 0, а толщина размытого края остается постоянной.)
Вот пример протирания круга старой школы. Технически это Iris Out, где переход к черному, но идея та же:
https://youtu.be/IqDhAW3TDR8?t=90
Я понятия не имею, как добиться кругового вытеснения со скошенным краем, используя слой-фигуру в качестве маски. Слои-фигуры всегда имеют острые края. Я мог бы подойти довольно близко, используя слой-фигуру, где круг обведен с непрозрачностью 50%, а середина круга заполнена цветом с непрозрачностью 100%, но это не приведет к плавному переходу от прозрачного к непрозрачному, который Я после.
Другой подход, который я пробовал, - использовать радиальный градиент с тремя цветами. Я установил внутренние цвета как непрозрачные, а внешний - как чистый. Я установил положение внешнего цвета как ›1 (скажем, 1.2), среднее положение - 1, а внутреннее положение - 0. Массив местоположений содержит [1.2, 1.0, 0]
, что делает всю часть маски, покрывающей изображение, непрозрачной, с плавный переход к прозрачному, который происходит за краями изображения.
Затем я делаю анимацию массива местоположений в 2 этапа. На первом этапе я анимирую массив местоположений в [0, 0, 0.2]
. Это приводит к тому, что полоса растушевки приближается к углам и останавливается на 0,2 от центра изображения.
На 2-м шаге я анимирую массив местоположений от [0, 0, 0.2]
до [0,0,0]
. Это приводит к тому, что внутренний, от прозрачного до непрозрачного, центр сжимается до точки и исчезает.
Эффект нормальный, и если я запускаю его с узкой полосой размытия и быстрой продолжительностью, он выглядит прилично, но не идеально.
Вот как это выглядит с диапазоном размытия 0,2 и продолжительностью (я думаю) 0,25 секунды:
Однако если я сделаю паузу между этапами анимации, вы увидите недостатки в эффекте:
Вопрос: есть ли способ анимировать круг с небольшим радиусом размытия (5 точек или около того) от полного размера вида до 0 с помощью Core Animation?
Тот же вопрос относится и к другим типам анимации протирания: замочная скважина, звезда, протирание сбоку, прямоугольник и многие другие. Для них трюк с радиальным градиентом, который я использую для вытеснения с перьями, вообще не сработает. (Вы создаете эти специализированные анимации протирания с помощью CAShapeLayer, который представляет собой форму, которую хотите анимировать, а затем регулируете ее размер от большого до маленького.
Было бы легко создать статический размытый круг (или другую форму), сначала нарисовав круг, а затем применив к нему фильтр размытия основного изображения, но в iOS нет способа анимировать это, а фильтр размытия CI работает слишком медленно. iOS, даже если бы вы могли.
Вот ссылка на проект, который я использовал для создания анимации в этом посте с использованием описываемого мною трехцветного радиального градиента: https://github.com/DuncanMC/GradientView.git.
Редактировать:
Основываясь на комментарии Джеймса, я попытался использовать слой-фигуру с тенью в качестве маски. Эффект находится на правильном пути, но все еще есть резкий переход от непрозрачной части изображения к большей части прозрачной части, которая маскируется теневым слоем. Даже с непрозрачностью тени 1.0 тень по-прежнему остается прозрачной. Вот как это выглядит:
Частично прозрачность цвета линии круга помогает некоторым и дает переход между непрозрачной частью изображения и большей частью прозрачной тенью. Вот изображение выше, но обводка слоя-фигуры с шириной линии 2 точки и непрозрачностью 0,6:
Редактировать # 2: РЕШЕНО!
Идея Джеймса об использовании shadowPath - это решение. Вам не нужно ничего в вашем слое маски, кроме shadowPath. Если вы это сделаете, вы можете использовать свойство shadowRadius для управления степенью размытия и плавно анимировать траекторию тени от круга, который полностью охватывает вид до точки исчезновения, за один шаг.
Я обновил свой проект github по адресу https://github.com/DuncanMC/GradientView.git, чтобы включить для сравнения анимацию радиального градиента и анимацию shadowPath.
Вот как выглядит готовый эффект, сначала с радиусом размытия 5 пикселей:
А затем с радиусом размытия 30 пикселей: