Vue.jsでスクロールに連動したコンテンツナビゲーションを実装する
1枚もののウェブページで表示されているコンテンツに合わせてメニューのナビゲーションが変わるというような機能要件をVue.jsで実装してみたいと思います。このような機能は以前にもjQueryで実装したまとめ(「jQueryでスクロールと連動したコンテンツナビゲーションを実装する」)にて紹介していましたが、Vue.jsではもっとわかりやすく、また双方向バインディングでテンプレート側の切り分けも簡単にできるのでこちらの方がオススメですね。
それでは早速コードを見ていきます。まずはHTMLです、今回はサンプル用としてセクションをいくつか用意し、ヘッダー部分にセクションに対応した現在のコンテンツ名を出力する部分を設けました。その部分はVue.js側で返ってきた値をそのまま表示させるためマスタッシュ記法で記述しておきます。
【HTML(Pug)】※一部抜粋
同じ機能でもjQueryではコードが複雑になりがちですが、Vue.jsを使うことでかなり見通しが良くなりました。カスタマイズするときも楽ですね。またHTMLのテンプレート側にも処理に合わせて動的に値を出力したりすることもできますので、より高度な見せ方も可能になりますね。1枚もののページを作成する場合にはぜひ試してみてはいかがでしょうか。
div#app header span. {{ currentNavi }} main section(id="section_01") span コンテンツ1のエリアです section(id="section_02") span コンテンツ2のエリアです section(id="section_03") span コンテンツ3のエリアです section(id="section_04") span コンテンツ4のエリアです section(id="section_05") span コンテンツ5のエリアです続いて処理の部分です。今回はVue.jsで新たにインスタンスを作成する方法でまとめていますが、単一コンポーネントを使う場合でも同じになります。まずはdataオプションに格納する値を変数として持たせておきます。ここでは縦方向のスクロール量と対象となるセクションのページトップからのY座標を配列で持たせるようにします。 computedのオプションでは、現在のスクロール量からどのコンテンツの位置にいるかを調べて、条件分岐させて対象となるコンテンツ名を返すようにしています。今回はこの値をそのままテンプレートに出力しています。 【JavaScript(Vue)】
var vueModel = new Vue({ el: '#app', data() { return { scrollY: 0, sectionOffsetTop: [] } }, computed: { currentNavi() { if(this.scrollY >= this.sectionOffsetTop[0] && this.scrollY < this.sectionOffsetTop[1]) { return 'コンテンツ1' } else if(this.scrollY >= this.sectionOffsetTop[1] && this.scrollY < this.sectionOffsetTop[2]) { return 'コンテンツ2' } else if(this.scrollY >= this.sectionOffsetTop[2] && this.scrollY < this.sectionOffsetTop[3]) { return 'コンテンツ3' } else if(this.scrollY >= this.sectionOffsetTop[3] && this.scrollY < this.sectionOffsetTop[4]) { return 'コンテンツ4' } else if(this.scrollY >= this.sectionOffsetTop[4]) { return 'コンテンツ5' } else { return 'スクロールすると現在のコンテンツ名が表示されます' } } }, mounted() { window.addEventListener('scroll', () => { this.pushScrollY(); }); window.addEventListener('resize', () => { this.pushScrollY(); }); this.pushElementOffsetTop(); }, methods: { pushScrollY() { this.scrollY = window.scrollY; }, pushElementOffsetTop() { const targets = [ 'section_01', 'section_02', 'section_03', 'section_04', 'section_05' ]; targets.forEach(target => { const element = document.getElementById(target); const offsetTop = Math.round(window.scrollY + element.getBoundingClientRect().top); this.sectionOffsetTop.push(offsetTop); }); } } });続いてmethodsオプションでは今回の機能に必要となる処理を定義しています。ここで必要になるのは「現在のスクロール量を取得」する処理と「各セクションのページトップからのY座標を取得」する処理の2つになります。Y座標を取得する処理は「getBoundingClientRect().top」で取得できますが、スクロール分を考慮しないといけないのと、小数点が発生した場合の対応も忘れず行なっておきます。最後に、DOMを操作することになるのでmountedオプションで定義した処理を実行するようにしておきます。createdオプションで実行した場合にはDOMが取得できないのでundefinedが返ってきてしまいます。 これでスクロールに合わせたコンテンツナビゲーションが作成できました。今回のサンプルはこちらにあげておりますので、ぜひご参考ください。
See the Pen contents_navi_on_vue by designsupply (@designsupply) on CodePen.
同じ機能でもjQueryではコードが複雑になりがちですが、Vue.jsを使うことでかなり見通しが良くなりました。カスタマイズするときも楽ですね。またHTMLのテンプレート側にも処理に合わせて動的に値を出力したりすることもできますので、より高度な見せ方も可能になりますね。1枚もののページを作成する場合にはぜひ試してみてはいかがでしょうか。
sponserd
keyword search
recent posts
- ViteでMarkuplintとPrettierを使える環境を構築する
ViteでMarkuplintとPrettierを使える環境を構築する
- ViteでStylelintとESlintを使える環境を構築する
ViteでStylelintとESlintを使える環境を構築する
- マウスオーバーしたセルを含む行列がハイライトするテーブルを作成する:has()擬似クラスの活用例
マウスオーバーしたセルを含む行列がハイライトするテーブルを作成する:has()擬似クラスの活用例
- ViteでVue.jsとVuex(Pinia)とVue Routerを使ってみる
ViteでVue.jsとVuex(Pinia)とVue Routerを使ってみる
- ViteでHandlebarsを使った複数ページの作成に使える外部JSONファイルのデータを読み込む
ViteでHandlebarsを使った複数ページの作成に使える外部JSONファイルのデータを読み込む
- ViteでTailwindCSSとテンプレートエンジンのHandlebarsを使ったページコーディング
ViteでTailwindCSSとテンプレートエンジンのHandlebarsを使ったページコーディング
- ViteでPostCSS周りの設定やSassを使う
ViteでPostCSS周りの設定やSassを使う
- フロントエンドの開発環境にVite + TypeScriptを導入する
フロントエンドの開発環境にVite + TypeScriptを導入する
categories