質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

2859閲覧

動的に追加したアンカーリンクがスムーズスクロールしない

erp

総合スコア46

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

3クリップ

投稿2021/10/29 13:17

編集2022/01/04 06:30

前提・実現したいこと

Vanillaでスムーズスクロールを書いており、動的に追加したアンカーリンクにもクリックイベントを起こしたいです。

発生している問題・エラーメッセージ

・問題一つ目
ヘッダー内のアンカーリンクがスムーズスクロールしない

・二つ目
a[href^="#"] にだけイベントを起こしたい

エラーはなし

該当のソースコード

js

1/* smooth scroll --------------------------------------------- */ 2 let Ease = { 3 easeInOut: function (t) { 4 return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; 5 } 6 } 7 let duration = 1200; 8 document.addEventListener('click', function (e) { 9 trigger = e.target; 10 if (trigger.tagName.toLowerCase() === 'a') { // and条件で a[href^="#"]を入れたい 11 let href = trigger.getAttribute('href'); 12 let currentPosition = document.documentElement.scrollTop || document.body.scrollTop; 13 let targetElement = document.getElementById(href.replace('#', '')); 14 if (targetElement) { 15 e.preventDefault(); 16 e.stopPropagation(); 17 let targetPosition = window.pageYOffset + targetElement.getBoundingClientRect().top - 115; 18 let startTime = performance.now(); 19 let loop = function (nowTime) { 20 let time = nowTime - startTime; 21 let normalizedTime = time / duration; 22 if (normalizedTime < 1) { 23 window.scrollTo(0, currentPosition + ((targetPosition - currentPosition) * Ease.easeInOut(normalizedTime))); 24 requestAnimationFrame(loop); 25 } else { 26 window.scrollTo(0, targetPosition); 27 } 28 } 29 requestAnimationFrame(loop); 30 } 31 } 32 }); 33 /* smooth scroll ----------------------------------------- end */

html

1<header> 2 <a href="#link">dummy</a> <!-- これがスムーズスクロールしない --> 3</header> 4 5<section id="link"> 6あのイーハトーヴォのすきとおった風、夏でも底に冷たさをもつ青いそら、うつくしい森で飾られたモリーオ市、郊外のぎらぎらひかる草の波。 7</section>

ヘッダー内以外のリンクはスムーズスクロールしました。ヘッダー内のアンカーリンクだけスムーズスクロールしません。

試したこと

なぜ、ヘッダーにだけクリックイベントが起きないのか、調べてみましたがめぼしい情報を得られませんでした。
また、and 条件で [href^="#"] を含めるのもどうすればいいのか全く分からず、お手上げです。

ご助力いただけますと大変助かります。

追記

22.01.04 追記

js

1/* smooth scroll --------------------------------------------- */ 2 let Ease = { 3 easeInOut: function (t) { 4 return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; 5 } 6 }, 7 duration = 1200; 8 function smooth(e) { 9 href = this.getAttribute('href'); 10 targetElement = document.getElementById(href.replace('#', '')); 11 if (targetElement) { 12 e.preventDefault(); 13 e.stopPropagation(); 14 let currentPosition = document.documentElement.scrollTop || document.body.scrollTop; 15 let targetPosition = window.pageYOffset + targetElement.getBoundingClientRect().top - 115; 16 let startTime = performance.now(); 17 let loop = function (nowTime) { 18 let time = nowTime - startTime; 19 let normalizedTime = time / duration; 20 if (normalizedTime < 1) { 21 window.scrollTo(0, currentPosition + ((targetPosition - currentPosition) * Ease.easeInOut(normalizedTime))); 22 requestAnimationFrame(loop); 23 } else { 24 window.scrollTo(0, targetPosition); 25 } 26 } 27 requestAnimationFrame(loop); 28 } 29 }; 30 let anchorLinks = [].slice.call(document.querySelectorAll('a[href^="#"]')); 31 anchorLinks.forEach(function (anchorLink) { 32 anchorLink.addEventListener("click", smooth, false); 33 }); 34 /* smooth scroll ----------------------------------------- end */

こちらのコードのに変更したところ、動的に追加した(Fetch Api で追加した要素)はスムーズスクロールしませんでした。他はしています。

補足情報(FW/ツールのバージョンなど)

Firefox 最新版

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

同様な質問が、過去に存在してます。

DOMの読み込みが終わって、addEventListenerでイベントハンドラが紐づいた後、
要素をDOMに追加するとそれはaddEventListenerを行った後の新要素なので、
イベントハンドラは追加されていませんし、DOM要素を再走査してイベントハンドラに紐づけるような動きは通常は実施されませんので、自分で追加した要素にもaddEventListnerを自前で設定しなければなりません。

それを対応したコードが参考リンクにありますので、ご覧になってください。

参考リンク:動的に追加した要素にaddEventListnerを設定する方法

既に、解決済みの場合は聞き流してください。

投稿2021/11/26 01:29

nekora

総合スコア501

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nekora

2021/11/26 01:30

回答が役になったなら回答の横の数字をポイントすると回答の評価の増減ができます。 また解決につながった回答はベストアンサーに指定できます。 この設定は個別に指定できますし、同時に指定することもできます。
erp

2022/01/04 06:36

大変遅くなり申し訳ございません。高評価を押させていただきました。 リンク先を参考に、追記してみました。非同期の fetch api で読み込んだ要素には、スムーズスクロールのクリックイベントを起こすことはできないのでしょうか。少し難しく、どうすればよいのか困っております。もし可能でしたら、ご助力いただけますと大変助かります。
guest

0

自己解決

js

1/* smooth scroll --------------------------------------------- */ 2 let Ease = { 3 easeInOut: function (t) { 4 return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; 5 } 6 }, 7 duration = 1200; 8 document.addEventListener('click', function (e) { 9 let trigger = e.target; 10 if (trigger.tagName.toLowerCase() === 'a' && trigger.getAttribute('href').match(/^#([a-zA-Z0-9!-/:-@¥[-`{-~]*$)/)) { 11 let href = trigger.getAttribute('href'); 12 let targetElement = document.getElementById(href.replace('#', '')); 13 if (targetElement) { 14 e.preventDefault(); 15 e.stopPropagation(); 16 let currentPosition = document.documentElement.scrollTop || document.body.scrollTop; 17 let targetPosition = window.pageYOffset + targetElement.getBoundingClientRect().top - 115; 18 let startTime = performance.now(); 19 let loop = function (nowTime) { 20 let time = nowTime - startTime; 21 let normalizedTime = time / duration; 22 if (normalizedTime < 1) { 23 window.scrollTo(0, currentPosition + ((targetPosition - currentPosition) * Ease.easeInOut(normalizedTime))); 24 requestAnimationFrame(loop); 25 } else { 26 window.scrollTo(0, targetPosition); 27 } 28 } 29 requestAnimationFrame(loop); 30 } 31 } 32 }); 33 /* smooth scroll ----------------------------------------- end */ 34

正規表現でページ内リンクを指定して、できました。

22.01.06 追記
これだとなぜか<header>にアンカーリンクがある場合、発火しないので、以下に書き換えました。

js

1/* smooth scroll --------------------------------------------- */ 2 let Ease = { 3 easeInOut: function (t) { 4 return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; 5 } 6 }, 7 duration = 1200; 8 let smoothScrollTriggers = [].slice.call(document.querySelectorAll('a[href^="#"]')); 9 smoothScrollTriggers.forEach(function (smoothScrollTrigger) { 10 smoothScrollTrigger.addEventListener('click', function (e) { 11 href = smoothScrollTrigger.getAttribute('href'); 12 e.preventDefault(); 13 e.stopPropagation(); 14 smooth(); 15 }); 16 }); 17 document.addEventListener('click', function (e) { 18 let trigger = e.target; 19 if (trigger.tagName.toLowerCase() === 'a' && trigger.getAttribute('href').match(/^#([a-zA-Z0-9!-/:-@¥[-`{-~]*$)/)) { 20 href = trigger.getAttribute('href'); 21 e.preventDefault(); 22 e.stopPropagation(); 23 smooth(); 24 } 25 }); 26 27 function smooth() { 28 let targetElement = document.getElementById(href.replace('#', '')); 29 if (targetElement) { 30 let currentPosition = document.documentElement.scrollTop || document.body.scrollTop, 31 targetPosition = window.pageYOffset + targetElement.getBoundingClientRect().top - 115; 32 let startTime = performance.now(); 33 let loop = function (nowTime) { 34 let time = nowTime - startTime, 35 normalizedTime = time / duration; 36 if (normalizedTime < 1) { 37 window.scrollTo(0, currentPosition + ((targetPosition - currentPosition) * Ease.easeInOut(normalizedTime))); 38 requestAnimationFrame(loop); 39 } else { 40 window.scrollTo(0, targetPosition); 41 } 42 } 43 requestAnimationFrame(loop); 44 } 45 } 46 /* smooth scroll ----------------------------------------- end */

投稿2022/01/05 02:50

編集2022/01/06 02:14
erp

総合スコア46

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問