iOS中字跡動畫效果

最近自己著手一款關(guān)于中國風(fēng)的app,其中需要的一個想法就是詩詞可以像ppt中的一種模式:字可以一個個的顯示出來。最先的想法是將詩詞分成一個個字放在一個個label上面,然后添加動畫將其顯示出來!然后這無疑是相當笨拙,且代碼也是相當?shù)某舐?!最后查閱了相關(guān)資料!終于找到了不錯的解決方法!效果如下圖所示

s24.gif
  • 廢話不多說,直接上思路

如何將字跡給顯示出來(重點)

首先我們要獲取字的軌跡,然后才能做出相應(yīng)的操作,比如給其添加path,添加動畫等等。 這里有一個自己添加不是系統(tǒng)的字體,我就大概的說一下了。首先下載好ttf格式的字體,添加到項目中來,在info.plist中 添加Fonts provided by application 然后在下面添加對應(yīng)的字體。

獲取字體的軌跡

   let paths = CGPathCreateMutable() //創(chuàng)建一個變量path添加到貝瑟爾曲線
   let fontName = __CFStringMakeConstantString("MFTongXin_Noncommercial-Regular")//自己添加的字體,(貌似沒有用,不知道什么鬼,難倒不支持系統(tǒng)外的?求解?。┛梢該Q成系統(tǒng)的字體
     print("\(fontName)")
   let fontRef:AnyObject = CTFontCreateWithName(fontName, 25, nil)
   let attrString = NSAttributedString(string: string, attributes: [kCTFontAttributeName as String : fontRef])
   let line = CTLineCreateWithAttributedString(attrString as CFAttributedString)
   let runA = CTLineGetGlyphRuns(line)

  • 上面的runA獲取了所有的字跡的line CFArrayGetCount(runA)獲取一個數(shù)組。遍歷數(shù)組 去除每個元素 (其中涉及到了一些與c橋接的內(nèi)容 估計有的會比較陌生,慢慢看,還是很好懂的)
       let run = CFArrayGetValueAtIndex(runA, runIndex);
       let runb = unsafeBitCast(run, CTRun.self)
       let  CTFontName = unsafeBitCast(kCTFontAttributeName, UnsafePointer<Void>.self)
       let runFontC = CFDictionaryGetValue(CTRunGetAttributes(runb),CTFontName)
       let runFontS = unsafeBitCast(runFontC, CTFont.self)
       let width = UIScreen.mainScreen().bounds.width
       
       var temp = 0
       var offset:CGFloat = 0.0
  • unsafeBitCast是非常危險的操作,它會將一個指針指向的內(nèi)存強制按位轉(zhuǎn)換為目標的類型。因為這種轉(zhuǎn)換是在Swift的類型管理之外進行的,因此編譯器無法確保得到的類型是否確實正確,你必須明確地知道你在做什么。

遍歷每個字跡,在這邊可以修改橫豎的方向

      //在這邊修改應(yīng)該可以修改橫豎的方向
      for(var i = 0; i < CTRunGetGlyphCount(runb); i++){
          let range = CFRangeMake(i, 1)
          let glyph:UnsafeMutablePointer<CGGlyph> = UnsafeMutablePointer<CGGlyph>.alloc(1)//在Swift中不能像C里那樣使用&符號直接獲取地址來進行操作。如果我們想對某個變量進行指針操作,我們可以借助withUnsafePointer這個輔助方法。
          glyph.initialize(0)
          let position:UnsafeMutablePointer<CGPoint> = UnsafeMutablePointer<CGPoint>.alloc(1)
          position.initialize(CGPointZero)
          CTRunGetGlyphs(runb, range, glyph)
          CTRunGetPositions(runb, range, position);
          
          let temp3 = CGFloat(position.memory.x)
          let temp2 = (Int) (temp3 / width)
          let temp1 = 0
          if(temp2 > temp1){
              temp = temp2
              offset = position.memory.x - (CGFloat(temp) * width)
          }
          let path = CTFontCreatePathForGlyph(runFontS,glyph.memory,nil)
          let x = position.memory.x - (CGFloat(temp) * width) - offset
          let y = position.memory.y - (CGFloat(temp) * 80)
          var transform = CGAffineTransformMakeTranslation(x, y)
          CGPathAddPath(paths, &transform, path)
          glyph.destroy()
          glyph.dealloc(1)
          position.destroy()
          position.dealloc(1)  //銷毀操作
      }

將paths添加到貝瑟爾曲線

       let bezierPath = UIBezierPath()
       bezierPath.moveToPoint(CGPointZero)
       bezierPath.appendPath(UIBezierPath(CGPath: paths))
~~~


- 好了最主要的事情已經(jīng)OK了下面就可以為這個動畫添加點酷炫的效果了,比如現(xiàn)在流行的漸變色。

~~~
    private var gradientLayer = CAGradientLayer() //創(chuàng)建全局變量
~~~

添加漸變色的layer和動畫

~~~
1.添加顏色
        // 漸變色的顏色數(shù)
        let count = 10
        var colors:[CGColorRef] = []
        let topColor = UIColor(red: (91/255.0), green: (91/255.0), blue: (91/255.0), alpha: 1)
        let buttomColor = UIColor(red: (24/255.0), green: (24/255.0), blue: (24/255.0), alpha: 1)
        let gradientColors: [CGColor] = [topColor.CGColor, buttomColor.CGColor]
        for _ in 0 ..< count {
            let color = UIColor.init(red: CGFloat(arc4random() % 256) / 255, green: CGFloat(arc4random() % 256) / 255, blue: CGFloat(arc4random() % 256) / 255, alpha: 1.0)
            colors.append(color.CGColor)
        }
~~~

~~~
添加方向
        gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
        gradientLayer.colors = gradientColors
        gradientLayer.frame = self.bounds
        gradientLayer.type = kCAGradientLayerAxial
        self.layer.addSublayer(gradientLayer)
添加動畫
        // 漸變色的動畫
        let animation = CABasicAnimation(keyPath: "colors")
        animation.duration = 0.5
        animation.repeatCount = MAXFLOAT
        var toColors:[CGColorRef] = []
        for _ in 0 ..< count {
            let color = UIColor.init(red: CGFloat(arc4random() % 256) / 255, green: CGFloat(arc4random() % 256) / 255, blue: CGFloat(arc4random() % 256) / 255, alpha: 1.0)
            toColors.append(color.CGColor)
        }
        animation.autoreverses = true
        animation.toValue = toColors
        gradientLayer.addAnimation(animation, forKey: "gradientLayer")

~~~

最后將筆跡的path添加到layer上面去,將其以動畫的形式顯示出來 然后講pathLayer添加到漸變色的layer的mask屬性
~~~
        gradientLayer.mask = pathLayer
~~~

####最終在ViewController調(diào)用
~~~
這里用了一個延時的線程,里面的時間可以根據(jù)你動畫的時間自己來算
        let viewPoem = PoemShow(frame: CGRectMake(0, 200, self.view.frame.size.width, 50), message: "楚城今近遠,")
         view.addSubview(viewPoem)
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(5*Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
            let viewPoem1 = PoemShow(frame: CGRectMake(0, 250, self.view.frame.size.width, 50), message: "積靄寒塘暮。")
            self.view.addSubview(viewPoem1)
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(5*Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
                let viewPoem2 = PoemShow(frame: CGRectMake(0, 300, self.view.frame.size.width, 50), message: "水淺舟且遲,")
                self.view.addSubview(viewPoem2)
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(5*Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
                    let viewPoem3 = PoemShow(frame: CGRectMake(0, 350, self.view.frame.size.width, 50), message: "淮潮至何處。")
                    self.view.addSubview(viewPoem3)
                }
            }
        }

~~~

###語言表達的可能有點不清楚,大家可以參考我的[Demo](https://github.com/Loissoul/PoemShow),[Demo](https://github.com/Loissoul/PoemShow) readme中也有OC的相關(guān)解決方法,不足之處,請多多指出!如果有更好的解決方法,也要分享下哦。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,698評論 6 30
  • Core Animation Core Animation,中文翻譯為核心動畫,它是一組非常強大的動畫處理API,...
    45b645c5912e閱讀 3,165評論 0 21
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,692評論 4 61
  • 生活中,人們常常覺得頸椎疼,卻很少拿它當回事,也不刻意保護頸椎。如果保護不好頸椎,整個身體都會生病。 頸椎不好疾病...
    我微微一笑閱讀 1,071評論 0 2
  • 說好不再聯(lián)系的,聽到他說他時不時有輕生的念頭時,還是莫名地心疼。 我不知道這算不算愛?之前那么恨、現(xiàn)在反倒自責了?...
    沙漏在夢游閱讀 191評論 0 0

友情鏈接更多精彩內(nèi)容