Bir UIView'a perspektif dönüşümünü nasıl uygularım?


199

Bir UIView (coverflow'da görüldüğü gibi) üzerinde bir perspektif dönüşümü gerçekleştirmek istiyorum

Anyonew bunun mümkün olup olmadığını biliyor mu?

Kullanarak araştırdım CALayerve tüm pragmatik programcı Core Animation podcast'leri çalıştırdım, ancak bir iPhone'da bu tür bir dönüşümün nasıl oluşturulacağı konusunda hala net değilim.

Herhangi bir yardım, işaretçi veya örnek kod parçacıkları gerçekten takdir edilecektir!


Bunun sizin için uygun olup olmadığından emin değilim ama animasyon yaptığımda,
m14'ün

Teşekkürler! - bunu hangi değerleri veriyorsunuz?
Nick Cartwright

1
M14'ü ayarlayarak, X eksenindeki görünüm frustumunu tuhaf bir şekilde eğersiniz. Matematik mükemmel bir şekilde geçerlidir, ancak genel durumda bir tür kafa karıştırıcı olacaktır.
kabarık

M34 alanının kapsamlı bir açıklaması da dahil olmak üzere CALayer 3D dönüşümü ve perspektifi hakkında çok, çok iyi bir makale bu mükemmel makalede bulunabilir: çekirdek-animasyon-3d-model
Markus

Yanıtlar:


329

Ben'in dediği gibi, UIView'skatmanı kullanarak çalışmak için a'yı kullanmanız CATransform3Dgerekir layer's rotation. Burada açıklandığı gibi perspektif çalışması için hile cells, CATransform3D(m34) matrisinden birine doğrudan erişmektir. Matris matematik hiç benim işim olmadı, bu yüzden bunun neden işe yaradığını tam olarak açıklayamıyorum, ama işe yarıyor. Bu değeri ilk dönüşümünüz için negatif bir kesire ayarlamanız ve ardından katman dönüş dönüşümlerinizi buna uygulamanız gerekir. Ayrıca aşağıdakileri de yapabilmeniz gerekir:

Objective-C

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;

Swift 5.0

if let myView = self.subviews.first {
    let layer = myView.layer
    var rotationAndPerspectiveTransform = CATransform3DIdentity
    rotationAndPerspectiveTransform.m34 = 1.0 / -500
    rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 45.0 * .pi / 180.0, 0.0, 1.0, 0.0)
    layer.transform = rotationAndPerspectiveTransform
}

katman dönüşümü her dönüş için sıfırdan yeniden oluşturulur.

Bunun tam bir örneği (kodlu) burada bulunabilir , burada CALayersBill Dudney'nin bir örneğine dayanarak, bir kaçına dokunmaya dayalı döndürme ve ölçeklendirme uyguladım. Sayfanın en altındaki programın en yeni sürümü bu tür bir perspektif işlemi uygular. Kodun okunması oldukça basit olmalıdır.

sublayerTransformEğer cevap olarak adlandırdıkları, aramalarınızdan alt katmanlar uygulandığına dikkat dönüşümü olduğunu UIView's CALayer. Alt katmanınız yoksa endişelenmeyin. Benim örneğimde sublayerTransform'u kullanıyorum çünkü CALayersdöndürdüğüm bir katmanın içinde iki tane var .


1
Teşekkürler Brad - sen bir yıldızsın. Not: Mükemmel cevabınızın geç geçtiği için özür dileriz! Nick.
Nick Cartwright

Bu benim için iyi çalışıyor, ancak görüntümün yarısını (dikey bir bölüm boyunca) kaybediyor görünüyorum - bazen LHS, bazen RHS.
iPadDeveloper2011

18
@ iPadDeveloper2011 - Oranlar, aynı düzlemde başka bir opak görünüm veya katman olduğunda bir görünümü veya katmanı döndürmeye çalışıyorsunuz. Görünümünüzün veya katmanınızın ekrandan uzağa yansıyan yarısı, bu diğer görünümün altında olacak ve böylece gizlenecektir. Bunu önlemek için görünüm hiyerarşinizi yeniden sıralayabilir veya ön plan görünümünüzü kesen görünümden yeterince yükseğe taşımak için zPosition özelliğini kullanabilirsiniz.
Brad Larson

26
FYI, m34 hücresinin perspektif dönüşümünü etkilemesinin nedeni, matristeki dünya uzay Z değerinin klip uzay W değerine (perspektif projeksiyonu için kullanılan) nasıl eşlendiğini etkileyen hücredir. Daha fazla bilgi için homojen dönüşüm matrislerini okuyun.
kabarık

2
@uerceg - Bunu ayrı bir soru olarak, tercihen neler olduğunu ve ne olmak istediğinizi gösteren resimlerle sormak isteyeceksiniz.
Brad Larson

7

UIView'in transform özelliğine doğrudan uygulanan Çekirdek Grafik (yalnızca Kuvars, 2D) dönüşümlerini kullanabilirsiniz. Kapak akışındaki efektleri elde etmek için, 3 boyutlu uzayda uygulanan CATransform3D'yi kullanmanız ve böylece istediğiniz perspektif görünümünü vermeniz gerekir. Görünümlere değil, yalnızca katmanlara CATransform3D uygulayabilirsiniz, bu nedenle bunun için katmanlara geçmeniz gerekir.

Xcode ile birlikte gelen "CovertFlow" örneğine bakın. Sadece mac (iPhone için değil), ancak birçok kavram iyi aktarılıyor.


/ Geliştirici / Örneklerde bu coverflow örneğini arıyorum, başarı olmadan, nerede bulabilirim?
Alex

Aslında "CovertFlow", ve içinde / Geliştirici / Örnekler / Kuvars / Çekirdek Animasyon / "
Ben Gottlieb

2

Brad'in cevabına eklemek ve somut bir örnek vermek için, benzer bir konuyla ilgili başka bir gönderide kendi cevabımı ödünç alıyorum . Benim cevap olarak, ben basit Swift oluşturulan oyun alanı sen ki indirip oynamak ı tabakaların basit hiyerarşi ile UIView perspektif efektleri oluşturmak için nasıl göstermek ve ben kullanmak arasındaki farklı sonuçlar göstermektedir nerede transformve sublayerTransform. Bunu kontrol et.

İşte yazıdan bazı görüntüler:

.sublayerTransform seçeneği

.transform seçeneği


1
Kod metin olarak gönderilmelidir. Bir görüntüdeki kodu okumak gerçekten zor. Ayrıca resimdeki koda başvurulamaz, kopyalanamaz veya aranamaz.
rmaddy

@rmaddy, cevabımda Bitbucket bağlantısında kod var.
HuaTham

1
Bağlantılar zamanla kötüleşir. Önemli kodu doğrudan cevaba metin olarak yapıştırmak her zaman en iyisidir.
rmaddy

-1

İCarousel SDK kullanarak doğru Atlıkarınca efekti elde edebilirsiniz.

Muhteşem ve ücretsiz iCarousel kütüphanesini kullanarak iOS'ta anında Cover Flow efekti elde edebilirsiniz. Https://github.com/nicklockwood/iCarousel adresinden indirebilir ve bir köprü başlığı (Objective-C ile yazılmış) ekleyerek Xcode projenize oldukça kolay bir şekilde bırakabilirsiniz.

Daha önce bir Swift projesine Objective-C kodu eklemediyseniz, aşağıdaki adımları izleyin:

  • İCarousel'i indirin ve sıkıştırmasını açın
  • Sıkıştırdığınız klasöre gidin, iCarousel alt klasörünü açın, ardından iCarousel.h ve iCarousel.m dosyasını seçin ve bunları proje navigasyonunuza sürükleyin - bu Xcode'daki sol bölmedir. Info.plist'in hemen altında sorun yok.
  • "Gerekiyorsa öğeleri kopyala" yı işaretleyin ve Son'u tıklayın.
  • Xcode size "Objective-C köprüleme üstbilgisi yapılandırmak ister misiniz?" "Köprü Oluşturma Başlığı Oluştur" u tıklayın Projenizde ProjenizAdı-Bridging-Header.h adlı yeni bir dosya görmelisiniz.
  • Bu satırı dosyaya ekleyin: #import "iCarousel.h"
  • Projenize iCarousel ekledikten sonra kullanmaya başlayabilirsiniz.
  • Hem iCarouselDelegate hem de iCarouselDataSource protokollerine uyduğunuzdan emin olun.

Swift 3 Örnek Kodu:

    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
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.