這篇文章將為大家詳細(xì)講解有關(guān)iOS如何使用CAEmitterLayer實(shí)現(xiàn)粒子發(fā)射動(dòng)畫(huà)效果,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
在方正等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶(hù)提供成都做網(wǎng)站、成都網(wǎng)站建設(shè)、成都外貿(mào)網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需求定制制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都營(yíng)銷(xiāo)網(wǎng)站建設(shè),外貿(mào)網(wǎng)站建設(shè),方正網(wǎng)站建設(shè)費(fèi)用合理。iOS實(shí)現(xiàn)粒子發(fā)射動(dòng)畫(huà)效果圖
代碼已上傳 GitHub:https://github.com/Silence-GitHub/CoreAnimationDemo
動(dòng)畫(huà)效果用 CAEmitterLayer 實(shí)現(xiàn)。CAEmitterLayer 顯示粒子發(fā)射動(dòng)畫(huà),具體的粒子由 CAEmitterCell 封裝。代碼示例是展示 CAEmitterLayer 如何使用。為了方便,直接在控制器(UIViewController)中設(shè)置 CAEmitterLayer。如果在項(xiàng)目中使用,有時(shí)在自定義視圖(UIView)中加入 CAEmitterLayer 比較合理,例如自定義點(diǎn)贊按鈕,可以精簡(jiǎn)控制器的代碼。
下雨動(dòng)畫(huà)效果
這里的雨勻速下落,雨的密度逐漸變化。
給控制器添加類(lèi)型為 CAEmitterLayer 的屬性 rainLayer,在 viewDidLoad 方法中對(duì)此屬性進(jìn)行初始化
private var rainLayer: CAEmitterLayer! private func setupRainLayer() { // 粒子發(fā)射圖層 rainLayer = CAEmitterLayer() // 發(fā)射器形狀為線形,默認(rèn)發(fā)射方向向上 rainLayer.emitterShape = kCAEmitterLayerLine // 從發(fā)射器的輪廓發(fā)射粒子 rainLayer.emitterMode = kCAEmitterLayerOutline // 優(yōu)先渲染舊的粒子 rainLayer.renderMode = kCAEmitterLayerOldestFirst // 發(fā)射位置 // 對(duì)于線形發(fā)射器,線的兩端點(diǎn)分別為 // (emitterPosition.x - emitterSize.width/2, emitterPosition.y, emitterZPosition)和 // (emitterPosition.x + emitterSize.width/2, emitterPosition.y, emitterZPosition) rainLayer.emitterPosition = CGPoint(x: view.bounds.midX, y: 0) // 發(fā)射器大小 rainLayer.emitterSize = CGSize(width: view.bounds.width, height: 0) // 粒子生成速率的倍數(shù),一開(kāi)始不發(fā)射,設(shè)置為零 rainLayer.birthRate = 0 // 發(fā)射的粒子 let cell = CAEmitterCell() // 粒子顯示的內(nèi)容,設(shè)置CGImage,顯示圖片 cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage // 粒子縮放倍數(shù) cell.scale = 0.1 // 粒子壽命,單位是秒 cell.lifetime = 5 // 粒子生成速率,單位是個(gè)/秒,實(shí)際顯示效果要乘以CAEmitterLayer的birthRate cell.birthRate = 1000 // 粒子速度 cell.velocity = 500 // 粒子發(fā)射角度,正值表示順時(shí)針?lè)较? cell.emissionLongitude = CGFloat.pi // 圖層要發(fā)射1種粒子 rainLayer.emitterCells = [cell] // 添加粒子發(fā)射圖層 view.layer.addSublayer(rainLayer) }
點(diǎn)擊按鈕開(kāi)始或停止動(dòng)畫(huà)。用 CABasicAnimation 使粒子生成速率的倍數(shù)漸變,達(dá)到雨逐漸變大或變小的效果
@IBAction func rainButtonClicked(_ sender: UIButton) { // 連續(xù)調(diào)用此方法會(huì)影響雨變大或變小的連貫性,所以禁止連續(xù)點(diǎn)擊按鈕 sender.isUserInteractionEnabled = false // 粒子生成速率漸變動(dòng)畫(huà) let birthRateAnimation = CABasicAnimation(keyPath: "birthRate") birthRateAnimation.duration = 3 if rainLayer.birthRate == 0 { // 雨變大 birthRateAnimation.fromValue = 0 birthRateAnimation.toValue = 1 rainLayer.birthRate = 1 } else { // 雨變小 birthRateAnimation.fromValue = 1 birthRateAnimation.toValue = 0 rainLayer.birthRate = 0 } // 加入動(dòng)畫(huà) rainLayer.add(birthRateAnimation, forKey: "birthRate") // 動(dòng)畫(huà)時(shí)長(zhǎng)過(guò)后恢復(fù)按鈕可點(diǎn)擊狀態(tài) DispatchQueue.main.asyncAfter(deadline: .now() + birthRateAnimation.duration) { [weak self] in guard self != nil else { return } sender.isUserInteractionEnabled = true } }
發(fā)射一圈粒子動(dòng)畫(huà)效果
給控制器添加類(lèi)型為 CAEmitterLayer 的屬性 centerHeartLayer,在 viewDidLoad 方法中對(duì)此屬性進(jìn)行初始化
private var centerHeartLayer: CAEmitterLayer! private func setupCenterHeartLayer() { centerHeartLayer = CAEmitterLayer() // 發(fā)射器形狀為圓形,默認(rèn)向四周發(fā)射粒子 centerHeartLayer.emitterShape = kCAEmitterLayerCircle centerHeartLayer.emitterMode = kCAEmitterLayerOutline centerHeartLayer.renderMode = kCAEmitterLayerOldestFirst // 發(fā)射器位置 // 對(duì)于圓形發(fā)射器 // 圓心位于(emitterPosition.x, emitterPosition.y, emitterZPosition) // 半徑為emitterSize.width centerHeartLayer.emitterPosition = CGPoint(x: view.bounds.midX, y: view.bounds.midY) centerHeartLayer.emitterSize = centerHeartButton.frame.size centerHeartLayer.birthRate = 0 let cell = CAEmitterCell() cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage cell.lifetime = 1 cell.birthRate = 2000 cell.scale = 0.05 // 粒子縮放倍數(shù)每秒減小0.02,粒子逐漸縮小 cell.scaleSpeed = -0.02 // 粒子透明度每秒減小1,粒子逐漸變透明 cell.alphaSpeed = -1 cell.velocity = 30 centerHeartLayer.emitterCells = [cell] view.layer.addSublayer(centerHeartLayer) }
點(diǎn)擊按鈕開(kāi)始動(dòng)畫(huà)
@IBAction func centerHeartButtonClicked(_ sender: UIButton) { sender.isUserInteractionEnabled = false // 設(shè)置動(dòng)畫(huà)開(kāi)始時(shí)間,否則會(huì)有太多粒子 centerHeartLayer.beginTime = CACurrentMediaTime() // 開(kāi)始生成粒子 centerHeartLayer.birthRate = 1 // 一段時(shí)間后停止生成粒子 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in guard let strongSelf = self else { return } strongSelf.centerHeartLayer.birthRate = 0 } DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in guard self != nil else { return } sender.isUserInteractionEnabled = true } }
向上發(fā)射一個(gè)粒子動(dòng)畫(huà)效果
給控制器添加類(lèi)型為 CAEmitterLayer 的屬性 leftHeartLayer,在 viewDidLoad 方法中對(duì)此屬性進(jìn)行初始化
private var leftHeartLayer: CAEmitterLayer! private func setupLeftHeartLayer() { leftHeartLayer = CAEmitterLayer() // 點(diǎn)狀發(fā)射器,默認(rèn)發(fā)射方向向右 // 這句可以省略,點(diǎn)狀是默認(rèn)值 leftHeartLayer.emitterShape = kCAEmitterLayerPoint // 從發(fā)射器中的一點(diǎn)發(fā)射粒子 // 這句可以省略,是默認(rèn)值 leftHeartLayer.emitterMode = kCAEmitterLayerVolume leftHeartLayer.renderMode = kCAEmitterLayerOldestFirst // 發(fā)射器位置 // 對(duì)于點(diǎn)狀發(fā)射器,發(fā)射點(diǎn)在(emitterPosition.x, emitterPosition.y, emitterZPosition) leftHeartLayer.emitterPosition = CGPoint(x: view.bounds.midX * 0.5, y: view.bounds.midY) leftHeartLayer.birthRate = 0 let cell = CAEmitterCell() cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage cell.scale = 0.5 cell.lifetime = 1 // 1秒發(fā)射1個(gè)粒子 cell.birthRate = 1 cell.alphaSpeed = -1 cell.velocity = 50 cell.emissionLongitude = -CGFloat.pi / 2 leftHeartLayer.emitterCells = [cell] view.layer.addSublayer(leftHeartLayer) }
點(diǎn)擊按鈕開(kāi)始動(dòng)畫(huà)
@IBAction func leftHeartButtonClicked(_ sender: UIButton) { sender.isUserInteractionEnabled = false // 從上1秒開(kāi)始動(dòng)畫(huà),使按鈕點(diǎn)擊后立即發(fā)射粒子 leftHeartLayer.beginTime = CACurrentMediaTime() - 1 leftHeartLayer.birthRate = 1 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in guard let strongSelf = self else { return } strongSelf.leftHeartLayer.birthRate = 0 } DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in guard self != nil else { return } sender.isUserInteractionEnabled = true } }
向上發(fā)射幾個(gè)粒子動(dòng)畫(huà)效果
給控制器添加類(lèi)型為 CAEmitterLayer 的屬性 rightHeartLayer,在 viewDidLoad 方法中對(duì)此屬性進(jìn)行初始化
private var rightHeartLayer: CAEmitterLayer! private func setupRightHeartLayer() { rightHeartLayer = CAEmitterLayer() rightHeartLayer.renderMode = kCAEmitterLayerOldestFirst rightHeartLayer.emitterPosition = CGPoint(x: view.bounds.midX * 1.5, y: view.bounds.midY) rightHeartLayer.birthRate = 0 let cell = CAEmitterCell() cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage cell.scale = 0.5 cell.lifetime = 1 cell.birthRate = 5 cell.alphaSpeed = -1 cell.velocity = 50 cell.emissionLongitude = -CGFloat.pi / 2 // 粒子發(fā)射角度的變化范圍 cell.emissionRange = CGFloat.pi / 4 rightHeartLayer.emitterCells = [cell] view.layer.addSublayer(rightHeartLayer) }
點(diǎn)擊按鈕開(kāi)始動(dòng)畫(huà)
@IBAction func rightHeartButtonClicked(_ sender: UIButton) { sender.isUserInteractionEnabled = false // 1秒發(fā)射5個(gè)粒子,0.2秒發(fā)射1個(gè)粒子,從上0.2秒開(kāi)始動(dòng)畫(huà),使按鈕點(diǎn)擊后立即發(fā)射粒子 rightHeartLayer.beginTime = CACurrentMediaTime() - 0.2 rightHeartLayer.birthRate = 1 DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { [weak self] in guard let strongSelf = self else { return } strongSelf.rightHeartLayer.birthRate = 0 } DispatchQueue.main.asyncAfter(deadline: .now() + 1.6) { [weak self] in guard self != nil else { return } sender.isUserInteractionEnabled = true } }
拋物線粒子動(dòng)畫(huà)效果
實(shí)現(xiàn)拋物線動(dòng)畫(huà)需要給粒子加上重力加速度。此外,這里還加入粒子旋轉(zhuǎn)效果,同時(shí)發(fā)射兩種粒子。
給控制器添加類(lèi)型為 CAEmitterLayer 的屬性 gravityLayer,在 viewDidLoad 方法中對(duì)此屬性進(jìn)行初始化
private var gravityLayer: CAEmitterLayer! private func setupGravityLayer() { gravityLayer = CAEmitterLayer() gravityLayer.renderMode = kCAEmitterLayerOldestFirst gravityLayer.emitterPosition = CGPoint(x: 0, y: view.bounds.maxY) gravityLayer.birthRate = 0 let cell = CAEmitterCell() cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage cell.scale = 0.5 cell.lifetime = 10 cell.alphaSpeed = -0.1 cell.birthRate = 10 cell.velocity = 100 // y軸方法的加速度,模擬重力加速度 cell.yAcceleration = 20 cell.emissionLongitude = -CGFloat.pi / 4 cell.emissionRange = CGFloat.pi / 4 // 粒子旋轉(zhuǎn)角速度,單位是弧度/秒,正值表示順時(shí)針旋轉(zhuǎn) // 這句可以省略,默認(rèn)值是零 cell.spin = 0 // 粒子旋轉(zhuǎn)角速度變化范圍 cell.spinRange = CGFloat.pi * 2 let cell2 = CAEmitterCell() cell2.contents = #imageLiteral(resourceName: "Heart_blue").cgImage cell2.scale = 0.3 cell2.lifetime = 20 cell2.alphaSpeed = -0.05 cell2.birthRate = 5 cell2.velocity = 135 cell2.yAcceleration = 20 cell2.emissionLongitude = -CGFloat.pi / 4 cell2.emissionRange = CGFloat.pi / 4 cell2.spin = 0 cell2.spinRange = CGFloat.pi * 2 // 圖層要發(fā)射2種粒子 gravityLayer.emitterCells = [cell, cell2] view.layer.addSublayer(gravityLayer) }
點(diǎn)擊開(kāi)始或停止動(dòng)畫(huà)
@IBAction func gravityButtonClicked(_ sender: UIButton) { if gravityLayer.birthRate == 0 { gravityLayer.beginTime = CACurrentMediaTime() gravityLayer.birthRate = 1 } else { gravityLayer.birthRate = 0 } }
關(guān)于“iOS如何使用CAEmitterLayer實(shí)現(xiàn)粒子發(fā)射動(dòng)畫(huà)效果”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站muchs.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。
文章題目:iOS如何使用CAEmitterLayer實(shí)現(xiàn)粒子發(fā)射動(dòng)畫(huà)效果-創(chuàng)新互聯(lián)
瀏覽路徑:http://muchs.cn/article48/dhdpep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、網(wǎng)站改版、外貿(mào)建站、外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容