スクロールで要素が画面内にある際に背景を表示するjQueryのスクリプトを作成した
読み物系のサイトを作ってたとき、記事題通りにスクロールで要素が画面内にある際に、背景を表示させるといったjQueryのスクリプトを組むことになった。
用途が凄まじくニッチであり、そのものとしては正直他に使えるのか?と思いつつも、スクリプトに書いた条件分岐のの処理については今後もまた使う可能性があると思い書き残しておくことにした。
動作としてはこちらのページのような形になっている。
スクロールで特定の要素が画面に収まっている際はそれに対応した背景が表示されると言った形。
用途としてはキャンペーンページなどで使えそうかな?といったところ。
以下は今回書いたスクリプトの内容。
jquery.scrollblink.js
/* * This plugin is follow all the rules of jQuery * copyright (c) 2018 cattlemute */ (function($){ $.fn.scrollblink = function(options){ var option = { contents: 'contents', show: 'show', }; var static = { contents: 'scrollblink-contents', show: 'scrollblink-show', showChildren: 'scrollblink-show-children', active: 'scrollblink-active', prep: 'scrollblink-prep', }; var config = $.extend(option, options); var inc = $(this), contents = null, shows = null, nowscroll = 0, lastscroll = 0; var scrollblink = (function(){ return{ init: function(){ inc.children('.' + config.contents).addClass(static.contents); inc.children('.' + config.show).addClass(static.show + ' ' + static.prep) .children().addClass(static.showChildren); scrollblink.setshow(); scrollblink.clip(); }, clip: function(){ $(window).bind('scroll', function(){ scrollblink.activate(); }); $(window).bind('load', function(){ $('.' + static.show).removeClass(static.prep); scrollblink.activate(); }); }, setshow: function(){ $('.' + static.show).children('.' + static.showChildren).each(function(n){ $(this).css({ 'z-index': $('.' + static.show).children('.' + static.showChildren).length - n }); }); }, activate: function($direct){ nowscroll = $(window).scrollTop(); contents = $('.' + static.contents); show = $('.' + static.show).children('.' + static.showChildren); contents.each(function(n){ if( $(this).offset().top - Math.floor( window.innerHeight / 3 ) <= $(window).scrollTop() && $(this).offset().top + $(this).outerHeight(true) + Math.floor( window.innerHeight / 2 ) >= $(window).scrollTop() + window.innerHeight ){ $(this).addClass(static.active); show.eq(n).removeClass(static.preactive); show.eq(n).addClass(static.active); } else if( $(this).hasClass(static.active) ) { $(this).removeClass(static.active); show.eq(n).removeClass(static.active); } }); lastscroll = $(window).scrollTop(); } }; })(); scrollblink.init(); return(this); }; })(jQuery);
次はこいつの動作に必要なCSS。
jquery.scrollblink.css
.scrollblink-contents{ min-height: 100vh !important; } .scrollblink-show{ display: block !important; position: fixed !important; z-index: -1 !important; top: 0 !important; left: 0 !important; right: 0 !important; bottom: 0 !important; width: 100% !important; height: 100% !important; will-change: transform; } .scrollblink-prep{ display: none !important; } .scrollblink-show-children{ display: block !important; position: absolute !important; z-index: 0; top: 0 !important; bottom: 0 !important; right: 0 !important; left: 0 !important; width: 100% !important; height: 100% !important; opacity: 0; transition: ease 0.4s; } .scrollblink-show-children.scrollblink-active{ z-index: 99999 !important; opacity: 1; }
<link />と<script />でのファイルの読み込みに関しては割愛。使う場合は適当なディレクトリで設定して下さい。
HTMLの構成とスクリプトの設定は以下のような形で設定する。
HTML
<script type="text/javascript"> (function($){ $(document).ready(function(){ $('#campaign').scrollblink({ contents: 'blocks', // Front Element show: 'bg', // Back Element }); }); })(jQuery); </script> <div id="campaign"> <div class="blocks"> <p>動作ブロック1</p> </div> <div class="blocks"> <p>動作ブロック2</p> </div> <div class="blocks"> <p>動作ブロック3</p> </div> <div class="bg"> <div style="background-image: url(bg1.jpg);background-attachment: scroll;background-size: cover;background-repeat: no-repeat;background-position: 50% 50%;"></div> <div style="background-image: url(bg2.jpg);background-attachment: scroll;background-size: cover;background-repeat: no-repeat;background-position: 50% 50%;"></div> <div style="background-image: url(bg3.jpg);background-attachment: scroll;background-size: cover;background-repeat: no-repeat;background-position: 50% 50%;"></div> </div> </div>
こんな感じで書くと、先に書いたデモページと同じような形で動かせると思う。
背景の表示周りは単純な要素構成で書いてあるので使いようによっては、上でざっくり書いたHTMLでいうところの、
<div style="background-image: url(bg1.jpg);background-attachment: scroll;background-size: cover;background-repeat: no-repeat;background-position: 50% 50%;"></div>
この要素の中に装飾要素とアニメーションなどを入れてみても良いかもしれない。
背景が表示される際に当該の背景用の要素には「scrollblink-active」がクラスとして付くから、そいつを見てあげれば容易にできると思う。
最後に備忘録的な部分でスクリプトのところ、
$(this).offset().top - Math.floor( window.innerHeight / 3 ) <= $(window).scrollTop() $(this).offset().top + $(this).outerHeight(true) + Math.floor( window.innerHeight / 2 ) >= $(window).scrollTop() + window.innerHeight $(this).addClass(static.active); show.eq(n).removeClass(static.preactive); show.eq(n).addClass(static.active); $(this).hasClass(static.active) $(this).removeClass(static.active); show.eq(n).removeClass(static.active);
この複合条件あたりは個人的にめっちゃ大事。
背景表示の移行のタイミング(つまり要素が画面内にあると認識している状態)を調整したい場合は、補正係数を弄ればよさげ。
上端の係数は以下の太字のところ。
$(this).offset().top - Math.floor( window.innerHeight / 3 ) <= $(window).scrollTop()
下端の係数は以下の太字のところを弄る。
$(this).offset().top + $(this).outerHeight(true) + Math.floor( window.innerHeight / 2 ) >= $(window).scrollTop() + window.innerHeight
継ぎ目を出したくなくて、ページの頭~一番最初の要素、最後の要素~ページの最後に常に画像を表示しておきたい場合は、
( $(this).offset().top - Math.floor( window.innerHeight / 2 ) <= $(window).scrollTop() && $(this).offset().top + $(this).outerHeight(true) + Math.floor( window.innerHeight / 2 ) >= $(window).scrollTop() + window.innerHeight ) || ( n == 0 && $(this).offset().top - Math.floor( window.innerHeight / 2 ) >= $(window).scrollTop() ) || ( n == contents.length - 1 && $(this).offset().top + $(this).outerHeight(true) + Math.floor( window.innerHeight / 2 ) <= $(window).scrollTop() + window.innerHeight )
こういう条件とか。
あんまり係数取りすぎると乱れるかもしれん。そのあたりは未検証。
まぁ何が起こるか分からんので、蓼食う虫もなんとやらな人は適当に試してみてね。
ああ、書くの忘れてた。
愛用のあいぽんと古い泥で試した限りは一応動いていたので、レスポンシブでも動くと思うんだぜ(´・ω・`)
とりあえず、今回のデモ用の動作をまとめたファイル群はこちらからダウンロードできます。
必要な方はご自由にどうぞ。