¿Cómo puedo aplicar una transformación de perspectiva a una UIView?


Estoy buscando realizar una transformación de perspectiva en un UIView (como se ve en coverflow)

¿Sabe alguien nuevo si esto es posible?

He investigado el uso de CALayer y he corrido a través de todos los podcasts de animación Programmer Core pragmatic, pero todavía no estoy más claro sobre cómo crear este tipo de transformación en un iPhone.

Cualquier ayuda, punteros o fragmentos de código de ejemplo sería muy apreciado!

Author: Brad Larson, 2008-12-07

4 answers

Como dijo Ben, tendrá que trabajar con la capa de UIView, utilizando un CATransform3D para realizar la rotación de la capa. El truco para que la perspectiva funcione, como se describe aquí, es acceder directamente a una de las celdas matriciales del CATransform3D (m34). La matemática matricial nunca ha sido lo mío, así que no puedo explicar exactamente por qué funciona, pero funciona. Necesitará establecer este valor en una fracción negativa para su transformación inicial, luego aplique sus transformaciones de rotación de capa a eso. Usted también debe ser capaz de hacer lo siguiente:

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;

Que reconstruye la transformación de capa desde cero para cada rotación.

Un ejemplo completo de esto (con código) se puede encontrar aquí, donde he implementado la rotación y el escalado táctiles en un par de CALayers, basado en un ejemplo de Bill Dudney. La versión más reciente del programa, en la parte inferior de la página, implementa este tipo de operación de perspectiva. El código debe ser razonablemente fácil de leer.

El sublayerTransform a la que se refiere en su respuesta es una transformación que se aplica a las subcapas de su UIView CALayer. Si no tienes subcapas, no te preocupes. Utilizo el sublayerTransform en mi ejemplo simplemente porque hay dos capas contenidas dentro de la capa que estoy rotando.

 321
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-21 14:04:57

Solo puede usar transformaciones Core Graphics (Quartz, solo 2D) aplicadas directamente a la propiedad transform de UIView. Para obtener los efectos en coverflow, tendrás que usar CATransform3D, que se aplican en espacio 3D, y así te puede dar la vista en perspectiva que deseas. Solo puede aplicar CATransform3Ds a capas, no a vistas, por lo que tendrá que cambiar a capas para esto.

Echa un vistazo a la muestra "CovertFlow" que viene con Xcode. Es solo para mac (es decir, no para iPhone), pero muchos de los los conceptos se transfieren bien.

 7
Author: Ben Gottlieb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-07 17:43:09

Para agregar a la respuesta de Brad y proporcionar un ejemplo concreto, tomo prestado de mi propia respuesta en otro post sobre un tema similar. En mi respuesta, creé un simple Swift playground que puedesdescargar y jugar con , donde muestro cómo crear efectos de perspectiva de un UIView con una simple jerarquía de capas, y muestro diferentes resultados entre usar transform y sublayerTransform. Compruébelo.

Estas son algunas de las imágenes del post:

 3
Author: HuaTham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-13 19:03:45

Puede obtener un efecto de Carrusel preciso usando iCarousel SDK.

Puede obtener un efecto de Cover Flow instantáneo en iOS utilizando la maravillosa y gratuita biblioteca iCarousel. Puede descargarlo desde https://github.com/nicklockwood/iCarousel y colóquelo en su proyecto Xcode con bastante facilidad agregando un encabezado de puente (está escrito en Objective-C).

Si no ha agregado código Objective-C a un proyecto Swift antes, siga estos pasos:

  • Descargar iCarousel y descomprimirlo
  • Vaya a la carpeta que descomprimió, abra su subcarpeta iCarousel y luego seleccione iCarousel.h e iCarousel.m y arrástrelos a la navegación de su proyecto, que es el panel izquierdo en Xcode. Justo debajo de Info.plist está bien.
  • Marque "Copiar elementos si es necesario" y luego haga clic en Finalizar.
  • Xcode le preguntará con el mensaje "¿Le gustaría configurar un encabezado de puente de Objective-C?"Haga clic" Crear Encabezado de Puente" Debería ver un nuevo archivo en su proyecto, llamado YourProjectName-Bridging-Header.h.
  • Agregue esta línea al archivo: #import "iCarousel.h "
  • Una vez que haya agregado iCarousel a su proyecto, puede comenzar a usarlo.
  • Asegúrese de cumplir con los protocolos iCarouselDelegate e iCarouselDataSource.

Swift 3 Código de ejemplo:

    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
    }
 0
Author: Tech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-21 11:43:29