Подтвердить что ты не робот

Установка правильного кадра только что созданного CAShapeLayer

Короче:

  • Apple НЕ устанавливает frame или bounds для CAShapeLayer автоматически (и Apple НЕ реализовала эквивалент [UIView sizeThatFits])
  • Если вы установите фрейм, используя размер ограничивающей рамки пути... все идет не так. Независимо от того, как вы пытаетесь установить его, он закручивает путь

Итак, какой правильный способ программно установить фрейм вновь созданного CAShapeLayer с недавно добавленным CGPath? Apple docs молчат по этому вопросу.

Вещи, которые я пробовал, которые не работают:

  • Создайте CAShapeLayer
  • Создайте CGPath, добавьте его в слой
  • Проверьте слой frame - it {{0,0},{0,0}}
  • Установить: layer.frame = CGPathGetBoundingBox( layer.path )
  • Теперь кадр корректен, но путь теперь DOUBLE offset - изменение frame приводит к тому, что путь для эффективного смещения добавляется дополнительно (x,y) пикселей

  • Установить: layer.bounds = CGPathGetBoundingBox( layer.path )

  • ... все идет с ума. Ничто не имеет смысла больше
  • Попробуйте исправить его, выполнив layer.position = CGPathGetBoundingBox( layer.path ).origin
  • ... нет кубиков; все еще орехи.

Одна вещь, с которой я пытался работать DID, но вызывает проблемы в другом месте:

EDIT: этот BREAKS, как только вы автоматически поворачиваете экран. Мое предположение: автоматический поворот Apple требует управления свойством "transform".

  • Создайте CAShapeLayer
  • Создайте CGPath, добавьте его в слой
  • Проверьте рамку слоя - it {{0,0},{0,0}}
  • Установить: layer.frame = CGPathGetBoundingBox( layer.path )
  • Set: layer.transform = CGAffineTransformMakeTranslation( CGPathGetBoundingBox( layer.path ).origin.x * -1, // same for y-coord: set it to "-1 * the path origin

Это работает, но... много стороннего кода предполагает, что исходным преобразованием для CALayer является Identity.

Это не должно быть так сложно! Наверняка там что-то я здесь делаю неправильно?

(У меня было одно предложение: "каждый раз, когда вы добавляете путь, вручную запускайте пользовательскую функцию, чтобы сдвинуть все точки на -1 * (top-left-point.x, top-left-point.y)". Опять же, это работает - но это смехотворно сложно)

4b9b3361

Ответ 1

Настройка layer.bounds для границ пути - это правильная вещь - вы хотите, чтобы локальное координатное пространство слоя соответствовало пути. Но вам также необходимо установить свойство position layer, чтобы переместить его в нужное место в своем суперслое.

(Установка .frame преобразуется в фреймворк, вычисляющий правильные значения .bounds и .position для вас, но всегда оставляет bounds.origin нетронутым, что не то, что вы хотите, когда ваши границы пути имеют ненулевое начало. )

Итак, что-то вроде этого должно работать, предполагая, что вы не изменили anchorPoint из его обычного значения (.5,.5) и хотите поместить слой в исходное состояние своего суперслоя:

CGRect r = CGPathGetBoundingBox(layer.path);
layer.bounds = r;
layer.position = CGPointMake(r.size.width*.5, r.size.height*.5);