2023.2.7更新
このアプローチには多くの欠陥があります。他にもより良い解決策があり、新しい記事で更新されています。興味のある友達は新しい記事にアクセスして読んでください↓
これは Vue で作成されたアンダースコアに続くエフェクトであり、他のプラグインは使用されていません
目次
最終的な効果はこれ↓
初めはネットで他の人の実践を調べましたが、ほとんどが下枠や擬似要素+枠という手法で実現していました。
単純にボーダーを使うとオプション内容の長さに応じてボーダーの長さが変わってしまうのであまり良くないので擬似要素にボーダーを書くことで解決できますがデメリットはあると思いますそうすると枠線が設定できない 角が丸いので見た目の美しさはちょっと…
話は戻りますが、こんな感じで気づきました↓
1. 初期ナビゲーションバーを作成する
<body>
<div id="app">
<div class="nav">
<!-- 标题列表 -->
<div class="nav-list">
<div v-for="(item, index) in navList" :key="index">{
{ item }}</div>
</div>
<!-- 下划线 -->
<div class="nav-line"></div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el: "#app",
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
},
});
</script>
<style>
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.nav {
position: relative;
}
.nav-list {
width: 100%;
height: 50px;
display: flex;
justify-content: space-around;
align-items: center;
}
.nav-line {
width: 18px;
height: 4px;
border-radius: 2px;
background-color: red;
position: absolute;
bottom: 0;
}
</style>
上に示した効果はこれです
2.クリックスタイルを追加する
まず、ナビゲーションの各オプションにクリック イベントを追加し、クリックされた項目の色がクリック時に変更されるようにする必要があります。
- HTML部分にイベントと動的クラスを追加
<div class="nav-list">
<div v-for="(item, index) in navList" :key="index" @click="click(index)" :class="{ active : index==current }">{
{ item }}</div>
</div>
- Vue インスタンスに変数とメソッドを追加する
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
current: 0,
},
methods: {
// 点击时执行
click(index) {
this.current = index;
this.lineMove();
},
// 计算下划线应该移动的距离
lineMove() {
},
},
- CSS部分にスタイルを追加する
.active {
color: red;
font-weight: bold;
}
すると、次のようなものが得られます
最初の 2 つの手順を完了すると、フォントの色が変わり、次の手順では、それに合わせて下線も移動します。
3.動きに下線を引く
- HTML 部分の下線に動的スタイルを追加する
以前に下線に絶対位置が追加されているため、ここでは変位にleftプロパティを使用できます。
<div class="nav-line" :style="{left:X+'px',transform : 'translateX(-50%)'}"></div>
もちろん、left を使用せず、属性のtransformを変更するtranslateX()のみを使用することでも同じ効果を得ることができます↓
<!-- 只使用transform的写法 -->
<div class="nav-line" :style="{transform : `translateX(${X}px) translateX(-50%)`}"></div>
translationX() は引用符 ' ' またはテンプレート文字列 `` で囲む必要があることに注意してください。そうしないと、エラーが報告されます。translateX( -50%) は、整列を確保するために下線を 50% 左に移動します。誰もが理解する必要があります。これ
- Vue インスタンスに変数 X とメソッド lineMove を追加します
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
X: 0,
current: 0,
},
methods: {
// 点击时执行
click(index) {
this.current = index;
this.lineMove();
},
// 计算下划线应该移动的距离
lineMove() {
// 导航栏的宽度,因为是100%所以就是屏幕宽度
let width = document.body.clientWidth;
// 每个选项栏的宽度 = 导航栏宽度/选项个数
let divWidth = width / this.navList.length;
// 半个选项栏宽度
let halfDivWidth = divWidth / 2;
// 下划线移动的距离 = 半个选项栏宽度 + (单个选项栏宽度*当前index)
this.X = halfDivWidth + divWidth * this.current;
},
},
ここで、 width = .nav-list の幅とします。前に CSS で .nav-list の幅を 100% として定義したため、例では現在の画面の幅を取得しました。
- CSSは下線にトランジション効果を追加します
.nav-line {
width: 18px;
height: 4px;
border-radius: 2px;
background-color: red;
position: absolute;
bottom: 0;
transition: 0.3s all;
}
効果を得る
これを実行すると、効果が実現されたことがわかりますが、小さな問題がまだあります。ページの初期化時に下線の位置が間違っており、下線が画面の一番左にあり、半分が画面からはみ出しています。理由も明白で、変数 X に設定した初期値は 0 です。
問題を解決します。作成されたライフサイクルで lineMove メソッドを 1 回実行します。
created() {
// 避免页面初始化会有显示问题,初始加载时就执行一次该方法
this.lineMove();
},
注:マウントされたサイクルではなく、作成されたサイクルで実行することをお勧めします。マウントされたサイクルはページの初期読み込みが完了した後に実行されるため、マウントされたサイクルで実行すると、下線がページの左側に一時的に残ることがわかります。冒頭の画面。
最終効果を得る ↓
最終コード
<body>
<div id="app">
<div class="nav">
<!-- 标题列表 -->
<div class="nav-list">
<div v-for="(item, index) in navList" :key="index" @click="click(index)" :class="{ active : index==current }">{
{ item }}</div>
</div>
<!-- 下划线 -->
<div class="nav-line" :style="{left:X+'px',transform : 'translateX(-50%)'}"></div>
<!-- <div class="nav-line" :style="{transform : `translateX(${X}px) translateX(-50%)`}"></div> -->
</div>
</div>
</body>
<script>
var vm = new Vue({
el: "#app",
data: {
navList: ["首页", "头条", "特惠", "财经", "动漫"],
X: 0,
current: 0,
},
methods: {
// 点击时执行
click(index) {
this.current = index;
this.lineMove();
},
// 计算下划线应该移动的距离
lineMove() {
// 导航栏的宽度,因为是100%所以就是屏幕宽度
let width = document.body.clientWidth;
// 每个选项栏的宽度 = 导航栏宽度/选项个数
let divWidth = width / this.navList.length;
// 半个选项栏宽度
let halfDivWidth = divWidth / 2;
// 下划线移动的距离 = 半个选项栏宽度 + (单个选项栏宽度*当前index)
this.X = halfDivWidth + divWidth * this.current;
},
},
created() {
// 避免页面初始化会有显示问题,初始加载时就执行一次该方法
this.lineMove();
},
});
</script>
<style>
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.nav {
position: relative;
}
.nav-list {
width: 100%;
height: 50px;
display: flex;
justify-content: space-around;
align-items: center;
}
.active {
color: red;
font-weight: bold;
}
.nav-line {
width: 18px;
height: 4px;
border-radius: 2px;
background-color: red;
position: absolute;
bottom: 0;
transition: 0.3s all;
}
</style>
予防
- ナビゲーション bar.nav -list のフレックス スタイルでは justify-content: space-around を使用する必要があります 。そうしないと、その後の下線の移動距離の計算が不正確になります。
- 下線のスタイルを定義したり、background-image属性を使用してグラデーションの下線を作成したりできます。
- ナビゲーションバーの選択肢の数(長さ)が違うと、下線の動きも不正確になりますので、選択肢の数(長さ)を統一するか、各マスターが自分で解決するのが最善です
- メッセージを残すことを歓迎します。気に入らない場合はスプレーしないでください