SCNNode到底應該怎麼貼圖?UIImage,UIImageView,CALayer用哪一個?

SCNNode 貼圖類型

在 AR 開發中,咱們常常會給物體貼圖,好比:swift

planeNode.geometry?.firstMaterial?.diffuse.contents = image
cubeNode.geometry?.firstMaterial?.diffuse.contents = image
複製代碼

這樣子,可是 SCNNode 類型支持的貼圖有不少種,官方文檔中說明中主要有:UIColor,UIImage, CALayer,NSURL,SKScene,SKTexture...甚至還支持AVCaptureDevice相機和AVPlayer播放視頻。數組

實際開發中,我還發現 UIView 也是支持的,size 須要取整,否則可能崩潰。另外我還發現 UIView 做爲貼圖,疑似存在內存泄露的問題:View 和 Node 都銷燬了,但 app 的總內存卻不斷上漲。bash

蘋果官方目前(至 iOS13)都並不推薦貼圖使用 UIView 類,可能會有潛在的佈局問題,內存問題等。蘋果論壇上官方員工的回覆forums.developer.apple.com/message/340… session

This can be a color (NSColor, UIColor, CGColorRef), 
an image (NSImage, UIImage, CGImageRef),
a layer (CALayer), a path (NSString or NSURL), a SpriteKit scene (SKScene),
a texture (SKTexture, id<MTLTexture> or GLKTextureInfo), 
or a floating value between 0 and 1 (NSNumber) for metalness and roughness properties. 
AVCaptureDevice is supported on iOS 11 and AVPlayer is supported on macOS 10.13, iOS 11 and tvOS 11.
複製代碼

那麼咱們在實際開發中應該用哪一個?它們有什麼區別呢?app

下面咱們主要來嘗試理解一下UIImage,UIImageView,UIScrollView 及 CALayer 這三種類型的區別。框架

UIImage

首先是UIImage,貼圖後效果以下 佈局

能夠看到,圖片做爲貼圖時,能夠真實還原圖片中每一個像素的顏色,當形狀不一致時,默認會被拉伸鋪滿。

動畫支持

UIImage自己沒法進行動畫,不過contentsTransform屬性是Animatable的,惋惜我測試沒反應,不知道是否是 UIImage 類型壓根就不支持動畫。。。測試

UIImageView

UIImageView 的貼圖方式是根據 Frame 的值進行的。好比 x 與 y 的偏移量會影響貼圖的原點。而 size 則決定了清晰度,當 size 爲width: 30, height: 30 時,而立方體寬高 1 米時效果以下。 動畫

當拉伸時,也會被拉伸平鋪,當 x 或 y 方向有偏移時,則會一邊空出一段距離,而另外一側被截斷。好比長方體中上面空了,下面被截斷了: spa

動畫支持

UIImageView 做爲 UIView 的子類,在平時開發中是支持 UIView 動畫和 CAAnimation 動畫。可是在 SCNNode 貼圖中,這兩種動畫都無效。

能夠用定時器去改變 UIImageView 的 frame 值來改變貼圖大小和位置,可是沒有過渡動畫。

contentsTransform屬性測試仍是沒反應,誰知道這個怎麼用。。。

UIScrollView

UIScrollView 本質上和 UIImageView 是同樣的,可是平時開發中除了UIView 動畫和 CAAnimation 動畫,它還有 Scroll 的動畫。

這個支持怎麼樣?咱們來測試一下

看來支持的效果很好。終於能在 SCNNode 的貼圖上用上動畫效果了!

CALayer

因爲 CALayer 通常是從 UIView 中抽出來的,咱們就直接用前面 UIImageView 和 UIScrollView 的 layer 進行測試。能夠看到基本表現和 UIImageView 是同樣的,只是清晰度低了不少,緣由不明:

可是,當 frame 的 x、y 有偏移時,發生偏移與截斷的形式卻並不同。下面是貼圖時 frame = CGRect(x: 0, y: 0, width: 30, height: 30),延時 5 秒後frame = CGRect(x: 10, y: 0, width: 30, height: 20),可見 CALayer 與 UIView 的座標系仍是不一樣。

動畫支持

在平時開發中,CALayer 是重要的動畫層,能夠完成不少動畫效果,可是在貼圖時,發現全部 CALayer 動畫都沒法正常顯示。那麼 UIScrollView 的 layer 呢?它是否還能正常顯示 scroll 的動畫效果?

下面爲了更好區分滾動先後的圖片,我將第二張圖片設置爲UIImage(),顯示爲黑色。

能夠看出來,CALyer 只能顯示 UIScrollView 滾動前和滾動後的圖像,不顯示中間的滾動過程動畫。

蘋果官方對貼圖動畫的說明 官方說明了動畫的三種途徑:視頻,CALayer 的 sublayer 動畫,SpriteKit

同時說明了,若是是 UIView 的 layer 也是能夠的,可是不能已經在其餘地方顯示過。

也就是說,外層 CALayer 的動畫不支持,可是手動建立 sublayer 並添加動畫是能夠的。

總結

類型 清晰度控制 偏移調整 UIView 動畫 CAAnimation Scroll 效果
UIImage 圖片自己清晰度,沒法調整 沒法偏移調整 -- -- --
UIImageView frame.size 的清晰度,可調整 可調整偏移 不支持 不支持 --
UIScrollView frame.size 的清晰度,可調整 可調整偏移 不支持 不支持 支持
CALayer 比frame.size 的清晰度更低 可調整偏移,效果不一樣 -- sublayer支持 不支持

因此,若是想在 SCNNode 的貼圖上顯示平面動畫,可考慮用:

  • gif 方式或 image 數組
  • UIScrollView 滾動方式(官方不推薦)
  • 逐幀調整 UIView 或子類的 frame/color 值(官方不推薦)
  • AVPlayer 播放視頻(官方推薦)
  • CALayer 的 sublayer 動畫(官方推薦)
  • SKScene 即 SpriteKit 框架的 scene(官方推薦)
    • 蘋果在WWDC2017 的 session609 裏演示過

其中功能最強大的就是 SpriteKit 框架了,它是蘋果的 2D 遊戲開發框架,能夠開發出各類你想要的動畫效果。可是這個框架不多有人用吧

相關文章
相關標籤/搜索