欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

css+js制作不定高度展開收起動畫詳解

 更新時間:2023年06月29日 09:19:51   作者:林恒  
這篇文章主要介紹了css+js制作不定高度展開收起動畫詳解的相關資料,需要的朋友可以參考下

最近在做需求的時候,遇見了元素高度展開收起的動畫需求,一開始是想到了使用 transition: all .3s; 來做動畫效果,在固定高度的情況下,transition 動畫很好使,滿足了需求,但是如果要考慮之后可能還會有更改的情況下,如果每次都是用固定高度來做動畫,會顯得很繁瑣,也很呆,就想到了使用 height: auto; 來做高度動畫,但是,眾所周知,高度設置成 auto 時是不會觸發(fā) transition 動畫的

.container {
    height: 0;
    background-color: #ccc;
    overflow: hidden;
    transition: all .3s;
}
.container:hover {
    height: 1000px;
}

效果如圖,不能滿足動畫的要求

在一番查找實驗之后,目前發(fā)現(xiàn)了如下幾種方法:

1. max-height 最大高度

transition 動畫可以響應 max-height

.container {
    max-height: 0;
    background-color: #ccc;
    overflow: hidden;
    transition: all .3s;
}
.container:hover {
    max-height: 1000px;
}

但是使用 max-height 做動畫有一個問題,如果設置的最大高度越大,但是實際高度確與最大高度相差甚遠,那么整體的動畫速度就會非常快,動畫的時間只會是 實際高度 / 最大高度 * 動畫時間,因為展開動畫原本預期高度是設置的最大高度,所以整體時間是以最大高度完全展開所用時間來進行的,但是當?shù)竭_實際高度的時候動畫就停止了,所以最終動畫時間會與期望時間相差甚遠。

max-height 方法做動畫也是一個好方法,如果能夠確定大致高度的話,使用此方法是最簡單也是最快的方法,但是如果不能確定大致高度或整體高度經(jīng)常變化的話,可以考慮其他方法。

2. grid 動畫

grid 網(wǎng)格布局,是一種較新的布局,號稱是最強大的布局方案。grid 布局不是本文的介紹重點,并且較為復雜,如果感興趣的話,可以參考相關文章,如:

寫給自己看的display: grid布局教程

最強大的 CSS 布局 —— Grid 布局

grid 布局中可以使用 fr 單位,fr 單位是支持過度動畫的(0fr=>1fr),將 grid 布局下的子元素,初始設置為0fr,在 :hover 狀態(tài)下設置為 1fr,就能夠實現(xiàn)不定高度動畫效果,但是如果子元素有內(nèi)容,在設置 0fr 的時候,會被其內(nèi)容撐開,所以要給子元素添加 min-height: 0;

.container {
    display: grid;
    grid-template-rows: 0fr;
    overflow: hidden;
    transition: all .3s;
}
.container:hover {
    grid-template-rows: 1fr;
}
.container .child {
    min-height: 0;
}

如果想要實現(xiàn)帶有基礎高度的展開收起動畫,我們可以設置 min-height: 100px;

.container .child {
    min-height: 100px;
}

雖然此時實現(xiàn)了帶有基礎高度的動畫效果,但是可以看到,如果我把 transition: all 3s; 的動畫時間設置的較大,就可以看出來,雖然有基礎高度,但是整個動畫的效果還是要實現(xiàn) 0fr1fr 的動畫效果,基礎高度部分不會有動畫效果,這也算是一個小的缺點,如果動畫時間較短并且基礎高度也不大的話,可以這樣使用,并不會有太大的影響效果。

但是 grid 布局有可能有兼容性的問題,grid-template-rows 動畫的支持可能有兼容性問題

3. js 控制動畫

寫這篇文章的原因是因為在看項目代碼的時候看見了 $(.xx).slideDown() 方法實現(xiàn)了元素的下滑動畫,覺得很不錯,想學習一下怎么實現(xiàn)的,實現(xiàn)效果如下:

但是在看元素的時候卻只能看見下面的樣子,發(fā)現(xiàn)不是 css 實現(xiàn)的,是使用 js 不斷改變元素的高度來實現(xiàn)的:

我又去看了一下 ant-designMenu 組件,通過觀察元素,發(fā)現(xiàn)其也是不斷改變高度來實現(xiàn)的(Ps: 我并沒有去看源碼,如果有誤,多謝指正)。

實現(xiàn)

首先要思考整個實現(xiàn)的思路

展開的時候,元素從無到有,我們應該首先獲取整個元素的實際高度使用 offsetHeight 來獲取,獲取到整體高度后就要計算每一次增加或者減少的高度,通過定時器不斷增加或減少元素的高度,直到到了最大高度或 0 后停止

展開

const element = document.getElementById('container');
let expandTimer = null;
let offsetHeight = 0;
// 獲取元素總高度
element.style.display = 'block';
let height = 0;
// 先將 display 設置為 block,獲取到的 offsetHeight 才是正確的高度,之后才能設置元素高度
offsetHeight = element.offsetHeight;
const stepHeight = offsetHeight / 30;
element.style.height = height + 'px';
expandTimer = setInterval(() => {
    height += stepHeight;
    if (height >= offsetHeight) {
        clearInterval(expandTimer);
        element.style = null;
        return;
    }
    element.style.height = height + 'px';
}, 10);

收起

let collapseTimer = null;

offsetHeight = element.offsetHeight;
let height = offsetHeight;

const stepHeight = offsetHeight / 30;
element.style.height = height + 'px';

collapseTimer = setInterval(() => {
    height -= stepHeight;
    if (height <= 0) {
        clearInterval(collapseTimer);
        element.style = null;
        return;
    }
    element.style.height = height + 'px';
}, 10);

現(xiàn)在能夠正確展開收起,但是我們在展開收起的時候也會有相反的操作,比如鼠標進入元素展開離開收起,在展開的過程中鼠標離開了,我們應該立刻就將元素收起,而不是等動畫結束后在進行下一個動畫,所以要將展開收起操作合并操作才可以

const element = document.getElementById('container');
let expandTimer = null;
let collapseTimer = null;
// 我認為在一次展開后,直到收起完成之前,這個元素的實際高度都不應該發(fā)生變化,但是可以在下一次展開時發(fā)生變化,所以在展開時會進行賦值,在收起完成時會將此值清空
let offsetHeight = 0;
let stepHeight = 0;

const handleClick = () => {
    // 如果當前 expandTimer 值存在,就標識當前是正在展開或已經(jīng)展開,接下來要進行的是收起操作
    if (expandTimer) {
        clearInterval(expandTimer);
        expandTimer = null;
        // 收起時的初始高度是元素的當前實際高度,即使是元素在展開動畫過程中,也要從當前元素高度進行收起動畫
        let height = element.offsetHeight;

        collapseTimer = setInterval(() => {
            height -= stepHeight;
            if (height <= 0) {
                // 高度小于等于 0 代表動畫完成,將數(shù)據(jù)進行重置
                clearInterval(collapseTimer);
                offsetHeight = 0;
                // 要將元素的高度置為 null,不然會影響下一次展開時獲取正確的高度
                element.style.height = null;
                // display 設為 null,要將元素隱藏
                element.style.display = 'none';
                return;
            }
            element.style.height = height + 'px';
        }, 10);
    } else {
        clearInterval(collapseTimer);
        collapseTimer = null;
        // 獲取元素總高度
        element.style.display = 'block';
        let height = 0;
        如果當前沒有 offsetHeight 就要重新獲取
        if (!offsetHeight) {
            offsetHeight = element.offsetHeight;
            // 每一次給元素添加或減少的高度,除以 30 是自己設定的,跟下面定時器的每次間隔時間一起控制整個高度動畫的時長,也可以給函數(shù)添加第二個時間參數(shù),可以自由控制動畫時間
            stepHeight = offsetHeight / 30;
        } else {
            // 如果有 offsetHeight 就代表正在進行收起動畫,應該從收起動畫的當前高度進行展開動畫
            height = element.offsetHeight;
        }
        
        element.style.height = height + 'px';

        expandTimer = setInterval(() => {
            height += stepHeight;
            if (height >= offsetHeight) {
                // 當前高度如果已經(jīng)到了元素的實際高度,就要清除定時器
                clearInterval(expandTimer);
                // 將 expandTimer 設為 1 是因為當前是以 expandTimer 判斷是否正在或已經(jīng)進行了展開動畫,所以要在完成是設為 1,在收起動畫的開始時會將值設為 null
                expandTimer = 1;
                element.style = null;
                return;
            }
            element.style.height = height + 'px';
        }, 10);
    }
};

最終實現(xiàn)效果

4. 總結

上面的三種方式實現(xiàn)效果都是各有千秋 - max-height 方法實現(xiàn)是最簡單,也是效率最高的方式,但是也有動畫時間不定的缺陷 - grid 方式實現(xiàn)比 max-height 稍微復雜一些,但是整體效果要比 max-height 更好,但是目前瀏覽器的支持方面可能有所不足,如果有低版本的兼容性要求的話,還是不能使用 - js 方式整體最復雜,但是卻沒有上面兩種方式的缺陷與問題,使用范圍也更廣泛,但是是 js 的實現(xiàn)方式,性能肯定是不如 css,雖然不如,但是由于整體操作也較為簡單,所以也不會有什么性能問題

幾種方法的取舍全看個人需求了。

如果有鼠標進入展開,離開收起的操作,可以配合使用 onmouseover onmouseout 事件來監(jiān)聽鼠標的進入離開。

其他還有像是 transform: scale(0); 的實現(xiàn)也是可以,但是整體動畫效果就是一個縮小的效果,而且元素還會有占位問題,如果沒什么要求也是可以使用的。

到此這篇關于css+js制作不定高度展開收起動畫詳解的文章就介紹到這了,更多相關css+js制作展開收起動畫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JavaScript自定義日歷實現(xiàn)簽到功能

    JavaScript自定義日歷實現(xiàn)簽到功能

    這篇文章主要為大家詳細介紹了JavaScript自定義日歷實現(xiàn)簽到功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 詳解js的事件代理(委托)

    詳解js的事件代理(委托)

    JavaScript事件代理(委托)一般用于以下情況:1. 事件注冊在祖先級元素上,代理其子級元素??梢詼p少事件注冊數(shù)量,節(jié)約內(nèi)存開銷,提高性能。2. 對js動態(tài)添加的子元素可自動綁定事件。本文主要介紹用原生 js 實現(xiàn)該功能。下面跟著小編一起來看下吧
    2016-12-12
  • 原生js編寫基于面向對象的分頁組件

    原生js編寫基于面向對象的分頁組件

    這篇文章主要為大家詳細介紹了原生js編寫基于面向對象的分頁組件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 微信小程序中遇到的iOS兼容性問題小結

    微信小程序中遇到的iOS兼容性問題小結

    這篇文章主要給大家介紹了關于微信小程序中遇到的一些iOS兼容性問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-11-11
  • js/html光標定位的實現(xiàn)代碼

    js/html光標定位的實現(xiàn)代碼

    光標定位,想必大家有所了解吧,在本文將為大家介紹的是通過自定義函數(shù)來實現(xiàn)標簽元素的定位,感興趣的朋友可以了解下
    2013-09-09
  • js實現(xiàn)輪播圖的完整代碼

    js實現(xiàn)輪播圖的完整代碼

    這篇文章主要為大家詳細介紹了js實現(xiàn)輪播圖的完整代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • es6函數(shù)之嚴格模式用法實例分析

    es6函數(shù)之嚴格模式用法實例分析

    這篇文章主要介紹了es6函數(shù)之嚴格模式用法,結合實例形式分析了es6函數(shù)嚴格模式的定義、用法及操作注意事項,需要的朋友可以參考下
    2020-03-03
  • Axios設置token請求頭的三種方式

    Axios設置token請求頭的三種方式

    用戶登錄時,后端會返回一個token,并且保存到瀏覽器的localstorage中,可以根據(jù)localstorage中的token判斷用戶是否登錄,所以當發(fā)送請求時,都要攜帶token給后端進行判斷,本文給大家介紹了Axios設置token請求頭的三種方式,需要的朋友可以參考下
    2024-02-02
  • Bootstrap模態(tài)框調(diào)用功能實現(xiàn)方法

    Bootstrap模態(tài)框調(diào)用功能實現(xiàn)方法

    這篇文章主要介紹了Bootstrap模態(tài)框調(diào)用功能實現(xiàn)方法的相關資料,非常不錯,具有參考借鑒價值,感興趣的朋友一起看看吧
    2016-09-09
  • JavaScript實現(xiàn)人體面部活體檢測的功能

    JavaScript實現(xiàn)人體面部活體檢測的功能

    本文詳細介紹了如何在瀏覽器端使用JavaScript實現(xiàn)高可靠度的人臉活體檢測,包括核心原理、可行方案、優(yōu)缺點對比以及示例代碼,感興趣的朋友一起看看吧
    2025-02-02

最新評論