天天看點

iOS中播放gif動态圖的方式探讨

    在ios開發中,uiimageview類專門來負責圖檔資料的渲染,并且uiimageview也有幀動畫的方法來播放一組圖檔,但是對于gif類型的資料,uiimageview中并沒有現成的接口提供給開發者使用,在ios中一般可以通過兩種方式來播放gif動态圖,一種方式是通過imageio架構中的方法将gif檔案中的資料進行解析,再使用coreanimation核心動畫來播放gif動畫,另一種方式計較簡單,可以直接通過webview來渲染gif圖。

     gif動态圖檔案中包含了一組圖檔及其資訊,資訊主要記錄着每一幀圖檔播放的時間,我們如果擷取到了gif檔案中所有的圖檔同時又擷取到每一幀圖檔播放的時間,就可以為uiimageview添加核心動畫的方法來讓其播放gif的内容了。

    首先解析gif檔案中的資料,代碼如下:

<a href="http://my.oschina.net/u/2340880/blog/608560#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

<code>//要引入imageio庫</code>

<code>#import &lt;imageio/imageio.h&gt;</code>

<code>//解析gif檔案資料的方法 block中會将解析的資料傳遞出來</code>

<code>-(</code><code>void</code><code>)getgifimagewithurk:(nsurl *)url</code>

<code>               </code><code>returndata:(</code><code>void</code><code>(^)(nsarray&lt;uiimage *&gt; * imagearray,</code>

<code>                                </code><code>nsarray&lt;nsnumber *&gt;*timearray,</code>

<code>                                </code><code>cgfloat totaltime,</code>

<code>                                </code><code>nsarray&lt;nsnumber *&gt;* widths,</code>

<code>                                </code><code>nsarray&lt;nsnumber *&gt;* heights))datablock{</code>

<code>    </code><code>//通過檔案的url來将gif檔案讀取為圖檔資料引用</code>

<code>    </code><code>cgimagesourceref source = cgimagesourcecreatewithurl((cfurlref)url, null);</code>

<code>    </code><code>//擷取gif檔案中圖檔的個數</code>

<code>    </code><code>size_t</code> <code>count = cgimagesourcegetcount(source);</code>

<code>    </code><code>//定義一個變量記錄gif播放一輪的時間</code>

<code>    </code><code>float</code> <code>alltime=0;</code>

<code>    </code><code>//存放所有圖檔</code>

<code>    </code><code>nsmutablearray * imagearray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//存放每一幀播放的時間</code>

<code>    </code><code>nsmutablearray * timearray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//存放每張圖檔的寬度 (一般在一個gif檔案中,所有圖檔尺寸都會一樣)</code>

<code>    </code><code>nsmutablearray * widtharray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//存放每張圖檔的高度</code>

<code>    </code><code>nsmutablearray * heightarray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//周遊</code>

<code>    </code><code>for</code> <code>(</code><code>size_t</code> <code>i=0; i&lt;count; i++) {</code>

<code>        </code><code>cgimageref image = cgimagesourcecreateimageatindex(source, i, null);</code>

<code>        </code><code>[imagearray addobject:(__bridge uiimage *)(image)];</code>

<code>        </code><code>cgimagerelease(image);</code>

<code>        </code><code>//擷取圖檔資訊</code>

<code>        </code><code>nsdictionary * info = (__bridge nsdictionary*)cgimagesourcecopypropertiesatindex(source, i, null);</code>

<code>        </code><code>cgfloat width = [[info objectforkey:(__bridge nsstring *)kcgimagepropertypixelwidth] floatvalue];</code>

<code>        </code><code>cgfloat height = [[info objectforkey:(__bridge nsstring *)kcgimagepropertypixelheight] floatvalue];</code>

<code>        </code><code>[widtharray addobject:[nsnumber numberwithfloat:width]];</code>

<code>        </code><code>[heightarray addobject:[nsnumber numberwithfloat:height]];</code>

<code>        </code><code>nsdictionary * timedic = [info objectforkey:(__bridge nsstring *)kcgimagepropertygifdictionary];</code>

<code>        </code><code>cgfloat </code><code>time</code> <code>= [[timedic objectforkey:(__bridge nsstring *)kcgimagepropertygifdelaytime]floatvalue];</code>

<code>        </code><code>alltime+=</code><code>time</code><code>;</code>

<code>        </code><code>[timearray addobject:[nsnumber numberwithfloat:</code><code>time</code><code>]];</code>

<code>    </code><code>}</code>

<code>    </code><code>datablock(imagearray,timearray,alltime,widtharray,heightarray);</code>

<code>}</code>

為uiimageview添加一個設定gif圖内容的方法:

<code>-(</code><code>void</code><code>)yh_setimage:(nsurl *)imageurl{</code>

<code>        </code><code>__weak id __self = self;</code>

<code>        </code><code>[self getgifimagewithurk:imageurl returndata:^(nsarray&lt;uiimage *&gt; *imagearray, nsarray&lt;nsnumber *&gt; *timearray, cgfloat totaltime, nsarray&lt;nsnumber *&gt; *widths, nsarray&lt;nsnumber *&gt; *heights) {</code>

<code>            </code><code>//添加幀動畫</code>

<code>            </code><code>cakeyframeanimation *animation = [cakeyframeanimation animationwithkeypath:@</code><code>"contents"</code><code>];</code>

<code>            </code><code>nsmutablearray * times = [[nsmutablearray alloc]init];</code>

<code>            </code><code>float</code> <code>currenttime = 0;</code>

<code>            </code><code>//設定每一幀的時間占比</code>

<code>            </code><code>for</code> <code>(</code><code>int</code> <code>i=0; i&lt;imagearray.count; i++) {</code>

<code>                </code><code>[times addobject:[nsnumber numberwithfloat:currenttime/totaltime]];</code>

<code>                </code><code>currenttime+=[timearray[i] floatvalue];</code>

<code>            </code><code>}</code>

<code>            </code><code>[animation setkeytimes:times];</code>

<code>            </code><code>[animation setvalues:imagearray];</code>

<code>            </code><code>[animation settimingfunction:[camediatimingfunction functionwithname:kcamediatimingfunctionlinear]];</code>

<code>            </code><code>//設定循環</code>

<code>            </code><code>animation.repeatcount= maxfloat;</code>

<code>            </code><code>//設定播放總時長</code>

<code>            </code><code>animation.duration = totaltime;</code>

<code>            </code><code>//layer層添加</code>

<code>            </code><code>[[(uiimageview *)__self layer]addanimation:animation forkey:@</code><code>"gifanimation"</code><code>];</code>

<code>        </code><code>}];</code>

使用代碼示例如下:

<code>    </code><code>uiimageview * imageview = [[uiimageview alloc]initwithframe:cgrectmake(0,0 , 320, 200)];</code>

<code>    </code><code>nsurl * url = [[nsurl alloc]initfileurlwithpath:[[nsbundle mainbundle] pathforresource:imagename oftype:nil]];</code>

<code>    </code><code>[imageview yh_setimage:url];</code>

<code>    </code><code>[self.view addsubview:imageview];</code>

iOS中播放gif動态圖的方式探讨

    ios中的uiwebview功能十分強大,可以通過uiwebview為載體,來展示gif圖。并且這種方法也十分簡單,代碼如下:

<code>         </code><code>//讀取gif資料</code>

<code>         </code><code>nsdata *gifdata = [nsdata datawithcontentsofurl:imageurl];</code>

<code>        </code><code>uiwebview *webview = [[uiwebview alloc] initwithframe:cgrectmake(0, 0, self.frame.size.width, self.frame.size.height)];</code>

<code>        </code><code>//取消回彈效果</code>

<code>        </code><code>webview.scrollview.bounces=no;</code>

<code>        </code><code>webview.backgroundcolor = [uicolor clearcolor];</code>

<code>        </code><code>//設定縮放模式</code>

<code>        </code><code>webview.scalespagetofit = yes;</code>

<code>        </code><code>//用webview加載資料</code>

<code>        </code><code>[webview loaddata:gifdata mimetype:@</code><code>"image/gif"</code> <code>textencodingname:nil baseurl:nil];</code>

    經過測試,從加載速度上來說,通過uiimageview類别加載的方式更加快速,uiwebview的方式加載時間會稍長,但是從性能上來比較,webview的方式性能更優,播放的gif動态圖更加流暢。在開發中,可以根據需求,适當選擇,例如雖然webview加載的方式性能更好,但是在許多情況下,原生的uiimageview能夠更加自由的讓開發者進行擴充。

繼續閱讀