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

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

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

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

Q&A

解決済

1回答

760閲覧

【JavaScript】DOM取得について

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

1クリップ

投稿2020/09/25 08:57

編集2020/09/25 10:04

animate-titleクラスの要素(3つあります)がそれぞれ画面内に入ったときに、アニメーションを開始するよう実装しようと、以下のコードを書いたのですが、なぜか一番初めのanimate-titleクラスの要素が分割されて表示されました。
animate-titleの最初の要素が分割されて表示

よく見てみると<span>の文字まで分割されているので、何度も同じ要素が取得されて、それに対してさらにHTML要素が分割されています。
どうしてこうなるのかがずっと分かりません。

是非教えていただけると嬉しいです。

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous"> 9 <link href="https://fonts.googleapis.com/css2?family=Teko:wght@500&display=swap" rel="stylesheet"> 10 <link rel="stylesheet" href="style.css"> 11 <title>Document</title> 12</head> 13 14<body> 15 <section> 16 <div class="animate-title">Start where you are.</div> 17 </section> 18 <section> 19 <div class="animate-title">Use what you have.</div> 20 </section> 21 <section> 22 <div class="animate-title">Do what you can.</div> 23 </section> 24 <script src="text-animation.js"></script> 25 <script src="main.js"></script> 26</body> 27 28</html>

JavaScript

1class TextAnimation { 2 constructor(el) { 3 this.DOM = {}; 4 this.DOM.el = document.querySelector(el); //animate-titleのDOMが格納される 5 this.chars = this.DOM.el.innerHTML.trim().split(""); 6 this.DOM.el.innerHTML = this._splitText(); 7 } 8 _splitText() { 9 return this.chars.reduce((acc, curr) => { 10 curr = curr.replace(/\s+/, '&nbsp;'); 11 return `${acc}<span class="char">${curr}</span>`; 12 }, ""); 13 } 14 animate() { 15 this.DOM.el.classList.add('inview'); 16 } 17} 18 19document.addEventListener("DOMContentLoaded", function () { 20 21 const cb = function (entries, observer) { 22 entries.forEach((entry) => { 23 if (entry.isIntersecting) { //elが画面内に入ってきたとき 24 const ta = new TextAnimation(".animate-title"); 25 ta.animate(); 26 observer.unobserve(entry.target); 27 } else { 28 29 } 30 }); 31 // alert('intersecting'); 32 }; 33 const options = { 34 root: null, 35 rootMargin: "-300px 0px", 36 threshold: [0, 0.5, 1], 37 }; 38 39 const io = new IntersectionObserver(cb, options); 40 const els = document.querySelectorAll(".animte-title"); 41 els.forEach(el => io.observe(el)); 42 //elsが複数あるのでforEachですべての要素についてintersectionobserverを設置 43});

2020.09.25追記
アニメーションの見本はこのような感じです。
https://gyazo.com/379b7940d55ff1e239767706a690744b
(gifを貼り付けられなかったので、いったんこちらにリンクを貼ります。解決し次第編集してプレビューが見れるように善処します)

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

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

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

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

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

yambejp

2020/09/25 09:02

DOM処理するのになんでinnerHTMLをsplitする必要があるのですか?
退会済みユーザー

退会済みユーザー

2020/09/25 09:17

初心者で、仰っている意味がよく分かりません。 どういうことでしょうか?
yambejp

2020/09/25 09:25

むしろ、何をしたいのかをもっと明確にした方がよいでしょう animate-titleクラスの要素の何がどうアニメーションする 想定なのでしょうか?
退会済みユーザー

退会済みユーザー

2020/09/25 10:05

いったんgifの見本を貼らせていただきました。 gyazoのmp4ではこちらにうまく貼れないので、違うツールで試してみます。
yambejp

2020/09/25 10:17

「画面内に入ったとき」というトリガーでなければ アニメーションは実装できているということですか?
退会済みユーザー

退会済みユーザー

2020/09/25 10:39

はい。 ボタンを押すトリガーでは実装できましたが、仰る通り「画面内に入ったとき」というトリガーでInterSectionObserverを導入したら途端にうまくいかなくなりました。
yambejp

2020/09/25 10:56

そういうことなら画面のtopとbottomのY座標を拾って オブジェクトのgetBoundingClientRect()のtop,bottomの値で 調整してみてはどうでしょう?
退会済みユーザー

退会済みユーザー

2020/09/25 11:04

ありがとうございます。 試してみます。
guest

回答1

0

ベストアンサー

【JavaScript】DOM取得について

返り値がどのようになるのかを再確認してください。

  • document.querySelector()
  • document.querySelectorAll()

なぜか一番初めのanimate-titleクラスの要素が分割されて表示されました

  • TextAnimation#_splitText()がそのように処理しているからです。

よく見てみると<span>の文字まで分割されているので、何度も同じ要素が取得されて、それに対してさらにHTML要素が分割されています。どうしてこうなるのか

  • コンストラクタの this.DOM.el = document.querySelector(el); の返り値は最初に見つかった要素であり、前述のTextAnimation#_splitText()を繰り返しているからです。

(3つの div.animate-title が)それぞれ画面内に入ったときに、アニメーションを開始するよう実装

  • 現在のTextAnimation の実装では不可能です。改修してください。

追記)

TextAnimation オブジェクトはアニメーションさせたい1つの要素に紐付ける形をとると判りやすいのではないでしょうか。

javascript

1class TextAnimation { 2 constructor(el) { 3 if( !el instanceof HTMLElement ) { 4 throw TypeError("required HTMLElement in a argument"); 5 } 6 this.textsplit = false; // 分割済みかどうか 7 this.el = el; 8 el.innerHTML = this._splitText( el.textContent ); 9 } 10 11 _splitText( txt ) { 12 // 返却値 : undefined から innerHTML に訂正 13 if( !txt || this.textsplit ) return this.el.innerHTML; 14 this.textsplit = true; 15 return txt.trim().split("").reduce((acc, curr) => { 16 curr = curr.replace(/\s+/, '&nbsp;'); 17 return `${acc}<span class="char">${curr}</span>`; 18 }, ""); 19 } 20 21 animate() { 22 // 分割されている場合にアニメーション用スタイル '.inview' を適用する 23 if( this.textsplit ) 24 this.el.classList.add('inview'); 25 } 26} 27 28document.querySelectorAll(".animate-title").forEach( el => { 29 let anim = new TextAnimation(el); 30 console.log( anim.el === el ); 31 /* omitted */ 32});

投稿2020/09/27 02:50

編集2020/09/27 06:28
AkitoshiManabe

総合スコア5434

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

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

退会済みユーザー

退会済みユーザー

2020/09/27 12:48 編集

TextAnimationクラスのインスタンスを作成する際に、引数としてentry.targetを渡してあげることで解決しました。 その際にconstructorのthis.DOMに直接その値を入れてあげることになります。 ご回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問