TECH::EXPERT【jQuery】スライドショーBasic【72日目】

【学習内容】


・画像とキャプションの表現
・見え隠れするサイドバー
・スライドショーを作る Basic


【画像とキャプションの表現】


HTML上に配置された画像にmouseoverしたときに、画像に被せる形で簡単な説明文を表示します。

□HTML

<div id=”images”>
 <h2>IMAGES</h2>
 <div class=”inner clearfix”>
   <p><img src=”img/01_img.jpg”><strong>test1</strong><span></span></p>
   <p><img src=”img/02_img.jpg”><strong>test2</strong><span></span></p>
   <p><img src=”img/03_img.jpg”><strong>test3</strong><span></span></p>
 </div>
</div>

<strong>のあとに空の<span>が置いてありますが、JavaScriptでここを上手く活用していきます。

□CSS

#images p {
 overflow: hidden;
}

#images p strong {
 position: absolute;
 display: block;
 z-index: 1;
 bottom: 0;
 width: 540;;
 height: 30px;
 background: rgba(0, 0, 0, 0.5);
 text-align: left;
 padding: 20px;
}

#images p span {
 position: absolute;
 display: block;
 z-index: 0;
 top: 0;
 width: 580px;
 height: 380px;
 box-shadow: inset 0 0 50px rgba(50, 30, 0, 0.6),
             inset 0 0 100px rgba(50, 30, 0, 0.3),
 background: rgba(255, 155, 0, 0.2);
 opacity: 0;
}


#images p strongは、黒い箱を示していて、画像下部に表示するようにします。

#images p spanでは、内側の影を示していて、bow-shadow:insetを使用する事で画像全体に対して、‘内側に’影をつけます。CSSではopacity: 0;と指定することで透明にしていますが、JSでopacityを操作することでアニメーションを加えます。

□1つ目の画像のCSS

#images p:nth-child(1) strong {
 opacity: 0;
}

strong要素のみ画像のキャプションを0にして透明にします。

□1つ目の画像のJavaScript

$(function() {
 var duration = 300;
 var $images = $(‘images p’)
 $images.filter(‘:nth-child(1)’)
   .on(‘mouseover’, function() {
     $(this).find(‘strong, span’).stop(true).animate({
       opacity: 1
     }, duration);
   })
   .on(‘mouseout’, function() {
     $(this).find(‘strong, span’).stop(true).animate({
       opacity: 0
     }, duration);
   });
});

<解説>
.filter()メソッドを使用して、3枚の画像の中から1枚目の画像だけをセレクタに指定します。

その後、.on()メソッドで、発火条件がmouseoverで第二引数の関数が動くようにします。

1枚目の画像のHTMLの中から、<strong>と<span>を複数指定して、opacityを操作することでアニメーションを加えます。

□2つ目の画像のCSS

#images p:nth-child(2) strong {
 opacity: 0;
 left: -200%;
}

left: -200%;とすることで、画像の左側に黒い箱が隠れている形になります。

□2つ目の画像のJavaScript

$(function() {
 var duration = 300;
 var $images = $(‘#images p’); 
 $images.filter(‘:nth-child(2)’)
   .on(‘mouseover’, function(){
     $(this).find(‘.strong’).stop(true).animate({
       opacity: 1;
       left: 0%;
     }, duration);
     $(this).find(‘span’).stop(true).animate({
       opacity: 1;
     }, duration);
   })
   .on(‘mouseout’, function(){
     $(this).find(‘.strong’).stop(true).animate({
       opacity: 0;
       left: -200%;
     }, duration);
     $(this).find(‘span’).stop(true).animate({
       opacity: 1;
     }, duration);
   });
}) ;

<解説>

考え方はほぼ1つ目のJSと同じですが、今回はキャプションだけをスライドインさせるので、2つに分ける必要があります。

□3つ目の画像のCSS

#images p:nth-child(3) strong {
 bottom: -80px;
 background: rgba(34, 34, 34, 1);
}

#images p:nth-child(3) img {
 position: absolute;
 top: 0px;
}

もはや得意芸になりつつある要素位置のマイナスでの指定ですが、今回はbottomから-80pxの位置に忍ばせておきます。

また、画像本体についてはtopから0pxの位置に固定しておきます。

□3つ目の画像のJavaScript

$(function() {
 var duration = 300; 
 var $images = $(‘#images p’);
 $images.filter(‘:nth-child(3)’)
   .on(‘mouseover’, function(){
     $(this).find(‘strong’).stop(true).animate({
       bottom: ‘0px’
     }, duration);
     $(this).find(‘span’).stop(true).animate({
       opacity: 1
     }, duration);
     $(this).find(‘img’).stop(true).animate({
       top: ‘-20px’
     }, duration * 1.3);
   })
   .on(‘mouseout’, function(){
     $(this).find(‘strong’).stop(true).animate({
       bottom: ‘-80px’
     }, duration);
     $(this).find(‘span’).stop(true).animate({
       opacity: 0
     }, duration);
     $(this).find(‘img’).stop(true).animate({
       top: ‘0px’
     }, duration);
   });
});

<解説>
前提として、<strong>で囲まれた黒い箱は要素の-80px分下に、<span>で囲まれた要素のopacityは0に、<img>はtopから0pxの位置にあります。

これらの濃さや位置をだんだんと変化させることでアニメーションを付与していきます。

また<img>に関しては、ゆっくりとアニメーションの時間をかけたいので、*1.3することで秒数を伸ばしています。


【見え隠れするサイドバー】

クリック操作によってWebページの左側に格納できるサイドバーを実装します。

□HTML

<aside>
 <ul>
   <li><a href=”#”><img src=”img/01_aside.png”></a></li>
   <li><a href=”#”><img src=”img/01_aside.png”></a></li>
   <li><a href=”#”><img src=”img/01_aside.png”></a></li>
</ul>
<button><img src=”img/btn_open.png”></button>
</aside>

□CSS

.page-main > aside {
 width: 350px;
 height: 100&;
 top: 0;
 left: -350px;
 position: fixed;
}

.page-main > aside ul {
 margin: 0;
 padding: 0;
 top: 50px;
 left: 114px;
 position: absolute;
}

.page-main > aside li {
 margin: 0 0 20px;
 line-style: none;
}

.page-main > aside button {
 background-color: rgba(0, 0, 0, 0.8);
 display: block;
 position: absolute;
 top: 150px;
 left: 350px;
 width: 50px;
 height: 132px;
 margin: 0;
 padding: 0;
 border: none;
}

CSSでは、サイドバー全体に対して、left: -350px;をかけているので、デフォルトで画面の外にサイドバーが位置する形です。

サイドバーの幅自体が350pxなので、このleftの値を操作することでにょきっと出すことができます。

□サイドバーのjavaScript

今回はmouseoverではなく、clickでサイドバーが出るようにします。

$(function(){
 var duration = 300;
 var $aside = $(‘.page-main . aside’);
 var $asidButton = $aside.find(‘button’)
   .on(‘click’, function() {
     $aside.toggleClass(‘open’);
     if($aside.hasClass(‘open’)) {
       $aside.stop(true).animate({
         left: ‘-70px’
       }, duration, ‘easeOutback’);
       $asidButton.find(‘img’)
         .attr(‘src’, ‘img/btn_close.png’);
     }else{
       $aside.stop(true).animate({
         left: ‘-350px’
       }, duration, ‘easeInBack’);
       $asidButton.find(‘img’)
         .attr(‘src’, img/btn_open.png);
       };
   });
});


<解説>

toggleClass()メソッドは、「引数に指定されたクラス名(文字列)が、jQueryオブジェクト内の要素のclass属性に指定されているか判定し、指定されていない場合は追加し、すでに指定されている場合は削除するメソッド」です。

その後、‘open’クラスを持っている場合と、持っていない場合で条件分岐させます。
hasClass()メソッドはその名の通り「引数に渡したクラス名が「対象のclass属性に含まれていればtrueを返し、そうでなければfalseを返すメソッド」です。

if文の中では、aside要素のclass属性に「open」が含まれている場合は下記の2つの処理を実行します。

①サイドバーを表示するアニメーション
CSSで画面外に置いておいたサイドバーを画面の中に引っ張ってくる内容が記述されています。

②img要素に対してattr()メソッドを実行する
attr()メソッドは、「要素の属性値の取得または属性値の設定を行うメソッド」です。

.attr(‘src’, ‘img/btn_close.png’);と記述してあるので、「属性値の設定を行う」処理が実行されています。

要は「btn_close.png、(CLOSEボタン)に置き換える処理を行っています。

elseの処理では基本的に上記とは逆の処理を行っており、サイドバーを画面外に戻し、CLOSEボタンをOPENボタンに置き換えます


【スライドショーを作る Basic】

スライドショーとは、時間の経過やクリックによってスライド(画像)が切り替わるコンポーネントです。

Basicでは、時間の経過によって画像が切り替わるスライドショーを作成します。

○スライドショーのしくみ
①複数枚のスライドを1箇所に重ねて配置する
②いったん配置したスライドを全て非表示にする
③最初のスライドのみをfadeInで表示する
④一定時間が経過したら、現在表示されているスライドをfadeOutし、次のスライドをfadeInする
⑤一定時間ごとにこれを繰り返す。
⑥最後のスライドまで進んだら、先頭のスライドに戻る。


□HTML

<div class=”slideshow”>
 <img src=”./img/slide-1.jpg” alt=”” width=”1600” height=”465”>
 <img src=”./img/slide-2.jpg” alt=”” width=”1600” height=”465”>
 <img src=”./img/slide-3.jpg” alt=”” width=”1600” height=”465”>
 <img src=”./img/slide-4.jpg” alt=”” width=”1600” height=”465”>
</div>

□CSS

.slideshow {
 overflow: hidden;
 position: relative;
 min-width: 960px;
 height: 465px;
}

.slideshow img {
 display: none;
 position: absolute;
 left: 50%;
 margin-left: -800px;
}

上記の通り、各画像をposition: absolute;で1箇所に重ねて配置し、display: none;で非表示にしています。

□JavaScript

$(function() [
 $(‘.slideshow’).each(function() {
   var $slides = $(this).find(‘img’),
   slideCount = $slides.length,
   currentIndex = 0;
   $slides.eq(currentIndex).fadeIn();
   setInterval(showNextSlide, 7500);
   function showNext
slide() {
     var nextIndex = (currentIndex + 1) % slideCount;
     $slides.eq(currentIndex).fadeOut();
     $slides.eq(nextIndex).fadeIn();
     currentIndex = nextIndex;
 }
});
});

<解説>

①eachを使う
冒頭で.each(function() {を使い、.slideshowクラスを持った要素それぞれに対して括弧内の処理を実行します。

②最初に変数を用意する
スライドの命名でなんとなく雰囲気を感じ取ってほしいのですが、「全部のスライド」、「スライドの枚数」、「現在のimgの背番号」をここで定義します。

③currentIndexをフェードインさせる
CSSによって全ての画像は非表示の状態です。

eq()メソッドを使って、「複数あるjQueryオブジェクトのうち、引数に渡したインデックスに該当するものを選択」します。

最初()内の初期値にcurrentindex(0)、つまり最初の画像がフェードインされます。

④setInterval()関数でスライドの動く時間を設定する

setInterval()関数は、「指定した時間ごとに指定した処理を実行する関数」です。
第一引数には、「実行する関数」、第二引数には「その関数を実行する間隔」を指定します。

実行する関数は、次のスライドを表示する関数(showNextSlide())はこのあと記述します。

⑤次のスライドを表示する関数(showNextSlide())を記述する

var nextIndexに格納する値は、次のスライド % スライドの枚数です。

単純にcurrentIndex + 1だと、最後のスライドの次のスライド(存在しないスライド)を指定することになるので、あまりを算出する記述をすれば最初のスライドに戻る事ができます。

currentIndexに対してはfadeOutさせ、nextIndexをfadeInさせます。

最後にcurrentIndexを更新すればOKです。

【所感】

やはり見た目の部分で動きがあると、内容がリッチになりますね。

見栄っ張りというかカッコつけの性格の僕に案外合っているのかなあなんて思ってたりしています。

さて、しばらく足を運んでいないTECH::EXPERTですが、来週末にはChat-spaceの提出期限のようです。

進捗管理表を見ていると、期限内に終わらせることができそうなのは10人ちょっとといったところでしょうか。

ちょうど1週間前にAWSの東京リージョンで大規模な障害があったようで、ちょうどデプロイに取り掛かっていた方は思わぬ部分で足を引っ張られたのではないでしょうか。

とにかく1人でも多くの方が期限内にChat-spaceを完成させて一緒にチーム開発に進めたらいいなと思います。

この記事が気に入ったらサポートをしてみませんか?