[Swift通天遁地]9、拔劍吧-(14)建立更美觀的景深視差滾動效果

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-qrcmtddy-bg.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

目錄:[Swift]通天遁地Swiftios

景深視差常常被應用在遊戲項目中。git

本文將演示建立更美觀的景深視差滾動效果。github

首先確保已經安裝了所需的第三方類庫。雙擊查看安裝配置文件【Podfile】swift

1 platform :ios, '12.0'
2 use_frameworks!
3 
4 target 'DemoApp' do
5     source 'https://github.com/CocoaPods/Specs.git'
6     pod 'Presentation'
7 end

根據配置文件中的相關設置,安裝第三方類庫。數組

安裝完成以後,雙擊打開項目文件【DemoApp.xcodeproj】xcode

在左側的項目導航區,打開視圖控制器的代碼文件【ViewController.swift】微信

  1 import UIKit
  2 //引入已經安裝的第三方類庫
  3 import Presentation
  4 
  5 //修改當前類的父類,這裏使用第三方類庫提供的父類
  6 class ViewController: PresentationController {
  7 
  8     //添加一個結構體類型,
  9     //用來更加方便的管理背景視圖中的視差圖片,
 10     //四個屬性依次表示:
 11     struct BackgroundImage
 12     {
 13         //圖片的名稱
 14         let name: String
 15         //水平初始位置
 16         let left: CGFloat
 17         //垂直初始位置
 18         let top: CGFloat
 19         //滾動的速度
 20         let speed: CGFloat
 21         
 22         //添加一個初始化方法,用來初始化結構體的各個屬性。
 23         init(name: String, left: CGFloat, top: CGFloat, speed: CGFloat)
 24         {
 25             //依次設置各個屬性的值
 26             self.name = name
 27             self.left = left
 28             self.top = top
 29             self.speed = speed
 30         }
 31         
 32         //添加一個方法,用來獲取當滾動到某個頁面時到位置屬性
 33         func positionAt(_ index: Int) -> Position?
 34         {
 35             //添加一個位置變量
 36             var position: Position?
 37             
 38             //判斷當前是否時是須要顯示滾動效果的頁面。
 39             if index == 0 || speed != 0.0
 40             {
 41                 //根據起始位置、當前頁面的序號、計算當前頁面的視差圖片的水平位置。
 42                 let currentLeft = left + CGFloat(index) * speed
 43                 //設置視差圖片的新的位置,視差圖片的垂直座標,是保持不變的。
 44                 position = Position(left: currentLeft, top: top)
 45             }
 46             
 47             //返回設置好的位置
 48             return position
 49         }
 50     }
 51     
 52     //添加一個導航條按鈕控件,做爲導航條左側的按鈕
 53     lazy var leftButton: UIBarButtonItem =
 54         { [unowned self] in
 55             
 56             //對導航條按鈕進行初始化操做,並設置它的標題、樣式和動做屬性。
 57             let leftButton = UIBarButtonItem(title: "Previous", style: .plain,
 58                                              target: self, action: #selector(moveBack))
 59             
 60             //設置標題的前景顏色爲黑色
 61             leftButton.setTitleTextAttributes(
 62                 [NSAttributedString.Key.foregroundColor : UIColor.black], for: .normal)
 63             
 64             //返回設置好的按鈕控件
 65             return leftButton
 66             }()
 67     
 68     //建立另外一個導航條按鈕控件,做爲導航條右側的按鈕。
 69     lazy var rightButton: UIBarButtonItem =
 70         { [unowned self] in
 71             
 72             //對導航條按鈕k進行初始化操做,並設置它的標題、樣式和動做屬性。
 73             let rightButton = UIBarButtonItem(title: "Next", style: .plain,
 74                                               target: self, action: #selector(moveForward))
 75             
 76             //設置標題文字的前景顏色爲黑色。
 77             rightButton.setTitleTextAttributes(
 78                 [NSAttributedString.Key.foregroundColor : UIColor.black], for: .normal)
 79             
 80             //返回設置好的按鈕控件。
 81             return rightButton
 82             }()
 83     
 84     override func viewDidLoad() {
 85         super.viewDidLoad()
 86         // Do any additional setup after loading the view, typically from a nib.
 87         
 88         //依次設置導航控制器左側和右側的導航按鈕。
 89         navigationItem.leftBarButtonItem = leftButton
 90         navigationItem.rightBarButtonItem = rightButton
 91         
 92         //設置根視圖的背景顏色。
 93         view.backgroundColor = UIColor(red: 1.0, green: 188.0/255, blue: 0, alpha: 1)
 94         
 95         //調用兩個方法:
 96         //方法一:用來設置滾動的標題
 97         configureSlides()
 98         //方法二:用來設置具備景深效果的背景視圖。
 99         configureBackground()
100     }
101 
102     //添加一個方法,用來配置滾動標題
103     func configureSlides()
104     {
105         //初始一個字體對象
106         let font = UIFont(name: "HelveticaNeue", size: 24.0)!
107         //初始化一個顏色對象
108         let color = UIColor(red: 1.0, green: 232.0/255, blue: 169.0/255, alpha: 1)
109         //做爲標題文字的字體和顏色。
110         
111         //初始化一個段落樣式對象
112         let paragraphStyle = NSMutableParagraphStyle()
113         //設置段落樣式的對齊方式爲居中
114         paragraphStyle.alignment = NSTextAlignment.center
115         
116         //初始化一個屬性常量,做爲標題文字的字體、顏色和段落樣式。
117         let attributes = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: color, .paragraphStyle: paragraphStyle]
118         
119         //初始化一個字符串數組,做爲五個滾動標題的內容。
120         let titles = [
121             "Parallax is a displacement or difference in the apparent position of an object viewed along two different lines of sight.",
122             "It's measured by the angle or semi-angle of inclination between those two lines.",
123             "The term is derived from the Greek word παράλλαξις (parallaxis), meaning 'alteration'.",
124             "Nearby objects have a larger parallax than more distant objects when observed from different positions.",
125             "http://www.coolketang.com"]
126             //對標題數組進行遍歷,設置標題的樣式
127             .map
128             { title -> Content in
129                 //初始化一個標籤對象,
130                 let label = UILabel(frame: CGRect(x: 0, y: 0, width: 550, height: 200))
131                 //設置標籤對象最多顯示的行數
132                 label.numberOfLines = 5
133                 //設置標籤對象顯示的文字內容,和文字的外觀樣式。
134                 label.attributedText = NSAttributedString(string: title, attributes: attributes)
135                 //初始化一個位置對象
136                 let position = Position(left: 0.0, top: 0.35)
137                 
138                 //使用標籤和位置初始化一個內容對象,並返回內容對象做爲頁面的標題
139                 return Content(view: label, position: position)
140         }
141         
142         //初始化一個滑動控制器類型的數組對象。
143         var slides = [SlideController]()
144         
145         //添加一個執行五次的循環語句,用來往數組中添加控制器。
146         for index in 0...(titles.count - 1)
147         {
148             //初始化一個滑動控制器對象,並設置它的標題內容
149             let controller = SlideController(contents: [titles[index]])
150             //往滑動控制器中,添加一個標題滾動的動畫。
151             controller.add(animations: [Content.centerTransition(forSlideContent: titles[index])])
152            
153             if(index == titles.count - 1)
154             {
155                 controller.setLast()
156             }
157             
158              //將配置好的滑動控制器,添加到數組中。
159             slides.append(controller)
160         }
161         
162         //將滑動控制器數組添加到景深視圖控制器中。
163         add(slides)
164     }
165     
166     //添加另外一個方法,用來配置具備景深效果的背景視圖。
167     func configureBackground()
168     {
169         //初始化一個圖像視圖數組,做爲背景視圖中的視差圖片。
170         let backgroundImages =
171             [
172                 //往數組中,依次添加同結構體類型,生成的九張視差圖片,
173                 //並設置每張視查圖片的名稱、位置、和速度等屬性。
174                 BackgroundImage(name: "Trees", left: 0.0, top: 0.743, speed: -0.3),
175                 BackgroundImage(name: "Bus", left: 0.02, top: 0.77, speed: 0.25),
176                 BackgroundImage(name: "Truck", left: 1.3, top: 0.73, speed: -1.5),
177                 BackgroundImage(name: "Roadlines", left: 0.0, top: 0.79, speed: -0.24),
178                 BackgroundImage(name: "Houses", left: 0.0, top: 0.627, speed: -0.16),
179                 BackgroundImage(name: "Hills", left: 0.0, top: 0.51, speed: -0.08),
180                 BackgroundImage(name: "Mountains", left: 0.0, top: 0.29, speed: 0.0),
181                 BackgroundImage(name: "Clouds", left: -0.415, top: 0.14, speed: 0.18),
182                 BackgroundImage(name: "Sun", left: 0.8, top: 0.07, speed: 0.0)
183         ]
184         
185         //添加一個內容類型的數組。
186         var contents = [Content]()
187         
188         //對視差圖片數組進行遍歷,從而建立九個視差內容,
189         //並放置在數組中。
190         for backgroundImage in backgroundImages
191         {
192             //從指定的結構體中,得到圖片的名稱,而後初始化一個指定圖片名稱的圖像視圖。
193             let imageView = UIImageView(image: UIImage(named: backgroundImage.name))
194             //得到結構體中的視差圖片的位置。
195             if let position = backgroundImage.positionAt(0)
196             {
197                 //初始化一個指定視圖、位置和中心點屬性的視差內容。而後將視差內容添加到數組中。
198                 contents.append(Content(view: imageView, position: position, centered: false))
199             }
200         }
201         
202         //將全部的視差內容添加到背景視圖中
203         addToBackground(contents)
204         
205         //添加另外一個執行五次的循環語句,給每一個頁面添加一個視差動畫。
206         for row in 1...4
207         {
208             //對數組中的視差內容進行遍歷
209             for (column, backgroundImage) in backgroundImages.enumerated()
210             {
211                 //得到視差內容,以及視差內容的當前位置。
212                 if let position = backgroundImage.positionAt(row), let content = contents.at(column)
213                 {
214                     //初始化一個過渡動畫對象,並設置動畫對象的視差內容、目標位置、動畫時長和阻尼值
215                     addAnimation(TransitionAnimation(content: content, destination: position, duration: 2.0, damping: 1.0), forPage: row)
216                 }
217             }
218         }
219         
220         //建立一個指定顯示區域的視圖對象,做爲視差背景的地面視圖
221         let groundView = UIView(frame: CGRect(x: 0, y: 0, width: 1024, height: 60))
222         //設置地面視圖的背景顏色,
223         groundView.backgroundColor = UIColor(red: 1.0, green: 205.0/255, blue: 65/255.0, alpha: 1.0)
224         //將地面視圖轉換成一個內容對象,並設置它的位置。
225         let groundContent = Content(view: groundView,
226                                     position: Position(left: 0.0, bottom: 0.063), centered: false)
227         //將地面內容對象也添加到數組中。
228         contents.append(groundContent)
229         
230         //將內容數組添加到背景視圖。
231         addToBackground([groundContent])
232     }
233 }
234 
235 //添加一個針對數組類型的擴展。
236 extension Array
237 {
238     //添加一個擴展方法,用來得到在數組中指定位置的元素。
239     func at(_ index: Int?) -> Element?
240     {
241         //建立一個元素變量。
242         var object: Element?
243         //當元素位置在數組長度範圍以內時,根據下標得到數組中的元素。
244         if let index = index , index >= 0 && index < endIndex
245         {
246             object = self[index]
247         }
248         
249         //返回得到的元素
250         return object
251     }
252 }

在左側的項目導航區,打開應用程序的代理文件【AppDelegate.swiftapp

在應用程序加載完成的方法中,建立一個導航控制器。ide

 1 import UIKit
 2 
 3 @UIApplicationMain
 4 class AppDelegate: UIResponder, UIApplicationDelegate {
 5 
 6     var window: UIWindow?
 7 
 8     func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
 9         // Override point for customization after application launch.
10         
11         //清除導航條在默認狀態下的背景圖片
12         UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
13         //清除導航條的陰影圖片
14         UINavigationBar.appearance().shadowImage = UIImage()
15         
16         //多上文建立的視圖控制器進行初始化操做。
17         let vc = ViewController(pages: [])
18         //建立一個導航控制器,並設置導航控制器的根視圖控制器
19         let navigationController = UINavigationController(rootViewController: vc)
20         //設置窗口對象的根視圖控制器,爲導航控制器。
21         window?.rootViewController = navigationController
22          //並將窗口對象做爲應用程序的主窗口。
23         window?.makeKeyAndVisible()
24 
25         return true
26     }
27 
28     func applicationWillResignActive(_ application: UIApplication) {
29         // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
30         // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
31     }
32 
33     func applicationDidEnterBackground(_ application: UIApplication) {
34         // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
35         // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
36     }
37 
38     func applicationWillEnterForeground(_ application: UIApplication) {
39         // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
40     }
41 
42     func applicationDidBecomeActive(_ application: UIApplication) {
43         // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
44     }
45 
46     func applicationWillTerminate(_ application: UIApplication) {
47         // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
48     }
49 }
相關文章
相關標籤/搜索