AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

使用 React Hooks 實(shí)現(xiàn)鼠標(biāo)懸浮卡片發(fā)光的動(dòng)畫效果

來源: 責(zé)編: 時(shí)間:2024-06-05 17:43:48 124觀看
導(dǎo)讀有趣的動(dòng)畫效果前幾天在網(wǎng)上看到了一個(gè)很有趣的動(dòng)畫效果,如下,光會(huì)跟隨鼠標(biāo)在卡片上進(jìn)行移動(dòng),并且卡片會(huì)有視差的效果,那么在 React 中應(yīng)該如何去實(shí)現(xiàn)這個(gè)效果呢?基本實(shí)現(xiàn)思路其實(shí)實(shí)現(xiàn)思路很簡(jiǎn)單,無非就是分幾步:首先,卡片是

有趣的動(dòng)畫效果

前幾天在網(wǎng)上看到了一個(gè)很有趣的動(dòng)畫效果,如下,光會(huì)跟隨鼠標(biāo)在卡片上進(jìn)行移動(dòng),并且卡片會(huì)有視差的效果,那么在 React 中應(yīng)該如何去實(shí)現(xiàn)這個(gè)效果呢?BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

基本實(shí)現(xiàn)思路

其實(shí)實(shí)現(xiàn)思路很簡(jiǎn)單,無非就是分幾步:BoP28資訊網(wǎng)——每日最新資訊28at.com

  • 首先,卡片是相對(duì)定位,光是絕對(duì)定位
  • 監(jiān)聽卡片的鼠標(biāo)移入事件mouseenter,當(dāng)鼠標(biāo)進(jìn)入時(shí)顯示光
  • 監(jiān)聽卡片的鼠標(biāo)移動(dòng)事件mouseover,鼠標(biāo)移動(dòng)時(shí)修改光的left、top,讓光跟隨鼠標(biāo)移動(dòng)
  • 監(jiān)聽卡片的鼠標(biāo)移出事件mouseleave,鼠標(biāo)移出時(shí),隱藏光

我們先在 Index.tsx 中準(zhǔn)備一個(gè)卡片頁面,光的CSS效果可以使用filter: blur() 來實(shí)現(xiàn):BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

卡片視差效果

卡片的視差效果需要用到樣式中 transform 樣式,主要是配置四個(gè)東西:BoP28資訊網(wǎng)——每日最新資訊28at.com

  • perspective:定義元素在 3D 變換時(shí)的透視效果
  • rotateX:X 軸旋轉(zhuǎn)角度
  • rotateY:Y 軸旋轉(zhuǎn)角度
  • scale3d:X/Y/Z 軸上的縮放比例

BoP28資訊網(wǎng)——每日最新資訊28at.com

給所有卡片添加光源

上面只是給一個(gè)卡片增加光源,接下來可以給每一個(gè)卡片都增加光源啦?。?!BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

讓光源變成可配置

上面的代碼,總感覺這個(gè) hooks 耦合度太高不太通用,所以我們可以讓光源變成可配置化,這樣每個(gè)卡片就可以展示不同大小、顏色的光源了~像下面一樣:BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

既然是配置化,那我們希望是這么去使用 hooks 的,我們并不需要自己在頁面中去寫光源的dom節(jié)點(diǎn),也不需要自己去寫光源的樣式,而是通過配置傳入 hooks 中:BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

所以 hooks 內(nèi)部要自己通過操作 DOM 的方式,去添加、刪除光源,可以使用createElement、appendChild、removeChild 去做這些事~BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

BoP28資訊網(wǎng)——每日最新資訊28at.com

完整源碼

// use-light-card.tsimport { useEffect, useRef } from 'react';interface IOptions {  light?: {    width?: number; // 寬    height?: number; // 高    color?: string; // 顏色    blur?: number; // filter: blur()  };}export const useLightCard = (option: IOptions = {}) => {  // 獲取卡片的dom節(jié)點(diǎn)  const cardRef = useRef<HTMLDivElement | null>(null);  let cardOverflow = '';  // 光的dom節(jié)點(diǎn)  const lightRef = useRef<HTMLDivElement>(document.createElement('div'));  // 設(shè)置光源的樣式  const setLightStyle = () => {    const { width = 60, height = 60, color = '#ff4132', blur = 40 } = option.light ?? {};    const lightDom = lightRef.current;    lightDom.style.position = 'absolute';    lightDom.style.width = `${width}px`;    lightDom.style.height = `${height}px`;    lightDom.style.background = color;    lightDom.style.filter = `blur(${blur}px)`;  };  // 設(shè)置卡片的 overflow 為 hidden  const setCardOverflowHidden = () => {    const cardDom = cardRef.current;    if (cardDom) {      cardOverflow = cardDom.style.overflow;      cardDom.style.overflow = 'hidden';    }  };  // 還原卡片的 overflow  const restoreCardOverflow = () => {    const cardDom = cardRef.current;    if (cardDom) {      cardDom.style.overflow = cardOverflow;    }  };  // 往卡片添加光源  const addLight = () => {    const cardDom = cardRef.current;    if (cardDom) {      cardDom.appendChild(lightRef.current);    }  };  // 刪除光源  const removeLight = () => {    const cardDom = cardRef.current;    if (cardDom) {      cardDom.removeChild(lightRef.current);    }  };  // 監(jiān)聽卡片的鼠標(biāo)移入  const onMouseEnter = () => {    // 添加光源    addLight();    setCardOverflowHidden();  };  // use-light-card.ts  // 監(jiān)聽卡片的鼠標(biāo)移動(dòng)  const onMouseMove = (e: MouseEvent) => {    // 獲取鼠標(biāo)的坐標(biāo)    const { clientX, clientY } = e;    // 讓光跟隨鼠標(biāo)    const cardDom = cardRef.current;    const lightDom = lightRef.current;    if (cardDom) {      // 獲取卡片相對(duì)于窗口的x和y坐標(biāo)      const { x, y } = cardDom.getBoundingClientRect();      // 獲取光的寬高      const { width, height } = lightDom.getBoundingClientRect();      lightDom.style.left = `${clientX - x - width / 2}px`;      lightDom.style.top = `${clientY - y - height / 2}px`;      //   設(shè)置動(dòng)畫效果      const maxXRotation = 10; // X 軸旋轉(zhuǎn)角度      const maxYRotation = 10; // Y 軸旋轉(zhuǎn)角度      const rangeX = 200 / 2; // X 軸旋轉(zhuǎn)的范圍      const rangeY = 200 / 2; // Y 軸旋轉(zhuǎn)的范圍      const rotateX = ((clientX - x - rangeY) / rangeY) * maxXRotation; // 根據(jù)鼠標(biāo)在 Y 軸上的位置計(jì)算繞 X 軸的旋轉(zhuǎn)角度      const rotateY = -1 * ((clientY - y - rangeX) / rangeX) * maxYRotation; // 根據(jù)鼠標(biāo)在 X 軸上的位置計(jì)算繞 Y 軸的旋轉(zhuǎn)角度      cardDom.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`; //設(shè)置 3D 透視    }  };  // 監(jiān)聽卡片鼠標(biāo)移出  const onMouseLeave = () => {    // 鼠標(biāo)離開移出光源    removeLight();    restoreCardOverflow();  };  useEffect(() => {    // 設(shè)置光源樣式    setLightStyle();    // 綁定事件    cardRef.current?.addEventListener('mouseenter', onMouseEnter);    cardRef.current?.addEventListener('mousemove', onMouseMove);    cardRef.current?.addEventListener('mouseleave', onMouseLeave);    return () => {        // 解綁事件        cardRef.current?.removeEventListener('mouseenter', onMouseEnter);        cardRef.current?.removeEventListener('mousemove', onMouseMove);        cardRef.current?.removeEventListener('mouseleave', onMouseLeave);    }  })  return {    cardRef,  };};// Index.tsximport './Index.less'import { useLightCard } from './use-light-card'const Index = () => {    const { cardRef: cardRef1 } = useLightCard()    const { cardRef: cardRef2 } = useLightCard({        light: {            color: '#ffffff',            width: 100        }    })    const { cardRef: cardRef3 } = useLightCard({        light: {            color: 'yellow'        }    })    return <div className='light-card-container'>        {/* 方塊盒子 */}        <div className='item' ref={cardRef1}></div>        {/* 方塊盒子 */}        <div className='item' ref={cardRef2}></div>        {/* 方塊盒子 */}        <div className='item' ref={cardRef3}></div>    </div>}export default Index// Index.less.light-card-container {    background: black;    width: 100%;    height: 100%;    padding: 200px;    display: flex;    justify-content: space-between;      .item {      position: relative;      width: 125px;      height: 125px;      background: #1c1c1f;      border: 1px solid rgba(255, 255, 255, 0.1);      // 不需要了      // .light {      //   width: 60px;      //   height: 60px;      //   background: #ff4132;      //   filter: blur(40px);      //   position: absolute;      // }    }}

結(jié)語

BoP28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-92131-0.html使用 React Hooks 實(shí)現(xiàn)鼠標(biāo)懸浮卡片發(fā)光的動(dòng)畫效果

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 25個(gè)每個(gè)開發(fā)人員都應(yīng)該知道的CSS 技巧

下一篇: C# 異常處理:每個(gè) .NET 開發(fā)者都應(yīng)掌握的核心知識(shí)點(diǎn)

標(biāo)簽:
  • 熱門焦點(diǎn)
  • 紅魔電競(jìng)平板評(píng)測(cè):大屏幕硬實(shí)力

    前言:三年的疫情因?yàn)橐暇W(wǎng)課的原因激活了平板市場(chǎng),如今網(wǎng)課的時(shí)代已經(jīng)過去,大家的生活都恢復(fù)到了正軌,這也就意味著,真正考驗(yàn)平板電腦生存的環(huán)境來了。也就是面對(duì)著這種殘酷的
  • 之家push系統(tǒng)迭代之路

    前言在這個(gè)信息爆炸的互聯(lián)網(wǎng)時(shí)代,能夠及時(shí)準(zhǔn)確獲取信息是當(dāng)今社會(huì)要解決的關(guān)鍵問題之一。隨著之家用戶體量和內(nèi)容規(guī)模的不斷增大,傳統(tǒng)的靠"主動(dòng)拉"獲取信息的方式已不能滿足用
  • 深度探索 Elasticsearch 8.X:function_score 參數(shù)解讀與實(shí)戰(zhàn)案例分析

    在 Elasticsearch 中,function_score 可以讓我們?cè)诓樵兊耐瑫r(shí)對(duì)搜索結(jié)果進(jìn)行自定義評(píng)分。function_score 提供了一系列的參數(shù)和函數(shù)讓我們可以根據(jù)需求靈活地進(jìn)行設(shè)置。近期
  • 一篇文章帶你了解 CSS 屬性選擇器

    屬性選擇器對(duì)帶有指定屬性的 HTML 元素設(shè)置樣式??梢詾閾碛兄付▽傩缘?HTML 元素設(shè)置樣式,而不僅限于 class 和 id 屬性。一、了解屬性選擇器CSS屬性選擇器提供了一種簡(jiǎn)單而
  • 2天漲粉255萬,又一賽道在抖音爆火

    來源:運(yùn)營(yíng)研究社作者 | 張知白編輯 | 楊佩汶設(shè)計(jì) | 晏談夢(mèng)潔這個(gè)暑期,旅游賽道徹底火了:有的「地方」火了&mdash;&mdash;貴州村超旅游收入 1 個(gè)月超過 12 億;有的「博主」火了&m
  • 消費(fèi)結(jié)構(gòu)調(diào)整丨巨頭低價(jià)博弈,拼多多還卷得動(dòng)嗎?

    來源:征探財(cái)經(jīng)作者:陳香羽隨著流量紅利的退潮,電商的存量博弈越來越明顯。曾經(jīng)主攻中高端與品質(zhì)的淘寶天貓、京東重拾&ldquo;低價(jià)&rdquo;口號(hào)。而過去與他們錯(cuò)位競(jìng)爭(zhēng)的拼多多,靠
  • 品牌洞察丨服務(wù)本地,美團(tuán)直播成效幾何?

    來源:17PR7月11日,美團(tuán)App首頁推薦位出現(xiàn)&ldquo;美團(tuán)直播&rdquo;的固定入口。在直播聚合頁面,外賣&ldquo;神槍手&rdquo;直播間、美團(tuán)旅行直播間、美團(tuán)買菜直播間等均已上線,同時(shí)
  • 微博大門常打開,迎接海外畫師漂洋東渡

    作者:互聯(lián)網(wǎng)那些事&ldquo;起猛了,我能看得懂日語了&rdquo;。&ldquo;為什么日本人說話我能聽懂?&rdquo;&ldquo;中文不像中文,日語不像日語,但是我竟然看懂了&rdquo;&hellip;&hell
  • 滴滴違法違規(guī)被罰80.26億 共存在16項(xiàng)違法事實(shí)

    滴滴違法違規(guī)被罰80.26億 存在16項(xiàng)違法事實(shí)開始于2121年7月,歷經(jīng)一年時(shí)間,網(wǎng)絡(luò)安全審查辦公室對(duì)“滴滴出行”網(wǎng)絡(luò)安全審查終于有了一個(gè)暫時(shí)的結(jié)束。據(jù)“網(wǎng)信
Top