国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS CAEmitterLayer實現粒子發射動畫效果

2020-07-26 02:47:48
字體:
來源:轉載
供稿:網友

iOS實現粒子發射動畫效果圖

代碼已上傳 GitHub:https://github.com/Silence-GitHub/CoreAnimationDemo

動畫效果用 CAEmitterLayer 實現。CAEmitterLayer 顯示粒子發射動畫,具體的粒子由 CAEmitterCell 封裝。代碼示例是展示 CAEmitterLayer 如何使用。為了方便,直接在控制器(UIViewController)中設置 CAEmitterLayer。如果在項目中使用,有時在自定義視圖(UIView)中加入 CAEmitterLayer 比較合理,例如自定義點贊按鈕,可以精簡控制器的代碼。

下雨動畫效果

這里的雨勻速下落,雨的密度逐漸變化。

給控制器添加類型為 CAEmitterLayer 的屬性 rainLayer,在 viewDidLoad 方法中對此屬性進行初始化

private var rainLayer: CAEmitterLayer!private func setupRainLayer() {  // 粒子發射圖層  rainLayer = CAEmitterLayer()  // 發射器形狀為線形,默認發射方向向上  rainLayer.emitterShape = kCAEmitterLayerLine  // 從發射器的輪廓發射粒子  rainLayer.emitterMode = kCAEmitterLayerOutline  // 優先渲染舊的粒子  rainLayer.renderMode = kCAEmitterLayerOldestFirst  // 發射位置  // 對于線形發射器,線的兩端點分別為  // (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)  // 發射器大小  rainLayer.emitterSize = CGSize(width: view.bounds.width, height: 0)  // 粒子生成速率的倍數,一開始不發射,設置為零  rainLayer.birthRate = 0    // 發射的粒子  let cell = CAEmitterCell()  // 粒子顯示的內容,設置CGImage,顯示圖片  cell.contents = #imageLiteral(resourceName: "Heart_red").cgImage  // 粒子縮放倍數  cell.scale = 0.1  // 粒子壽命,單位是秒  cell.lifetime = 5  // 粒子生成速率,單位是個/秒,實際顯示效果要乘以CAEmitterLayer的birthRate  cell.birthRate = 1000  // 粒子速度  cell.velocity = 500  // 粒子發射角度,正值表示順時針方向  cell.emissionLongitude = CGFloat.pi    // 圖層要發射1種粒子  rainLayer.emitterCells = [cell]  // 添加粒子發射圖層  view.layer.addSublayer(rainLayer)}

點擊按鈕開始或停止動畫。用 CABasicAnimation 使粒子生成速率的倍數漸變,達到雨逐漸變大或變小的效果

@IBAction func rainButtonClicked(_ sender: UIButton) {  // 連續調用此方法會影響雨變大或變小的連貫性,所以禁止連續點擊按鈕  sender.isUserInteractionEnabled = false  // 粒子生成速率漸變動畫  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  }  // 加入動畫  rainLayer.add(birthRateAnimation, forKey: "birthRate")  // 動畫時長過后恢復按鈕可點擊狀態  DispatchQueue.main.asyncAfter(deadline: .now() + birthRateAnimation.duration) { [weak self] in    guard self != nil else { return }    sender.isUserInteractionEnabled = true  }}

發射一圈粒子動畫效果

給控制器添加類型為 CAEmitterLayer 的屬性 centerHeartLayer,在 viewDidLoad 方法中對此屬性進行初始化

private var centerHeartLayer: CAEmitterLayer!private func setupCenterHeartLayer() {  centerHeartLayer = CAEmitterLayer()  // 發射器形狀為圓形,默認向四周發射粒子  centerHeartLayer.emitterShape = kCAEmitterLayerCircle  centerHeartLayer.emitterMode = kCAEmitterLayerOutline  centerHeartLayer.renderMode = kCAEmitterLayerOldestFirst  // 發射器位置  // 對于圓形發射器  // 圓心位于(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  // 粒子縮放倍數每秒減小0.02,粒子逐漸縮小  cell.scaleSpeed = -0.02  // 粒子透明度每秒減小1,粒子逐漸變透明  cell.alphaSpeed = -1  cell.velocity = 30    centerHeartLayer.emitterCells = [cell]  view.layer.addSublayer(centerHeartLayer)}

點擊按鈕開始動畫

@IBAction func centerHeartButtonClicked(_ sender: UIButton) {  sender.isUserInteractionEnabled = false  // 設置動畫開始時間,否則會有太多粒子  centerHeartLayer.beginTime = CACurrentMediaTime()  // 開始生成粒子  centerHeartLayer.birthRate = 1  // 一段時間后停止生成粒子  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  }}

向上發射一個粒子動畫效果

給控制器添加類型為 CAEmitterLayer 的屬性 leftHeartLayer,在 viewDidLoad 方法中對此屬性進行初始化

private var leftHeartLayer: CAEmitterLayer!private func setupLeftHeartLayer() {  leftHeartLayer = CAEmitterLayer()  // 點狀發射器,默認發射方向向右  // 這句可以省略,點狀是默認值  leftHeartLayer.emitterShape = kCAEmitterLayerPoint  // 從發射器中的一點發射粒子  // 這句可以省略,是默認值  leftHeartLayer.emitterMode = kCAEmitterLayerVolume  leftHeartLayer.renderMode = kCAEmitterLayerOldestFirst  // 發射器位置  // 對于點狀發射器,發射點在(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秒發射1個粒子  cell.birthRate = 1  cell.alphaSpeed = -1  cell.velocity = 50  cell.emissionLongitude = -CGFloat.pi / 2    leftHeartLayer.emitterCells = [cell]  view.layer.addSublayer(leftHeartLayer)}

點擊按鈕開始動畫

@IBAction func leftHeartButtonClicked(_ sender: UIButton) {  sender.isUserInteractionEnabled = false  // 從上1秒開始動畫,使按鈕點擊后立即發射粒子  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  }}

向上發射幾個粒子動畫效果

給控制器添加類型為 CAEmitterLayer 的屬性 rightHeartLayer,在 viewDidLoad 方法中對此屬性進行初始化

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  // 粒子發射角度的變化范圍  cell.emissionRange = CGFloat.pi / 4    rightHeartLayer.emitterCells = [cell]  view.layer.addSublayer(rightHeartLayer)}

點擊按鈕開始動畫

@IBAction func rightHeartButtonClicked(_ sender: UIButton) {  sender.isUserInteractionEnabled = false  // 1秒發射5個粒子,0.2秒發射1個粒子,從上0.2秒開始動畫,使按鈕點擊后立即發射粒子  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  }}

拋物線粒子動畫效果

實現拋物線動畫需要給粒子加上重力加速度。此外,這里還加入粒子旋轉效果,同時發射兩種粒子。

給控制器添加類型為 CAEmitterLayer 的屬性 gravityLayer,在 viewDidLoad 方法中對此屬性進行初始化

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  // 粒子旋轉角速度,單位是弧度/秒,正值表示順時針旋轉  // 這句可以省略,默認值是零  cell.spin = 0  // 粒子旋轉角速度變化范圍  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    // 圖層要發射2種粒子  gravityLayer.emitterCells = [cell, cell2]  view.layer.addSublayer(gravityLayer)}

點擊開始或停止動畫

@IBAction func gravityButtonClicked(_ sender: UIButton) {  if gravityLayer.birthRate == 0 {    gravityLayer.beginTime = CACurrentMediaTime()    gravityLayer.birthRate = 1  } else {    gravityLayer.birthRate = 0  }}

以上是動畫的實現方法,代碼已上傳 GitHub:https://github.com/Silence-GitHub/CoreAnimationDemo

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武乡县| 上犹县| 图木舒克市| 都兰县| 周至县| 荥阳市| 浠水县| 隆德县| 涿州市| 会理县| 保德县| 崇明县| 读书| 共和县| 罗平县| 璧山县| 岳池县| 利津县| 尚义县| 彝良县| 白山市| 津市市| 汾阳市| 黄梅县| 洛阳市| 南阳市| 河北区| 肇东市| 江山市| 长泰县| 泰兴市| 明光市| 闻喜县| 上犹县| 府谷县| 双桥区| 新宁县| 达日县| 鲁甸县| 连平县| 亚东县|