關於transition動畫下,如果有fixed元素,渲染的奇葩問題


之前我們機票頁面有生成一個低價日歷,然后我們有一個需求就是滾動到那個月份,對應顯示這個月,然后這個區域是fixed定位的,然后奇怪的事情發生了,就是低價日歷的動畫執行完后,修改頁面的html卻沒有正常更新。(因為那個區域顯示有點問題,我截圖的地方也是fixed元素) 


然后大家可以看到以上截圖,改變了dom后頁面沒有重新渲染(可以這里用詞有誤,反正是沒有渲染正常。)



然后我就找了小釵(http://www.cnblogs.com/yexiaochai/)一起幫我看問題,然后看了一個下午,當天只能得出一個結論就是:動畫可能影響了fixed元素的渲染。


昨天和今天,我一直找真正導致bug的原因,因為我們業務代碼幾千行,所以不好定位,所以我只好用最笨的方法,一點點刪代碼,然后最后把不可能影響到的代碼和樣式統統刪掉,直至確認出是日歷組件本身的問題。



幸好我認識框架組的同事之前拿了源碼。好為了快速進入,舍棄前戲部分,我就不說定位過程了,最后得出的結論就是
的確是動畫影響了,下面我們看看組件動畫做了寫什么事情:

然后這里我還不確定animate方法里做了神馬事情,所以我再進去animate的源碼里看
然后這個animate函數調用了anim函數,幾個參數大家都屬性吧,分別是修改的屬性(可多個)、過渡時間、過渡效果、動畫結束回調函數、延時執行時間。

方便初學者理解,我加了幾行注釋
cssValues打個斷點輸出,看下圖,其實就是把東西轉變成css3的transtion來達到這個過渡效果。

然后我再分別寫了幾個測試的小例子:
懶得寫可以直戳以下幾個鏈接:

1、在頁面出來前display:none;的例子
2、在動畫結束后append,fixed元素的例子
3、在頁面出來前display:!none;的例子
4、去掉回調里重置transform的例子
5、addClass模擬animate函數的例子
   

分別寫了5個例子(看每個例子前必強清除緩存),下面我盡簡單直接說一下分別什么不一樣。
例子1,就是如果父級一開始是display:none; 那么子級的fixed的元素修改渲染必然有問題(至少我測試下來是這樣):


例子2,如果動畫結束后append fixed元素,那個這個元素能正常渲染:


例子3,如果父級本來不是display:none;那么本來存在的子級fixed元素能正常渲染,動畫過程中加入的fixed元素不能正常渲染。


例子4,如果我把執行動畫結束后的transform重置去掉,那么無論是否display,和動畫期間加入的fixed元素修改后都能正常渲染。


例子5,如果我用addClass,來模擬animate的效果,setTimeout10秒后重置transform,在清除前無論是否display:none,動畫過程加入的元素都能修改、正常渲染,但是10秒transform強制設置為none后,渲染均有問題。

 

單個版本代碼如下,供自行修改嘗試。

 

 

    <meta name="viewport"
          content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html, body {
            width: 100%;
            height: 100%;
        }
        .transilate_wrap {
            width: 100%;
            height: 100%;
            display: block;
            background: #add8e6;
            position: absolute;
            top: 0px;
            left: 0px;
        }

        .fixed1 {
            width: 100%;
            height: 30px;
            display: inline-block;
            background: red;
            position: fixed;
        }

        .append_fixed {
            width: 100%;
            height: 40px;
            top: 50px;
            position: fixed;
            background: green;
        }
        .append_fixed2 {
            width: 100%;
            height: 40px;
            top: 120px;
            position: fixed;
            background: green;
        }
    </style>
</head>
<body>

<div class="transilate_wrap" style="position: absolute; z-index: 3001; top: 0px; right: 0px; left: 0px;display: none;">
    <div class="fixed1">
        before animate fixed
    </div>
</div>
</body>

<script src="./zepto.ctrip.js"></script>
<script>
    var $el = $('.transilate_wrap');

    $el.css({
        '-webkit-transform': 'translate(100%, 0)',
        transform: 'translate(100%, 0)'
    }).show().animate({
                '-webkit-transform': 'translate(0, 0)',
                transform: 'translate(0, 0)'
            }, 1500, 'ease-in-out', function () {
                $el.css({
                    '-webkit-transform': '',
                    transform: ''
                });
            });

    setTimeout(function () {
        $el.append('<h1 class="append_fixed">during animate</h1>');
    }, 100);


   /* setTimeout(function () {
        $el.append('<h1 class="append_fixed2">after animate</h1>');
    }, 1600);*/


</script>

 

 

 

最后引發這個奇葩問題,我還是得不到最終解析,忘有知道的大神請告知一下,感謝感謝!


免責聲明!

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



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