Как применить перспективное преобразование к UIView? - PullRequest
198 голосов
/ 07 декабря 2008

Я хочу выполнить перспективное преобразование в UIView (например, в coverflow)

Кто-нибудь еще знает, возможно ли это?

Я исследовал использование CALayer и пробежался по всем прагматичным подкастам Core Animation для программиста, но я до сих пор не понимаю, как создать этот вид преобразования на iPhone.

Любая помощь, указатели или примеры фрагментов кода будут очень полезны!

Ответы [ 4 ]

323 голосов
/ 09 декабря 2008

Как сказал Бен, вам нужно будет работать со слоем UIView, используя CATransform3D для выполнения вращения слоя. Хитрость для работы в перспективе, как описано здесь , заключается в прямом доступе к одной из ячеек матрицы CATransform3D (m34). Математическая математика никогда не была моей вещью, поэтому я не могу точно объяснить, почему это работает, но это работает. Вам нужно будет установить это значение в отрицательную дробь для вашего первоначального преобразования, а затем применить к нему преобразования вращения слоя. Вы также должны быть в состоянии сделать следующее:

UIView *myView = [[self subviews] objectAtIndex:0];
CALayer *layer = myView.layer;
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -500;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 45.0f * M_PI / 180.0f, 0.0f, 1.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;

, который восстанавливает преобразование слоя с нуля для каждого поворота.

Полный пример этого (с кодом) можно найти здесь , где я реализовал ротацию и масштабирование на основе касания для пары CALayers на основе примера Билла Дадни. Самая новая версия программы, в самом низу страницы, реализует такую ​​перспективную операцию. Код должен быть достаточно простым для чтения.

ПодслойПреобразование, на которое вы ссылаетесь в своем ответе, является преобразованием, которое применяется к подуровням вашего UIView CALayer. Если у вас нет подслоев, не беспокойтесь об этом. Я использую sublayerTransform в моем примере просто потому, что в одном вращающемся слое содержатся два слоя CALay.

7 голосов
/ 07 декабря 2008

Вы можете использовать только преобразования Core Graphics (Quartz, 2D), непосредственно примененные к свойству преобразования UIView. Чтобы получить эффекты в coverflow, вы должны будете использовать CATransform3D, которые применяются в трехмерном пространстве, и, следовательно, могут дать вам перспективный вид, который вы хотите. Вы можете применять CATransform3D только к слоям, но не к видам, поэтому для этого вам придется переключиться на слои.

Проверьте образец "CovertFlow", который идет с Xcode. Это только для Mac (т.е. не для iPhone), но многие концепции хорошо переносятся.

3 голосов
/ 10 марта 2017

Чтобы добавить ответ Брэда и привести конкретный пример, я заимствую у мой собственный ответ в другом посте на аналогичную тему. В своем ответе я создал простую игровую площадку Swift, которую вы можете скачать и поиграть с , где я продемонстрирую, как создавать эффекты перспективы UIView с простой иерархией слоев, и я показываю разные результаты при использовании transform и sublayerTransform. Проверьте это.

Вот некоторые изображения из поста:

.sublayerTransform option

.transform option

0 голосов
/ 21 декабря 2017

Точный эффект Карусели можно получить с помощью iCarousel SDK.

Вы можете получить мгновенный эффект Cover Flow на iOS, используя замечательную и бесплатную библиотеку iCarousel. Вы можете скачать его с https://github.com/nicklockwood/iCarousel и довольно легко добавить в проект Xcode, добавив соединительный заголовок (он написан в Objective-C).

Если вы ранее не добавляли код Objective C в проект Swift, выполните следующие действия:

  • Загрузите iCarousel и распакуйте его
  • Перейдите в разархивированную папку, откройте ее подпапку iCarousel, затем выберите iCarousel.h и iCarousel.m и перетащите их в навигацию проекта - это левая панель в Xcode. Чуть ниже Info.plist в порядке.
  • Установите флажок «Копировать элементы при необходимости», затем нажмите «Готово».
  • Xcode предложит вам сообщение «Хотите настроить заголовок моста Objective-C?» Нажмите «Создать заголовок моста» В вашем проекте вы должны увидеть новый файл с именем YourProjectName-Bridging-Header.h.
  • Добавить эту строку в файл: #import "iCarousel.h"
  • Как только вы добавили iCarousel в свой проект, вы можете начать его использовать.
  • Убедитесь, что вы соответствуете протоколам iCarouselDelegate и iCarouselDataSource.

Swift 3 Образец кода:

    override func viewDidLoad() {
      super.viewDidLoad()
      let carousel = iCarousel(frame: CGRect(x: 0, y: 0, width: 300, height: 200))
      carousel.dataSource = self
      carousel.type = .coverFlow
      view.addSubview(carousel) 
    }

   func numberOfItems(in carousel: iCarousel) -> Int {
        return 10
    }

    func carousel(_ carousel: iCarousel, viewForItemAt index: Int, reusing view: UIView?) -> UIView {
        let imageView: UIImageView

        if view != nil {
            imageView = view as! UIImageView
        } else {
            imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 128, height: 128))
        }

        imageView.image = UIImage(named: "example")

        return imageView
    }
...