vue3實(shí)現(xiàn)tabs導(dǎo)航欄點(diǎn)擊每個(gè)導(dǎo)航項(xiàng)有下劃線動(dòng)畫效果
vue3實(shí)現(xiàn)tabs導(dǎo)航欄,點(diǎn)擊每個(gè)導(dǎo)航項(xiàng)有下劃線動(dòng)畫效果
<template> <div class="navigation"> <div v-for="(item, index) in items" :key="index" class="navigation-item" :class="{ active: index === activeIndex }" @click="activeIndex = index" ref="itemRefs" > {{ item }} </div> <div class="navigation-underline" :class="{ active: activeIndex !== -1 }" :style="underlineStyle" ref="underlineRef" ></div> </div> </template> <script setup> import { ref, watch, onMounted } from "vue"; const activeIndex = ref(0); const items = ref(["Home", "About", "Services", "Services"]); const underlineStyle = ref({ transform: "translateX(0)", }); const itemRefs = ref([]); const underlineRef = ref(null); const updateUnderline = () => { // 獲取標(biāo)題的寬度,減去下劃線的寬度除以2,可以使下劃線在標(biāo)題下居中顯示 const item = itemRefs.value[activeIndex.value]; const underline = underlineRef.value; let newLeft = Number((item.offsetWidth - underline.offsetWidth)) / 2; if (item && underline) { const { offsetLeft } = item; console.log(offsetLeft); underlineStyle.value = { transform: `translateX(${offsetLeft + newLeft}px)`, }; } }; watch(activeIndex, () => { updateUnderline(); }); onMounted(() => { updateUnderline(); }); </script> <style> .navigation { width: 400px; display: flex; align-items: center; justify-content: space-around; position: relative; padding: 0 20px; height: 50px; font-size: 16px; font-weight: bold; } .navigation-item { cursor: pointer; } .navigation-item.active { color: #f00; } .navigation-underline { /* 下劃線的寬度 */ width: 50px; height: 3px; border-radius: 2px; position: absolute; bottom: 0; left: 0; background-color: #f00; transition: all 0.3s ease-in-out; } .navigation-underline.active { transform: translateY(-3px); } </style>
效果圖:
vue 實(shí)現(xiàn)類似于錨點(diǎn)滑動(dòng) 或者點(diǎn)擊不同的tab時(shí)添加下劃線并滑動(dòng)到對(duì)應(yīng)的盒子,手動(dòng)滑動(dòng)下劃線也隨位置變動(dòng)
1、這個(gè)方法有個(gè)不好的地方就是要自己算每個(gè)盒子要滑動(dòng)的高度,下面是結(jié)構(gòu)
<ul> <li class="liTem" :class="{ acver: currentTab === 'tab1' }" @click="scrollToTab('tab1')">首頁(yè)</li> <li class="liTem" :class="{ acver: currentTab === 'tab2' }" @click="scrollToTab('tab2')">服務(wù)內(nèi)容</li> <li class="liTem" :class="{ acver: currentTab === 'tab3' }" @click="scrollToTab('tab3')">業(yè)務(wù)案例</li> <li class="liTem" :class="{ acver: currentTab === 'tab4' }" @click="scrollToTab('tab4')">關(guān)于我們</li> <li class="liTem" :class="{ acver: currentTab === 'tab5' }" @click="scrollToTab('tab5')">聯(lián)系方式</li> </ul> <div class="section1 " id="section1">Section 1</div> <div class="section2 " id="section2">Section 2</div> <div class="section3 " id="section3">Section 3</div>
2、簡(jiǎn)單寫點(diǎn)css
.tabsul { position: fixed; top: 0; left: 0; width: 100%; background-color: #f0f0f0; display: flex; justify-content: center; z-index: 1000; } .liTem { padding: 0 0px 5px 0px; box-sizing: border-box; height: 35px; text-align: center; font-size: 16px; font-weight: 500; margin: 0 20px; cursor: pointer; } .section { display: flex; justify-content: center; font-size: 24px; color: #fff; border: 1px solid #ccc; } .section1{ height: 430px; background: #48a994; } .section2{ height: 1200px; background: #49396f; } .section3{ height: 600px; background: #349f64; } .section4{ height: 1200px; background: #9c7d39; } .acver { font-size: 16px; font-weight: 500; border-bottom: 3px #ff8000 solid; }
3、在data里聲明這些變量
currentTab: "tab1", tabScrollPositions: { // 每個(gè)tab對(duì)應(yīng)的滾動(dòng)位置 tab1: 0, tab2: 670, tab3: 1700, // tab4: 4360, tab4: 3760, tab5: 5015, },
4、這里寫點(diǎn)擊事件
mounted() { window.addEventListener("scroll", this.handleScroll); }, beforeDestroy() { window.removeEventListener("scroll", this.handleScroll); }, methods: { scrollToTab(tab) { this.currentTab = tab; const position = this.tabScrollPositions[tab]; window.scrollTo({ top: position, behavior: "smooth", }); }, handleScroll() { const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; for (const tab in this.tabScrollPositions) { if ( scrollTop >= this.tabScrollPositions[tab] - 50 && scrollTop < this.tabScrollPositions[tab] + 50 ) { // 假設(shè)50是閾值 this.currentTab = tab; break; } } }, }
到此這篇關(guān)于vue3實(shí)現(xiàn)tabs導(dǎo)航欄點(diǎn)擊每個(gè)導(dǎo)航項(xiàng)有下劃線動(dòng)畫效果的文章就介紹到這了,更多相關(guān)vue3 tabs導(dǎo)航欄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何使用vue實(shí)現(xiàn)可視化界面設(shè)計(jì)
Vue是一款流行的前端開發(fā)框架,它的響應(yīng)式數(shù)據(jù)綁定和組件化特性使得它成為了可視化界面設(shè)計(jì)的一個(gè)理想選擇,本文將介紹如何使用Vue實(shí)現(xiàn)可視化界面設(shè)計(jì),并且演示一個(gè)基于Vue的可視化界面設(shè)計(jì)案例,需要的朋友可以參考下2023-12-12Vue源碼解析之Template轉(zhuǎn)化為AST的實(shí)現(xiàn)方法
這篇文章主要介紹了Vue源碼解析之Template轉(zhuǎn)化為AST的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12vue-pdf插件實(shí)現(xiàn)pdf文檔預(yù)覽方式(自動(dòng)分頁(yè)預(yù)覽)
這篇文章主要介紹了vue-pdf插件實(shí)現(xiàn)pdf文檔預(yù)覽方式(自動(dòng)分頁(yè)預(yù)覽),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03vue中modal傳輸數(shù)據(jù)并刷新部分頁(yè)面數(shù)據(jù)方式
這篇文章主要介紹了vue中modal傳輸數(shù)據(jù)并刷新部分頁(yè)面數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04vue2自定義組件通過rollup配置發(fā)布到npm的詳細(xì)步驟
這篇文章主要介紹了vue2自定義組件通過rollup配置發(fā)布到npm,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03vue?項(xiàng)目?jī)?yōu)雅的對(duì)url參數(shù)加密詳解
這篇文章主要為大家介紹了vue?項(xiàng)目?jī)?yōu)雅的對(duì)url參數(shù)加密詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10vue3.0引入百度地圖并標(biāo)記點(diǎn)的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue3.0引入百度地圖并標(biāo)記點(diǎn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08vue element-ui里的table中表頭與表格出現(xiàn)錯(cuò)位的解決
這篇文章主要介紹了vue element-ui里的table中表頭與表格出現(xiàn)錯(cuò)位的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08