亚洲欧美色αv在线影视_一区二区三区在线 | 日_国产精品5c5c5c_久久狠狠中文字幕2017_尤物影院点击进入网站入口

卡片放大播放效果實現(xiàn)總結(jié),不同元素間的放大過渡效果如何實現(xiàn)?

2023-01-10 12:14:58 來源:程序員客棧

背景


(資料圖片)

最近一段時間做了幾個需求,其中涉及的素材列表展示,需要實現(xiàn)類似下方圖片中的動效,暫且稱之為【卡片放大播放動效】,具體細節(jié)如下:

初始展示的是封面圖片,鼠標經(jīng)過時是視頻放大的效果;下方文字內(nèi)容區(qū)域,在放大前后展示的內(nèi)容不同,而且兩者的字體大小是一致的,不是簡單的放大實現(xiàn);四五個頁面都需要實現(xiàn)相同列表效果,列表的行數(shù)和列數(shù)是不一致的;
image
遇到的四個問題

在整個實現(xiàn)過程中,遇到以下四個問題,后面的解析中會有對應解答。

不同元素間的放大過渡效果如何實現(xiàn)?抽離為通用性組件時,如何實現(xiàn)類vue中的具名插槽效果,來替換下方文字信息區(qū)域?不同頁面中的列表區(qū)域?qū)挾炔煌械捻撁媪斜磉€是彈性寬度,常用的flex布局無法滿足要求,如何實現(xiàn)呢?邊界卡片放大后,如何避免被父級列表容器overflow:hidden`隱藏掉?實現(xiàn)解析

這個動效,在愛奇藝官網(wǎng)也有類似效果,愛奇藝官網(wǎng)是通過生成初始狀態(tài)卡片列表和鼠標放大卡片列表兩套列表,然后通過動態(tài)計算放大卡片位置,相對于body進行絕對定位展示的。

本實現(xiàn)方案通過將卡片初始狀態(tài)和放大狀態(tài),封裝到一個組件中,通過兩者間的相對關(guān)系,利用css自動完成對應關(guān)系,避免了大量的JS計算。

1. 放大效果實現(xiàn)

UI對該動效的要求實際就是鼠標視頻放大播放,如果卡片初始狀態(tài)也放置視頻video,通過transition對同一元素進行scale放大也可以實現(xiàn),但是這是一個列表,用戶進入頁面,就會同時加載多個視頻,用戶體驗不是很好。

所以,實現(xiàn)方案就是卡片初始狀態(tài)放置poster圖片,鼠標經(jīng)過時,在poster上方展示視頻層(絕對定位),然后對視頻執(zhí)行animation動畫來模擬放大效果。

卡片底部文字區(qū)域如何處理?

由于卡片初始狀態(tài)下,底部文字區(qū)域在列表布局中是占位的,所以在卡片初始狀態(tài)下,底部文字區(qū)域使用正常文檔流。

卡片鼠標經(jīng)過狀態(tài)下,視頻層的放大效果是以poster中心點為放大原點的,所以底部文字區(qū)域使用absolute定位,相對于player進行定位處理。

interfaceIItemData{src?:string;poster?:string;industry?:string;}interfaceIProps{posterClass:string;//poster區(qū)域?qū)捀遬layerClass:string;//放大后視頻寬高樣式itemData:IItemData;children:{[key:string]:any};}lett:NodeJS.Timeout;constVideoItem:FC=({posterClass,playerClass,itemData,children,})=>{const[isHover,setIsHover]=useState(false);constonMouseEnter=()=>{t=setTimeout(()=>{//避免快速移動鼠標,造成視頻無法隱藏問題setIsHover(true);},50);};constonMouseLeave=()=>{clearTimeout(t);setIsHover(false);};return(Top1
{isHover?({children?.playerBottom}
):null}
{children?.posterBottom}
);};exportdefaultVideoItem;

.container{position:relative;.poster{position:relative;background-position:center;background-size:cover;background-repeat:no-repeat;.player{z-index:10;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)scale(0.929);animation:showPlayer0.2sease;animation-fill-mode:forwards;.playerBottom{width:100%;position:absolute;top:100%;left:0;box-shadow:0px6px16px-8pxrgba(0,0,0,0.08),0px12px48px16pxrgba(0,0,0,0.03);filter:drop-shadow(0px9px28pxrgba(0,0,0,0.05));}}}.posterBottom{width:100%;}}@keyframesshowPlayer{0%{transform:translate(-50%,-50%)scale(0.929);}100%{transform:translate(-50%,-50%)scale(1);}}

2. 抽離為通用組件時,卡片底部文字區(qū)域如何動態(tài)替換

整個卡片組件,底部的文字區(qū)域在不同的場景下可能是不同的,所以作為通用性組件,需要將這部分抽離,支持動態(tài)替換。

vue中最簡單的方式,就是插槽,通過插槽從外部動態(tài)傳入。但是react框架是不支持具名插槽的。所以,這個問題就轉(zhuǎn)換成了,react如何實現(xiàn)具名插槽?

網(wǎng)上搜到了一種實現(xiàn)方式,通過傳入一個object來實現(xiàn),具體效果如下:

//cardList{{posterBottom:bottomInfo,playerBottom:bottomInfo,onClickPlayer:()=>{consturl=`${window.location.origin}/#/market/service/${item.itemId}`;window.open(url,"_blank");},}}//VideoItem{props.children?.playerBottom}{props.children?.posterBottom}

當然,具名插槽還有其它的實現(xiàn)方式,后面會專門寫一篇文章總結(jié)學習下。

3. 列表容器如果是彈性布局時,每行的列數(shù)無法固定,flex布局無法滿足

這個問題是一個通用性問題,在容器寬度不固定時,flex布局,每行最后一個元素無法選中設置樣式,同時子元素個數(shù)不固定時,最后一行元素的間距會變大。

這種情況下,就需要grid布局大顯身手了,以前很少用grid布局,這次也是學習到了,具體效果如下圖:

在示例中,調(diào)整瀏覽器窗口大小,來實驗彈性布局觀看效果代碼片段

image.png
4. 卡片放大后,可能會被容器設置的overflow:hidden給遮蓋隱藏掉

目前放大效果的實現(xiàn)方式,放大的視頻層是絕對定位的,參照物是每個卡片本身。所以在四周邊界處的卡片,放大后,很容易被容器給遮蓋。

處理方式也很簡單,給容器多設置一些padding,讓放大部分足夠展示,然后用margin設置負值來調(diào)整布局

.container{margin-left:-20px;margin-right:-20px;padding-left:20px;padding-right:20px;}

總結(jié)

每個產(chǎn)品需求里,可能都會隱藏著自己的盲點,將效果做到極致,就能獲得技術(shù)成長。在重復的需求里,多反思總結(jié),尋找自己的提升點,這就是進步吧啊。

相關(guān)推薦

1.CSS 實現(xiàn)按鈕點擊動效的套路

2.年份數(shù)字拼圖效果

3.跑馬燈簡單版

4.中心點靠近動畫解析

標簽: 初始狀態(tài) 絕對定位 這個問題

推薦閱讀>