人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

スクロールして下にいくのに合わせて背景画像の位置を変更するjavascriptのコードを教えて下さい。

外部CSSにてbodyに背景画像を指定しています。

body {
background-image: url(../img/base/●●.png);
background-repeat: no-repeat;
background-position-x:50%;
background-position-y:1%;
}

スクロールして一番下まで行った際に背景画像の「y軸」の高さを変更したいのです。
下に行ったタイミングでいきなり変わるのではなく、徐々に変わっていき、最終的に一番下までスクロールしたら希望の高さに変更できる形が理想です。

jquery等で可能でしょうか?

よろしくお願いいたします。


●質問者: kamefactory
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● a-kuma3
●200ポイント ベストアンサー

こんな感じでできます。

(function() {
 var is_support_only_y;
 var X_POS = "50%";

 function set_background_position() {
 var b_ = document.body;
 var y_pos_r = b_.scrollTop / (b_.scrollHeight - b_.clientHeight);
 var y = b_.scrollTop + b_.clientHeight / 2 - (b_.clientHeight / 2) * y_pos_r;
 if (is_support_only_y) {
 b_.style.backgroundPositionY = y + "px";
 } else {
 b_.style.backgroundPosition = X_POS + " " + y + "px";
 }
 }

 window.addEventListener("DOMContentLoaded", function() {
 is_support_only_y = document.body.style.backgroundPositionY;
 if (is_support_only_y) {
 b_.style.backgroundPositionX = X_POS;
 }
 window.addEventListener("scroll", set_background_position);
 set_background_position();
 });
})();

Firefox では、background-position-y を単独で指定できるのは、まだ先のようなので、その判定も入れています。

実際にどのように位置を調整したいかが質問の文面からは分からなかったので、初期状態では背景画像の頭がページの真ん中に来ていて、最後までスクロールすると表示領域の頭にくるように、スクロールした量に合わせて徐々に移動するようにしています。

こんな感じの動作です。
https://jsfiddle.net/03q2z5xv/embedded/result/




追記です。

実際にやりたい位置調整は、初期状態ではトップにある背景画像が、最後までスクロールすると、30pxほど下に下がるというものです。

一行、変更してます。

(function() {
 var is_support_only_y;
 var X_POS = "50%";

 function set_background_position() {
 var b_ = document.body;
 var y_pos_r = b_.scrollTop / (b_.scrollHeight - b_.clientHeight);
 var y = b_.scrollTop + 30 * y_pos_r;// ★ここを変えました
 if (is_support_only_y) {
 b_.style.backgroundPositionY = y + "px";
 } else {
 b_.style.backgroundPosition = X_POS + " " + y + "px";
 }
 }

 window.addEventListener("DOMContentLoaded", function() {
 is_support_only_y = document.body.style.backgroundPositionY;
 if (is_support_only_y) {
 b_.style.backgroundPositionX = X_POS;
 }
 window.addEventListener("scroll", set_background_position);
 set_background_position();
 });
})();

jsfiddle の方でも、変更したものを確認してみました。
https://jsfiddle.net/x5ahwgzp/embedded/result/


kamefactoryさんのコメント
ご回答ありがとうございます。 実際にやりたい位置調整は、初期状態ではトップにある背景画像が、最後までスクロールすると、30pxほど下に下がるというものです。 どこをどのように指定すればよいか具体的に教えていただくことはできますか? あと、実装方法も合わせてご教示頂ければ幸いです。 よろしくお願いいたします。

a-kuma3さんのコメント
>> 実際にやりたい位置調整は、初期状態ではトップにある背景画像が、最後までスクロールすると、30pxほど下に下がるというものです。 << 回答に追記しました。

kamefactoryさんのコメント
ありがとうございます!出来ました! ただ、クロームとFIREFOXではスムーズに動くのですが、IEだと少し動きがカクカクします。これの修正は難しいですか?

kamefactoryさんのコメント
追記 IEだと、スクロールボタンを長押しして自動スクロールにすることも出来なくなるようです。

a-kuma3さんのコメント
background-image に指定された画像の描画と、スクロール時の Listener の呼び出しの処理の後先の問題なので、回答に書いたやり方だと、少し変更して改善、というわけにはいかないと思います。 CSS で背景画像の指定、というのではなく、HTML の表記なども大幅に変更しても良いのであれば、できなくもなさそうですが(まだ、やってない)。

kamefactoryさんのコメント
ありがとうございました!助かりました。またよろしくお願いします!!

a-kuma3さんのコメント
あら、終了してた。 >> ただ、クロームとFIREFOXではスムーズに動くのですが、IEだと少し動きがカクカクします。これの修正は難しいですか? << 別のやり方を考えてみました。 >|html| <script> (function() { function set_background_position() { var b_ = document.body; var st = b_.scrollTop; var sh = b_.scrollHeight; var ch = b_.clientHeight; var y_pos_r = st / (sh - ch); var y = 30 * y_pos_r; var im = document.getElementById("background"); im.style.top = y + "px"; } window.addEventListener("DOMContentLoaded", function() { var cw = document.body.clientWidth; var im = document.getElementById("background"); im.style.left = ((cw - im.offsetWidth) / 2) + "px"; window.addEventListener("scroll", set_background_position); set_background_position(); }); })(); </script> <style> #background { position: fixed; z-index: 1; border: 1px solid red; } #contents { position: relative; z-index: 2; } </style> <body> <!-- 背景用の要素 --> <div id="background"><img src="背景画像の URL"></div> <!-- 本来のコンテンツ --> <div id="contents"> 本来、表示したかったもの </div> </body> ||< jsFiddle で試したのがこちら。 https://jsfiddle.net/nmu5wL51/embedded/result/ スクロールのイベントをつかまえて処理をする、というところは回答と同じですが、BODY の背景画像に指定するのではなく、IMG 要素に画像を指定して z-index の指定で背景のように見せています。 既にあるページに手を入れて質問されたことをやろうとすると、HTML の構造が変わったり、z-index の指定があったりしていますから、他の javascript のライブラリと組み合わせていたりすると、思わぬ副作用があるかもしれません。

kamefactoryさんのコメント
ありがとうございます! そうですね、HTML構造を変えたりはちょっと他のところに不具合が出そうで難しいです。 ちなみに、別の質問になっちゃうんですけど、IEだけ教えて頂いたJSを読み込まないように指定することはできますか? haed内に、 <!--[if !IE ]> <script type="text/javascript" src="xxxxx.js"></script> <![endif]--> と記載すると他のブラウザでも読み込まなくなっちゃうんですよ。 よろしくお願いいたします。

kamefactoryさんのコメント
>|| <!--[if !IE ]> <link href="css/ie.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="xxxxx.js"></script> <![endif]--> ||< すいません、先ほどのコードが見えなくなっていたので追記です。

kamefactoryさんのコメント
すいません、もう一つ教えて頂きたいことがあります。 教えて頂いたコードですと、スクロール後の背景の動きは「30px程下がる」でしたが、表示画面の「?%部分」まで下がるという形にしたい場合はどのようにすればいいでしょうか? よろしくお願いします。

a-kuma3さんのコメント
こちら、参考まで。 [https://ja.wikipedia.org/wiki/%E6%9D%A1%E4%BB%B6%E4%BB%98%E3%81%8D%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88:title] ただ、MS が勝手にやってることなので、それには頼らない方が良いと思います。 javascript で、window.navigator.userAgent で判定して、動的に link や script を埋め込む方が健全でしょう。 >> 教えて頂いたコードですと、スクロール後の背景の動きは「30px程下がる」でしたが、表示画面の「?%部分」まで下がるという形にしたい場合はどのようにすればいいでしょうか? << >|javascript| var y = b_.scrollTop + 30 * y_pos_r;// ★ここを変えました ||< ここの 30 を変えます。 50% 位置ならこんな感じ。 >|javascript| var y = b_.scrollTop + b_.clientHeight * 0.5 * y_pos_r;// ★ここを変えました ||<

kamefactoryさんのコメント
ありがとうございます! クロームだと問題なく動きましたが、IEやFIREFOXでは動きませんでした。 終了したのに、何度も申し訳ありません。 よろしくお願いいたします。

a-kuma3さんのコメント
>> クロームだと問題なく動きましたが、IEやFIREFOXでは動きませんでした。 << どちらの話でしょうか。 「条件付きコメント」の件でしょうか。 先のコメントでは、怪しいので条件付きコメントは使わない方が良いと思う、と書いたつもりなのですが。

kamefactoryさんのコメント
ご連絡が遅くなり申し訳ございません。 「クロームだと問題なく動きましたが、IEやFIREFOXでは動きませんでした。」 というのは、ご教示頂いた「パーセンテージ」で表示するコードです。 説明がわかりにくく大変申し訳ございません。 よろしくお願いします。

a-kuma3さんのコメント
>> 「クロームだと問題なく動きましたが、IEやFIREFOXでは動きませんでした。」 というのは、ご教示頂いた「パーセンテージ」で表示するコードです。 << 動きますよ。Firefox でも IE でも。 上部から 70% の位置に持ってくる場合の javascript の全コード。 >|javascript| (function() { var is_support_only_y; var X_POS = "50%"; function set_background_position() { var b_ = document.body; var st = b_.scrollTop; var sh = b_.scrollHeight; var ch = b_.clientHeight; var y_pos_r = st / (sh - ch); var y = st + ch * 0.7 * y_pos_r; // ★ 70% 位置 if (is_support_only_y) { b_.style.backgroundPositionY = y + "px"; } else { b_.style.backgroundPosition = X_POS + " " + y + "px"; } } window.addEventListener("DOMContentLoaded", function() { is_support_only_y = document.body.style.backgroundPositionY; if (is_support_only_y) { document.body.style.backgroundPositionX = X_POS; } window.addEventListener("scroll", set_background_position); set_background_position(); }); })(); ||< 変数を介在してるので、質問に追記したのとはちょっと違いますが、やってることは一緒です。

kamefactoryさんのコメント
>|| (function() { var is_support_only_y; var X_POS = "50%"; function set_background_position() { var b_ = document.body; var st = b_.scrollTop; var sh = b_.scrollHeight; var ch = b_.clientHeight; // フレームの中だと上手くいかない... st = -b_.getBoundingClientRect().top; sh = b_.scrollHeight; ch = window.innerHeight var y_pos_r = st / (sh - ch); var y = st + 30 * y_pos_r; console.log(y, st, sh, ch) if (is_support_only_y) { b_.style.backgroundPositionY = y + "px"; } else { b_.style.backgroundPosition = X_POS + " " + y + "px"; } } window.addEventListener("DOMContentLoaded", function() { is_support_only_y = document.body.style.backgroundPositionY; if (is_support_only_y) { b_.style.backgroundPositionX = X_POS; } window.addEventListener("scroll", set_background_position); set_background_position(); }); })(); ||< 何度もすいません。 教えて頂いた上記コードだと動きますが、 パーセンテージにする一行を変更すると動かなくなります。 よろしくお願いします。

a-kuma3さんのコメント
ああ、jsfiddle の方のソースでしたか。 70% 位置に持ってくるには、以下のようにしてください。 >|javascript| var b_ = document.body; var st = b_.scrollTop; var sh = b_.scrollHeight; var ch = b_.clientHeight; // フレームの中だと上手くいかない... st = -b_.getBoundingClientRect().top; sh = b_.scrollHeight; ch = window.innerHeight var y_pos_r = st / (sh - ch); // var y = st + 30 * y_pos_r; var y = st + ch * 0.7 * y_pos_r; // ★ここ ||< ソースのコメントでちょろっと書いただけですが、フレームの中で動作させるのでなければ、以下のような感じでいけます。 >|javascript| var b_ = document.body; var st = b_.scrollTop; var sh = b_.scrollHeight; var ch = b_.clientHeight; //フレームの中じゃなければ、以下の 3行は不要 // // フレームの中だと上手くいかない... // st = -b_.getBoundingClientRect().top; // sh = b_.scrollHeight; // ch = window.innerHeight var y_pos_r = st / (sh - ch); // var y = st + 30 * y_pos_r; var y = st + ch * 0.7 * y_pos_r; // ★ここ ||<

kamefactoryさんのコメント
ありがとうございます! 動きました! 何度もすいませんでした。 またよろしくお願いします。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ