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

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

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

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

2回答

5587閲覧

Intersection Observer APIのrootMarginが効かない

mTono

総合スコア31

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

1グッド

2クリップ

投稿2019/03/02 08:56

編集2019/03/02 17:33

前提・実現したいこと

JavascriptのIntersection Observer APIでの画像の遅延読み込みについて調べています。
対象の画像がビューポートの100px手前に来たときに画像の取得を開始したいと思っています。
具体的には以下の様にrootMarginの上下を100pxに設定しています。

rootMarginの設定

1const options = { 2 // 上下100pxで発火 3 rootMaring: "100px 0" 4};

※以下の記事を参考に実装を行っています。
参考記事
https://qiita.com/ryo_hisano/items/42f5980720bc832e6e09

参考デモ
https://andus.heteml.jp/intersection_observer/1.html

今回の質問内容

実際に参考デモで動作確認を行ったところ、画像がViewportの100px手前に来たときではなく、Viewportと画像が交差したとき(画像が画面内に入ってきたとき)に発火しているように見受けられます。

他の記事も色々みて調べてみましたが、やはりrootMarginでの制御で良さそうなのですが、
どこか使い方が間違っているのでしょうか?それとも私の確認方法が間違っているのでしょうか?

何かご存知の方いらっしゃいましたら、何卒よろしくお願い致します。

確認方法

イメージ説明
この画像はゆっくりスクロールした際に100px手前に差し掛かったときにブレークポイントで処理が止まるかを確認しています。(ブレークポイントは交差判定がtrueの時に止まるように置かれています。)表示されている画面のすぐ下には次の画像があるため、ブレイクポイントで止まる想定なのですが、実際には次の画像とViewportが交わるまで交差していない判定になっており、コンソール上のブレイクポイントで止まりません。

(実際、もう少しスクロールを行い、次の画像の上辺がViewportに差し掛かった当りでコンソール上のブレイクポイントで処理が停止します。

また、ChromeのDevToolのNetworkパネルでも確認を行いましたが、画像の100px手前ではなく、画像がViewportと交差したときに画像の取得が行われていることを確認しました。

試したこと

rootMarginを500pxにしてみましたが、変わりませんでした。
また、交差の判定条件をintersectionRatioにもしてみましたが、変わりませんでした。

if (entry.intersectionRatio > 0)

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

polyfillは使っていません。
Chromeで確認を行いました。

該当のソースコード

js

1(function() { 2 "use strict"; 3 4 // ターゲット指定 5 const targets = Array.from(document.querySelectorAll("img[data-src]")); 6 7 // 実際の画像パス 8 const img_path = "data-src"; 9 10 // オプション 11 const options = { 12 // 上下100px手前で発火 13 rootMaring: "100px 0" 14 }; 15 16 // 初期化 17 const observer = new IntersectionObserver(callback, options); 18 19 targets.forEach(function(img) { 20 // 監視の開始 21 observer.observe(img); 22 }); 23 24 // コールバック 25 function callback(entries, object) { 26 entries.forEach(function(entry) { 27 28 // 交差していない 29 if (!entry.isIntersecting) return; 30 31 // ターゲット要素 32 const img = entry.target; 33 34 // 遅延ロード実行 35 loading(img); 36 37 // 監視の解除 38 object.unobserve(img); 39 }); 40 }; 41 42 // 遅延ロード 43 function loading(img) { 44 // data-srcの値を取得 45 const src_val = img.getAttribute(img_path); 46 if (src_val) { 47 // 画像パスを設定 48 img.src = src_val; 49 img.onload = function() { 50 // data-src属性を削除 51 this.removeAttribute(img_path); 52 }; 53 } 54 }; 55})();

html

1 <ul> 2 <li><img src="data:image/gif;base64,R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7" data-src="./img/alexander-possingham-209285.jpg" alt="" width="500" height="333"></li> 3 ... 4 </ul> 5
kei344👍を押しています

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

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

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

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

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

guest

回答2

0

自己解決

本件の事象の原因
原因1:スペルミス
修正前:rootMaring
修正後:rootMargin

原因2:pxか%をつける
修正前: rootMargin: "100px 0"
修正後: rootMargin: "100px 0px"

pxまたは%を付けていない場合、以下のメッセージがブラウザコンソールに出力される。
Uncaught DOMException: Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent.
(本事象の場合、rootMarginのスペル自体が間違っていたため、初期段階ではコンソールにエラーが表示されていなかった。)

ご調査にご協力くださった方々、誠にありがとうございました。

投稿2019/03/02 17:47

編集2019/03/02 18:10
mTono

総合スコア31

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

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

oikashinoa

2019/03/03 09:23

確認お疲れ様でした。 ローカルでならきちんと動いた件、確認ありがとうございました。協力したかいがあります。
mTono

2019/03/03 11:20

大変お世話になりました! 参照元の記事の方にも記事を訂正頂けたので、 これで同じ過ちを繰り返す人は少なからず減るかと! では。
guest

0

中途半端な回答です。

まずはスペルミス。

rootMaring:

rootMargin:

ただし、Intersection Observer API - Web API | MDNの’監視される要素をターゲットにする’のcodepenで試してもなんか期待通りにならない。

rootMargin:

  • -100px ちゃんとマージン減る(だいぶ画面に入ってから反応する(MDNのサンプルだと四角四隅の数値が変わる))
  • 100px 画面に入ってからしか反応しない。

投稿2019/03/02 13:25

編集2019/03/02 13:27
oikashinoa

総合スコア2826

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

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

mTono

2019/03/02 13:46

ご回答ありがとうございます! スペルミス失礼いたしました。 >> ただし、Intersection Observer API - Web API | MDNの’監視される要素をターゲットにする’のcodepenで試してもなんか期待通りにならない。 やっぱりそうですよね。 IntersectionObserverについて紹介している記事はrootMarginを設定すればviewportに入る前でも発火できるよ謳っているのですが、 実際に動作を検証してみるとrootMarginを正にした際はviewportとの交差で発火するので、何か知らない仕様があるのかと思い質問させていただきました。 私の方でももう少し調べてみます。 ご回答、誠にありがとうございました。
oikashinoa

2019/03/02 14:58

MDNのサンプルですら期待通りの動作にならないのが解せないです。 - 環境を疑ったんですが、firefox/Ubuntuも同じ。 - Codepen、jsfiddleも結果同じ… Ubuntu環境だからってことはないと思いたいけど…(vivaldi,chronium,firefoxで軽くテスト) 何か分かりましたら情報共有お願いします。
oikashinoa

2019/03/02 15:13

[Positive rootMargin doesn't seem to work · Issue #260 · w3c/IntersectionObserver](https://github.com/w3c/IntersectionObserver/issues/260) 斜め読みするとCodepen(jsfiddleかも)はiFrame使っているからとか、Bodyからoverflow: hiddenを取れ とか。 お試し&ソースを見て頂けると助かります。明日は出張なので見るのは遅いかなぁ。 It turned out to be CSS that was the problem in our app. Our body hadoverflow: hidden. Inside, we had an element (B) which was statically positioned at the top of the screen and another element (C) which had overflow: auto (so this was the element being scrolled). It's within this element C that the observed element (D) exists. I've removed overflow: hidden from the body, gave B fixed positioning, and removed overflow: auto from C. This fixed it.
mTono

2019/03/02 17:43

遅くまでご調査いただきありがとうございます! 本件の事象の原因がわかりました。 原因1:まずはご指摘いただいた通り、スペルミスが原因でした。 修正前:rootMaring 修正後:rootMargin 修正後に改めてdevtoolのコンソールを確認すると、以下のメッセージが表示されていました。 Uncaught DOMException: Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent. rootMarginはpxか%をつけろと言っているようなので、そのとおりに修正すると希望の動作となりました。 原因2:pxか%がついていない。 修正前: rootMargin: "100px 0" 修正後: rootMargin: "100px 0px" cssのmarginと同じ感覚でpxを省略すると動かないんですね。 大変ご面倒をおかけしました。 また、先程のMDNのデモですが、確かにCodepen上では期待の通りに動いていませんが、 ローカルにコピーして動かしたところrootMarginが正の場合でも期待どおりの動きとなっていました。 (少し言及されている通り、iframeが関係していそうです。) ひとまず、この件はこれでクローズさせていただきます。 ご協力、誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問