動畫在webapp中的現狀


webapp的一大優勢便是在view切換時候可以擁有媲美與native的動畫效果,但是很多時候那只是一種想法,真正的情況卻不是這樣
產生此問題的原因有:
① 手機CPU爛!
② 手機顯卡爛!就算四核其渲染也很有問題
③ 高端手機瀏覽器會有BUG
④ 低端手機支持不好(國內山寨機笑而不語)
因為以上原因,事實上做webapp的都會不同程度的弱化動畫,或者在局部區域使用動畫
問題雖難,總有方案,事實上的情況是,幾行代碼搞死人,就我們的這個動畫問題,前后過手幾輪
最后又回到了我手上,中間甚至經手了國內著名的前端,其中兩位還出過書,所以說動畫老大難問題在移動端是真心難,今天就我所知的動畫做一次分享,希望對各位有幫助,若是有好方案,麻煩賜教一番

難在何處

dom樹過多
view的移動與簡單的圖片slider組件相差甚劇!原因便是其dom結構可能很復雜,大dom樹的移動在移動端效果很差
就簡單列表頁來說,當項目超過100個時,使用IScroll類插件都應該很慎重,這類移動可能非常卡!
而且dom樹復雜度與業務直接相關,我們沒有任何辦法去控制dom樹,因為業務代碼可能不會經過我們的手,就算經過,你又肯定自己做出來的dom樹有多小?不見得吧
長短頁問題
所謂長短頁便是一個view很長一個view很短,這里問題處理十分討厭
首先我們每次做切換需要將view位置切換至頭部(window.scroll(0, 0))如此的話ios中會引起
頁面viewport的變化(系統自動發生),或者會觸發低端工具欄的出現,這個時候頁面抖動無可避免
若是每次不執行window.scroll(0, 0),切換時候又會導致短的view不可見
我現階段想到的解決方案是,移動時候將scroll設得比較大,移動時候將bview的top值與scrollTop相同
最后仍然需要執行window.scroll(0, 0)的操作,所以,這個問題只能緩解,無法解決
手機渲染問題
只要是做移動端的朋友,一定會對三星機或者一些低端機的渲染嗤之以鼻!
具體表現為多次操作style后,后面的操作瀏覽器不會搭理你
解決方案是:
① 引起瀏覽器強烈重繪
② 臨時增刪一個dom結構
但是涉及view切換動畫的話,很有可能會出現一些莫名其妙的問題!

動畫的掙扎

以上是幾個不可避免會遇到的問題,所謂解決方案,也不過自欺欺人
如果不能提高效率,動畫時候最大程度的減小DOM結構便是唯一方法,就算減少render Tree也是一種進步
其基本想法是只顯示視口處的元素,其余不予理睬
 1 var FastRender = new inherit({
 2 
 3   initialize: function(opts) {
 4     this.handleOpts(opts);
 5     this.init();
 6   },
 7 
 8   handleOpts: function(opts) {
 9     if (!opts || !opts.doms || !opts.doms.length) throw 'FastRender param error';
10     this.doms = opts.doms;
11     this.container = opts.container || $(window);
12     this.renderContainer = {};
13     this.step = 50;
14 
15   },
16 
17   init: function() {
18     this.initImgContainer();
19     this.initRender();
20     this.bindEvents();
21   },
22 
23   bindEvents: function() {
24 
25     //為container綁定事件
26     this.container.on('scroll.fastRender', $.proxy(function() {
27       this.initRender();
28     },
29     this));
30   },
31 
32   initImgContainer: function() {
33     var el, i, len, offset;
34     for (i = 0, len = this.doms.length; i < len; i++) {
35       el = $(this.doms[i]);
36       offset = el.offset();
37 
38       //這塊卡
39       //      (function (el) {
40       //        setTimeout(function () {
41       el.css({
42         'width': offset.width,
43         'height': offset.height
44       });
45       //        }, 0);
46       //      })(el);
47 
48       if (!this.renderContainer[offset.top]) {
49         this.renderContainer[offset.top] = [];
50       }
51       this.renderContainer[offset.top].push(el);
52     }
53 
54   },
55 
56   /*
57         這里需要對對象遍歷做優化,以坐標搜索替換數值搜索
58 
59         */
60   initRender: function() {
61     var height = this.container.height();
62     var srollHeight = this.container.scrollTop();
63     var k, _imgs, el, i, len, els;
64 
65     this.doms.removeClass('wl');
66 
67     for (k in this.renderContainer) {
68       //                        if ((parseInt(k) < srollHeight + height + this.step) && (parseInt(k) > srollHeight - this.step)) {
69       if ((parseInt(k) < srollHeight + height - this.step) && (parseInt(k) > srollHeight + this.step)) {
70 
71         els = this.renderContainer[k];
72         for (i = 0, len = els.length; i < len; i++) {
73           el = $(els[i]);
74           el.find('.lazy_wrapper').show();
75         }
76       } else {
77         els = this.renderContainer[k];
78         for (i = 0, len = els.length; i < len; i++) {
79           el = $(els[i]);
80           el.find('.lazy_wrapper').hide();
81         }
82 
83       }
84     } // for
85 
86   },
87 
88   destroy: function() {
89     //為container綁定事件
90     this.container.off('.fastRender');
91   }
92 
93 });
94 
95 var f = new FastRender({
96   doms: $('.js_hotel_detail')
97 });

這個demo想法很美好,若是可實現的話,無疑是移動端一大功臣,事實上是

瀏覽器:10分

IOS(4000):6分

android小米(1800):5分

化為4核:4分(1800)

其表現在瀏覽器上很好,手機上便不行了,所以今日的論證失敗,該方案還需優化

這個結果其實可以預見,在渲染上手機根本跟不上,所以平滑度就跟不上,方案拋棄

換個方向想,若是可以繞過DOM樹過多問題也是可取,比如移動時候直接以一個白頁做動畫,這個方案比較可恥

另一個方案是使用cavas為本頁面生成一個縮略圖,每次移動實際上是縮略圖,如此動畫是順暢了,但是此方案甚難,還可能引起其它問題,此方案我得再做驗證

結局

結局並不美好,此問題我未找到很好的解決方案,移動端的動畫還有很長的路要走......


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM