1. 程式人生 > >手摸手教你寫ShineButton動畫

手摸手教你寫ShineButton動畫

移動端訪問不佳,請訪問我的個人部落格

前段時間在github上看見一個非常nice的動畫效果,可惜是安卓的,想著用swift寫一個iOS版的,下下來原始碼研究了一下,下面是我寫程式碼的心路歷程

分析動畫過程

剛開始看的時候感覺這個動畫很炫酷,實現起來應該挺複製的,後來我將gif圖逐一分解,瀏覽了一下安卓的實現過程,大致瞭解的實現的過程,下面是一些關鍵的動畫步驟:

  1. 第一步是裡面圖片的縮放動畫,使用CALayer配合CAKeyframeAnimation來實現;
  2. 第二步是是裡面一個圓環逐漸變大的過程,使用CAShapeLayer配合CAKeyframeAnimation
    來實現;
  3. 第三步是最外面一層太陽的擴散效果同樣也使用CAShapeLayer配合CAKeyframeAnimation來實現;
  4. 最後是閃爍和顏色變化的的效果,使用CABasicAnimationCADisplayLink來實現。

一、縮放動畫的實現

這個實現的過程相對而言比較簡單,用CALayer做為mask來實現下圖心形的圖片,然後用CAKeyframeAnimation來實現動畫,values的值為[0.4, 1, 0.9, 1],差值器模式為kCAAnimationCubic,下面是實現結果和關鍵程式碼:

public func startAnim() {
    let anim = CAKeyframeAnimation(keyPath: "transform.scale"
) anim.duration = animDuration anim.values = [0.4, 1, 0.9, 1] anim.calculationMode = kCAAnimationCubic maskLayer.add(anim, forKey: "scale") }

二、圓環擴散動畫的實現

首先圓環我們用CAShapeLayer來繪製一個圓環,然後通過CAKeyframeAnimation來改變圓環的path就可以了,下面是實現結果和關鍵程式碼:

public func startAnim() {
    let anim = CAKeyframeAnimation(keyPath: "path"
) anim.duration = params.animDuration * 0.1 let size = frame.size let fromPath = UIBezierPath(arcCenter: CGPoint.init(x: size.width/2, y: size.height/2), radius: 1, startAngle: 0, endAngle: CGFloat(M_PI) * 2.0, clockwise: false).cgPath let toPath = UIBezierPath(arcCenter: CGPoint.init(x: size.width/2, y: size.height/2), radius: size.width/2 * CGFloat(params.shineDistanceMultiple), startAngle: 0, endAngle: CGFloat(M_PI) * 2.0, clockwise: false).cgPath anim.delegate = self anim.values = [fromPath, toPath] anim.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)] anim.isRemovedOnCompletion = false anim.fillMode = kCAFillModeForwards shapeLayer.add(anim, forKey: "path") }

三、太陽的擴散效果實現

首先我們得先算出每個太陽的位置和將要擴散到的位置,然後用CAShapeLayer繪製出太陽,用CAKeyframeAnimation實現擴散的效果,下面是實現後的結果和關鍵程式碼 :

public func startAnim() {
    let radius = frame.size.width/2 * CGFloat(params.shineDistanceMultiple*1.4)
    var startAngle: CGFloat = 0
    let angle = CGFloat(M_PI*2/Double(params.shineCount)) + startAngle
    if params.shineCount%2 != 0 {
        startAngle = CGFloat(M_PI*2 - (Double(angle)/Double(params.shineCount)))
    }
    for i in 0..<params.shineCount {
        let bigShine = shineLayers[i]
        let bigAnim = getAngleAnim(shine: bigShine, angle: startAngle + CGFloat(angle)*CGFloat(i), radius: radius)
        let smallShine = smallShineLayers[i]
        var radiusSub = frame.size.width*0.15*0.66
        if params.shineSize != 0 {
            radiusSub = params.shineSize*0.66
        }
        let smallAnim = getAngleAnim(shine: smallShine, angle: startAngle + CGFloat(angle)*CGFloat(i) - CGFloat(params.smallShineOffsetAngle)*CGFloat(M_PI)/180, radius: radius-radiusSub)
        bigShine.add(bigAnim, forKey: "path")
        smallShine.add(smallAnim, forKey: "path")
    }
    let angleAnim = CABasicAnimation(keyPath: "transform.rotation")
    angleAnim.duration = params.animDuration * 0.87
    angleAnim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    angleAnim.fromValue = 0
    angleAnim.toValue = CGFloat(params.shineTurnAngle)*CGFloat(M_PI)/180
    angleAnim.delegate = self
    add(angleAnim, forKey: "rotate")
}

四、最後再將這些動畫通過一定規律結合起來

上圖是將之前動畫步驟組合起來後的效果,上面的一些程式碼只是部分程式碼,全部程式碼可以去我的github地址上去下在瀏覽,如果大家喜歡可以點一個start,有更好的想法也可以提出來,大家一起交流一下,最後謝謝大家閱讀~~

相關推薦

ShineButton動畫

移動端訪問不佳,請訪問我的個人部落格 前段時間在github上看見一個非常nice的動畫效果,可惜是安卓的,想著用swift寫一個iOS版的,下下來原始碼研究了一下,下面是我寫程式碼的心路歷程 分析動畫過程 剛開始看的時候感覺這個動畫很

討厭selector背景了嗎?封裝個控制元件!

前段時間專案裡要寫好幾個按下去狀態變化的button, 於是在drawable資料夾裡寫了一堆檔案, 想想好煩啊, 也是浪費時間,搞了一堆檔案,還要起名,真心煩! 一氣之下, 一勞永逸, 寫一個控制元件,各種屬性程式碼xml配置或者程式碼設定。因此也就有了St

自己動手實現一個前端路由

前言 用過現代前端框架的同學,對前端路由一定不陌生, vue, react, angular 都有自己的 router, 那麼你對 router 的工作原理了解嗎? 如果還不瞭解, 那麼請跟我一起來手寫一個簡單的前端路由, 順便了解一下. 實現路由的2種方式 hash模式

使用WebSocket[其實WebSocket也不難]

在本篇文章之前,WebSocket很多人聽說過,沒見過,沒用過,以為是個很高大上的技術,實際上這個技術並不神祕,可以說是個很容易就能掌握的技術,希望在看完本文之後,馬上把文中的栗子拿出來自己試一試,實踐出真知。 游泳、健身瞭解一下:部落格、前端積累文件、公眾

微信小程式開發之自定義元件

前言  相信大家在開發小程式時會遇到某個功能多次使用的情況,比如彈出框。這個時候大家首先想到的是元件化開發,就是把彈出框封裝成一個元件,然後哪裡使用哪裡就呼叫,對,看來大家都是有思路的人,但是要怎樣實現呢。可能你會去看官方文件,但是微信的官方文件也是說的不太清楚,所以寫起來也

Spring Boot2(十二):搭建Shiro安全框架

一、前言 SpringBoot+Shiro+Mybatis完成的。 之前看了一位小夥伴的Shiro教程,跟著做了,遇到蠻多坑的(´இ皿இ`) 修改整理了一下,成功跑起來了。可以通過postman進行測試 不多比比∠( ᐛ 」∠)_,直接上原始碼:https://github.com/niaobulashi/s

48 張圖 | 微服務的效能監控、壓測和調優

![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210317102307754.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG

【轉】,帶用vue擼後臺 系列二(登錄權限篇)

userinfo ogr abort 變化 再次 狀態碼 quest -o 監聽 前言 拖更有點嚴重,過了半個月才寫了第二篇教程。無奈自己是一個業務猿,每天被我司的產品虐的死去活來,之前又病了一下休息了幾天,大家見諒。 進入正題,做後臺項目區別於做其它的項目,權限驗證與

部署git伺服器實現自動釋出程式碼

前段趁著活動買了個騰訊雲伺服器,一直沒抽時間去折騰,最近才開始部署了一個自己專屬的git倉庫,實現程式碼自動釋出部署功能。(我也想成為努力向上,積極進取的有志青年啊!)文章的內容基本都是參考自谷歌搜尋,然後按我的思路重新整理一遍,既是為了分享也是為了鞏固知識。 我也是第一次折騰伺服器,前期部署就

,帶實現程式碼自動部署

為什麼? 為什麼要實現自動部署? 在2個月的時間裡,一直都在忙著整理部落格,每一個程式設計師都有一個部落格夢(當然也不排除有些是沒有的),我先後使用過各種部落格系統: vuepress react-static jekyll hexo ... 這些都因為前前後後的原因,

玩轉Xcode Extensions

題圖:from imgur 事情是這樣的前段時間看到,E神寫了個新玩具叫Code Friend很酷炫,私下裡給E神說拿來推廣讓iOSTips的讀者體驗一番,E神說目前功能還不完善,等再牛逼一點再拿來分享,然後就有了接下來的分享。 有沒有這樣的體驗,我們經常要開啟終端,跳轉到當前工程目錄,

對手的用canvas畫一個簡單的海報

啦啦啦,首先說下需求,產品想讓使用者在我們app內,分享一張圖片到微信、qq等平臺。圖片中包含使用者的姓名、頭像、和帶著自己資訊的二維碼。然後,如何生成這張海報呢~~~首先我們老大告訴我有一個外掛叫html2canvas、其作用就是可以將dom節點轉化成圖片,是個不錯的東西。我試驗了下、確實可以,但~這個外掛

,帶用vue擼後臺 系列二(登入許可權篇)

前言 拖更有點嚴重,過了半個月才寫了第二篇教程。無奈自己是一個業務猿,每天被我司的產品虐的死去活來,之前又病了一下休息了幾天,大家見諒。 進入正題,做後臺專案區別於做其它的專案,許可權驗證與安全性是非常重要的,可以說是一個後臺專案一開始就必須考慮和搭建的基礎核心功能

,帶用合理的姿勢使用 webpack 4(上)

(點選上方公眾號,可快速關注)作者:華爾街見聞技術團隊 - 花褲衩segmentfault.co

,帶用vue實現後臺管理許可權系統及頂欄三級選單顯示

手摸手,帶你用vue實現後臺管理許可權系統及頂欄三級選單顯示 效果演示地址 專案demo展示 重要功能總結 許可權功能的實現 許可權路由思路: 根據使用者登入的roles資訊與路由中配置的roles資訊進行比較過濾,生成可以訪問的路由表,並通過router.addRoutes(store.gett

圖解AQS的設計與實現,實現一把互斥鎖!

AQS是併發程式設計中非常重要的概念,它是juc包下的許多併發工具類,如CountdownLatch,CyclicBarrier,Semaphore 和鎖, 如ReentrantLock, ReaderWriterLock的實現基礎,提供了一個基於int狀態碼和佇列來實現的併發框架。本文將對AQS框架的幾個重

淺談Java中的Condition條件佇列,實現一個阻塞佇列!

條件佇列是什麼?可能很多人和我一樣答不出來,不過今天終於搞清楚了! 什麼是條件佇列 條件佇列:當某個執行緒呼叫了wait方法,或者通過Condition物件呼叫了await相關方法,執行緒就會進入阻塞狀態,並加入到對應條件佇列中。 在等待喚醒機制相關文章中我們提到了條件佇列,即當物件獲取到同步鎖之後,如果呼叫

volatile 解析

前言 volatile 是 Java 裡的一個重要的指令,它是由 Java 虛擬機器裡提供的一個輕量級的同步機制。一個共享變數宣告為 volatile 後,特別是在多執行緒操作時,正確使用 volatile 變數,就要掌握好其原理。 特性 volatile 具有可見性和有序性的特性,同時,對 volati

理解Vue響應式原理

## 前言 響應式原理作為 `Vue` 的核心,使用資料劫持實現資料驅動檢視。在面試中是經常考查的知識點,也是面試加分項。 本文將會循序漸進的解析響應式原理的工作流程,主要以下面結構進行: 1. 分析主要成員,瞭解它們有助於理解流程 2. 將流程拆分,理解其中的作用 3. 結合以上的點,理解整體流程

理解Vue的Computed原理

## 前言 `computed` 在 `Vue` 中是很常用的屬性配置,它能夠隨著依賴屬性的變化而變化,為我們帶來很大便利。那麼本文就來帶大家全面理解 `computed` 的內部原理以及工作流程。 在這之前,希望你能夠對響應式原理有一些理解,因為 `computed` 是基於響應式原理進行工作。如果你對