ホームページのバナーはバニラのjsよりslick.jsを使った方が早いかつ品質が良い話（2）

前回は<a href='https://qiita.com/u9908028/items/e666237c854e15a84103'>こちら</a>にご参照ください。
<a href='https://qiita.com/u9908028/items/e666237c854e15a84103'>https://qiita.com/u9908028/items/e666237c854e15a84103</a>
目標は、既存のバナーをカドカワ様の公式ページのようなバナーに改造することです。

<h1>バナーの特性と目標</h1>
見た目は似てきたものの、マウス動作による反応、バナーの最後尾から最初の画像に移動する際のニメーションなどは自作のバニラjavascriptバナーでは作れませんでした。
<br><br>
カドカワ様のバナーは下記の幾つの特性があります。
<ol>
<li>定期的に画像を左に移動する（以下、定期的移動と呼称します）
<li>マウスが画像の上にいるとき、定期的移動が停止
<li>マウスが「点」を押したら、対応する画像に移動した後、定期的に移動しない
<li>左右の矢印を押したら、定期的移動状態が停止しても、定期的移動状態になる
<li>最後尾の画像が最初の画像に変わるとき、スムーズに一枚分のピクセルだけが移動する
<li>しかし、現在の画像が最後尾で、最初の点を押すと、画像の移動は一枚分ではない
<li>レスポンシブデザインはあるんですが、画像の大きさは固定、画像の数はレスポンシブデザインに対応する感じ。モバイル版になると画像の大きさが変化し始める
</ol>
上記の幾つ主な点を念頭において、会社のバナーを修正していきます。

<h1>キーワードの「slick」</h1>
バニラのjavascriptで色々悩んでいる時、カドカワ様、弊社がよく取引をするスリーエーネットワーク様のバナーのコードを何度も見返しました。
<br>そこで、どうして関係のあまり無い両社が、バナーCSSのclassに同じような命名をされているんだろうと疑問を思いました。
<br>（もしかして同じWeb制作会社に頼んでいたんじゃないかなと思いましたが、カドカワ様はドワンゴなどの有名なIT関係子会社を持っているんですから、自社で依頼すれば良いのでは？と思いました）
<br>
<br>slickを検索したら、slick.jsというjQueryのプラグインを見つけました。
<br>公式サイトは<a href='https://kenwheeler.github.io/slick/'>こちら</a>になります。<br>
<a href='https://kenwheeler.github.io/slick/'>https://kenwheeler.github.io/slick/</a>
<br><br>
見つけたら、あとはドキュメントを読み漁って、自社のサイトに入れるだけです。

<h1>slick.jsの導入</h1>
公式サイトの「get it now」タブに書いてあります。<br>
CDN式とファイルダウンロード式、両方ありますが、<br>
弊社のサイトは既に「ローディング時間が長い」症状が出ているため、ファイルダウンロード式を選びました。<br>
あととても需要なことは、slick.jsはjQueryのプラグインなので、jQueryの導入を先にしないといけません。
<br>（弊社のサイトは2013年からずっと改修していない古いサイトなので、jQueryは大量に使っており、既に導入されていました）


<br>ダウンロードしたファイルを解凍したら、中身にはたくさんのファイルがあって、使うのは
「<b>slick.js</b>」、「<b>slick.min.js</b>」、「<b>slick.css</b>」、「<b>slick-theme.css</b>」の四つのファイルと、あまり重要ではないのですが、「<b>ajax-loader.gif</b>」、<b>fontsフォルダー内の「slick.svg」</b>も使っていました。
（使わないとエラーメッセージがずっと出ています。ウザイので指示通りのパスに画像ファイルを置きましたが、こういう場合はもし重大なエラーじゃなかったら、無視するか、原作コードの該当箇所をコメントアウトしても良いと思います。）

指定パスにアップロードしたら、`<head>`内に`<link>`と`<script>`を追加しましょう。
```html:HTML
<head>
    <script type="text/javascript" src="plugin/jquery/jquery-1.8.3.min.js"></script>
    <link rel="stylesheet" type="text/css" href="css/slick/slick-theme.css" />
    <link rel="stylesheet" type="text/css" href="css/slick/slick.css" />
    <script type="text/javascript" src="js/jquery/slick.min.js"></script>
</head>
```
jsファイルはslick.jsとslick.min.jsの両方から一つを選んで良いです。
「slick.min.js」は最低限必要なコードだけが記載されているファイルだから、ローディング時間が長い我が社のホームページにより適合しているので、そちらを選びました。

cssファイルは両方とも入れる必要があります。
バナーの画像、点、矢印がそれぞれ別のファイルに書かれているため、両方入れないと、一からcssを書かないといけないことになります。
（というものの、弊社サイトに合わせる際に、ほとんどのcss classを書き直しましたけど）
完了したら、次のステップはslickの公式サイトを参照しながら、jQueryコードを書きます。

<h1>jQueryにslick.jsを記述</h1>

```Javascript:Javascript
//ｊQueryの基本型
$(document).ready(function({
    
});
```
jQueryのプラグインなため、上記のようなjQueryの基本型の中に記述するが必要です。
slick.jsの基本型は`$('HTML/CSSの要素名やクラスなど').slick();`です。
その中にドキュメントに書いてある引数を`{}`で囲むオブジェクトを入れて、設定するだけで良いんです。
下記は私が会社のバナーを改修した際に使った引数達です。

```Javascript:Javascript
$(document).ready(function({
    $('#bannerDiv').slick({
        autoplay: true,
        autoplaySpeed: 4000,
        dots: true,
        dotsClass: 'slick-dots',
        pauseOnHover: true,
        pauseOnDotsHover: true,
        centerMode: true,
        arrows: true,
        slidesToShow: 1,
        variableWidth: true,
        speed: 800,
    });
});
```
<ul>
<li>autoplay：定期的に左に移動する。デフォルトはfalseだから、コード記述で起動する必要があります。
<li>autoplaySpeed：何秒ごとに一回移動する。単位はミリセカンド（ms）、1000で一秒になります。
<li>dots：「・・・」の有無。デフォルトはfalseで、点がついていないです。
<li>dotsClass：もし「・・・」の出現するところが別のところに出てきて欲しいなら、その要素のclass名を記入する必要があります。
<br>デフォルトのclass名は「slick-dots」です。つまり私が書いたコードのdotsClass記述を消しても良いということです。
<li>pauseOnHover：画像hover時に定期的移動を止める。
<li>pauseOnDotsHover：マウスが点hover時に定期的移動を止める。
<li>centerMode：第一枚のバナー画像が真ん中に置く。デフォルトはfalseだから、一番左に順番に描画しています。
<li>arrows:左右矢印の有無。デフォルトは既にtrueですから、こちらも記述を消して良いです。
<li>slidesToShow：何枚の画像同時出現する。デフォルトは1です。
<br>こちらの数字を0に設定すると、サイトがエラーを発生し、パンクして動かなくなります。
<br>こちらの数字は「何枚の画像をひと組にする」と捉えて良いでしょう。しかし10枚の画像しかないのに、数字を11に設定すると、対応する「・・・」が1になり、予期せぬ効果になります。
<li>variableWidth：レスボンスデザインに合わせて画像の大きさが自動的に調整されますが、これをtrueにしたら、画像の大きさは固定数値にすることができます。
<li>speed：画像が左に移動する動作を何秒内に終わらせる。つまり、画像移動の速度です。
</ul>

jsの部分はこのように綺麗で、簡潔になりました。
あとはcssを好きな形に調整するだけで良いです。
ちなみに、HTMLも下記のように簡潔になったのです。

```HTML:HTML
<div class="bannerDiv-slick-wrap">
    <div class="slick">
        <{section name=adv01_sec1 loop=$a01_link01_1}>
        <div>
            <{if $a01_link01_1[adv01_sec1].weblink == ""}>
                <a href="javascript:void(0);" title="<{$a01_link01_1[adv01_sec1].title01}>">
                    <img src="<{$a01_link01path}><{$a01_link01_1[adv01_sec1].dirname}>Crop_<{$a01_link01_1[adv01_sec1].upfile1}>" width="687" height="239" />
                </a>
            <{else}>
                <a href="<{$a01_link01_1[adv01_sec1].weblink}>" target="<{$a01_link01_1[adv01_sec1].weblink_target}>" title="<{$a01_link01_1[adv01_sec1].title01}>">
                    <img src="<{$a01_link01path}><{$a01_link01_1[adv01_sec1].dirname}>Crop_<{$a01_link01_1[adv01_sec1].upfile1}>" width="687" height="239" />
                </a>
            <{/if}>   
        </div>
        <{/section}>
    </div>
</div>
```
相変わらず複雑ですが、自分で左右矢印のdivと「・・・」のdiｖを記述しなくて良いようになりました。
<{XXXX}>の記述は前回で言及したPHPの<a href='https://www.smarty.net/'>Smarty</a>（<a href='https://www.smarty.net/'>Smarty</a>）の記述法です。（2022/09/01 Open Power TemplateをSmartyに修正しました。開発会社がSmartyのタグを別定義したそうです。）
今回は割愛させていただきます。


<h1>CSSの調整</h1>
自分が全バナー区域を包むクラス以外のクラスは、全部slick.jsのデフォルト名を使わないといけません。<br>
多分jQueryが生成する際に、必要な要素が既にその通りに命名してありますから、クラス名通りにCSSを調整しないと、全く変更できません。
下記はslick.jsのクラス概要になります。<br>
（詳細を知りたい方はダウンロードしたファイルの「slick.css」、「slick-theme.css」をご覧ください。）
<ul>
<li>slick-slide：一つ一つの画像、その外側のdivです。内部には<code>img</code>があります。
<li>slick-slider：一つ一つ画像を包むものです。あまり調整しなくて良いです。私はその外にもう一層を包んで調整しました。
<li>slick-arrow：デフォルトの左右矢印のdivです。
<li>slick-prev：左矢印のdivです。デフォルトだと、文字のみ使っているそうです。
<li>slick-next：右矢印のdivです。上記と同様。
<li>slick-dots：全部の点を包むdivです。デフォルトの点はul li で作成しているそうです。
<li>slick-active：どの画像が表示されているのかの点に付けるクラスです。色が黒くなるやつです。
</ul>

私がwrapper（包む）ものを含めて、調整した内容は下記に紹介します。

```css:CSS
.bannerDiv-slick-wrap {
    position: relative;
    margin-top: -15px;
    overflow: hidden;
}
```
一番外側に全部を包むdivです。上のHTMLにも書いてありますが、slickという二層目がありますが、多分不要です。
（自分の悪い癖です。元々は「・・・」のdivを包むために画像と点のdivを分けて付けましたが...）

```css:CSS
.bannerDiv-slick-wrap .slick .slick-slide {
    min-width: 687px;
    min-height: 239px;
    position: relative;
    overflow: hidden;
    margin: 0;
}
.bannerDiv-slick-wrap .slick .slick-slide img:hover {
    transition: 0.3s all;
    opacity: 0.5;
}
```
一つの画像区域は最低でも 687 * 239 px に設定しました。
デフォルトだと、画像と画像の間に間隔があるんですが、カドカワ様のように緊密に表示するには`margin`を 0 にするが必要です。
あとは、マウスが画像の上にいる時の`hover`動作を付けました。こちらは`img`に付けました。

```css:CSS
.bannerDiv-slick-wrap .slick .slick-arrow {/*arrow area background*/
    width: 50px;
    height: 100%;
    background: rgba(0,0,0,0.5);
    cursor: pointer;
    z-index: 1;
    position: absolute;
    border: none;
    margin: 0;
    padding: 0;
    transition: 0.3s all;
}
```
左右矢印の後ろ、黒い背景の区域です。
絶対バナー画像の上に表示しないといけないので、z-indexを1に設定します。
`position`は`absolute`にしましたが、デフォルトもそうだったので、基本は書かなくて良いです。
デフォルトは「真ん中にある白い背景、灰色の文字の丸い矢印ボタン」の形になります。
`height`、`width`、`background`を上書きしないといけません。
`transition`は`hover`時の変化に合わせて付けないといけないものです。

```css:CSS
.bannerDiv-slick-wrap .slick .slick-prev:before {
    /* prev arrow text */
    content: '\276E';
}
.bannerDiv-slick-wrap .slick .slick-next:before {
    /* next arrow text */
    content: '\276F';
}
.bannerDiv-slick-wrap .slick .slick-arrow:before {
    /*arrows size */
    font-size: 30px;
    transition: 0.3s all;
}
.bannerDiv-slick-wrap .slick .slick-arrow:hover {
    background: rgba(0,0,0,0.8);
}
.bannerDiv-slick-wrap .slick .slick-next {
    right: 0;
}
.bannerDiv-slick-wrap .slick .slick-next:before {
    left: 25px; /*come back a little*/
} 
.bannerDiv-slick-wrap .slick .slick-prev {
    left: 0;
}
.bannerDiv-slick-wrap .slick .slick-prev:before {
    right: 25px;
}
```

この辺はちょっとややこしくて、cssコードにコメントを入れました。
矢印の文字はbeforeというPseudo-classesを使っているそうです。
（HTMLでデフォルトの矢印を追加できないから、矢印の文字を変える場合はbeforeのcontentに書かないといけません）
HTMLの符号はW3schoolを参照しています。
slick-arrow:beforeで矢印のサイズを変えています。
slick-prevとslick-nextは位置調整なため、rightとleftだけを記述しています。
右矢印は右寄りですが、寄りを戻さないと矢印の半分が画面外になりますので、ちょっとだけ矢印の部分のleftを設定し、戻しました。
ちなみに、slick-next:beforeは別に両部分に分ける必要がなく、一緒のところ書いて良いんです。
最後は矢印にhoverした際にちょっと背景の色が変わるのを設定したら完了です。

```css:CSS
/* Dots */
.bannerDiv-slick-wrap .slick .slick-dotted.slick-slider /*next div distance*/
{
    margin-bottom: 30px;
}
.bannerDiv-slick-wrap .slick .slick-dots /*dots wrapper div*/
{
    position: absolute;
    bottom: -25px;
    display: block;
    width: 100%;
    padding: 0;
    margin: 0;
    list-style: none;
    text-align: center;
}
.bannerDiv-slick-wrap .slick .slick-dots li
{
    position: relative;
    display: inline-block;
    width: 16px;
    height: 16px;
    margin: 0 5px;
    padding: 0;
    cursor: pointer;
}
.bannerDiv-slick-wrap .slick .slick-dots li button /*in dot unit*/
{
    font-size: 6px;
    line-height: 16px;
    display: block;
    width: 16px;
    height: 16px;
    padding: 0px;
    cursor: pointer;
    color: transparent;
    border: 0;
    outline: none;
    background: lightgrey;
    border-radius: 50%;
    opacity: 0.5;
}
.bannerDiv-slick-wrap .slick .slick-dots li button:hover,
.bannerDiv-slick-wrap .slick .slick-dots li button:focus
{
    outline: none;
}
.bannerDiv-slick-wrap .slick .slick-dots li button:hover:before,
.bannerDiv-slick-wrap .slick .slick-dots li button:focus:before
{
    opacity: 1;
    background: black;
    border-radius: 50%;
    line-height: 16px;
    width: 16px;
    height: 16px;
}
.bannerDiv-slick-wrap .slick .slick-dots li button:before /*in dots text*/
{
    font-family: Arial;
    content: attr(data-before);
    color: white;
    line-height: 16px;
    width: 16px;
    height: 16px;
    font-size: 6px;
}
.bannerDiv-slick-wrap .slick .slick-dots li.slick-active button:before
{
    opacity: 1;
    background: black;
    border-radius: 50%;
    width: 16px;
    height: 16px;
    line-height: 16px;
}
```
こちらは全部「・・・」のスタイルを調整するためのcss内容です。
全部デフォルトから変えたもので、HTMLの構造は多分、このようになっています。

```HTML:HTML
<div　class='slick-dots'>
    <ul>
        <li>
            <button></button>
        </li>
    </ul>
</div>
```
一つの点が`li`、その中に`button`があります。（私が書いたわけじゃないです、slick.jsが自動生成したものです）
一番下のslick-activeは現在画面中央の画像に対応する点のclassです。
文字を入力するところは `li button:before` になります。デフォルトは「・」（日本語の点）です。
ちなみに、何も改修しないなら、カドカワ様のような「・・・」になります。（間隔がやや広め、点の●が小さめ）
私は上司の別の要求で、上記のように改修しないといけませんので、
点と点の間隔は小さめ、文字を入れるため●がちょっと大きめになるように設定しました。

一つ点の単位は`li`ですので、間隔は`li`に設定します。
`button`は点の内部の色面積です。
上司は点の中に数字を入れて欲しいと要求したので、文字は`button:before`のところの`content`に記述しました。
バナー画像の数は動的である必要がありますから、`attr()`の方法で書きました。
最後はslickが生成した後、jQueryのコードで数字を入れます。
（こちらはslick.jsにない機能なので、自分でjsで行なわれなければなりません）

```javascript:Javascript
$(document).ready(function({
    $('.slick').slick({
    	/*上記のコードなので、略させていただきます*/
    });
    for(let i=0; i<$('.slick-dots').children().length; i++){
        $('.slick-dots').children().eq(i).children().attr('data-before', i+1);
    }
});
```
forループでslickが生成された後に、button:beforeを書き換えれば、先ほどの点の中の文字が出現し、上司の要求を達成できます。
`slick-dots`しかclass名が付いていないので、
子供の`ul`、の子供の`li`（ここは何個子供もいるので、`eq(i)`を記述）、の子供の`button`、の先ほど記述した`before`の`content`の`attr('data-before')`を選択し、文字を入れていきます。

<h1>完成品プレビュー</h1>
上記の調整で、弊社サイトのバナーのアフターは下記のようになります。<br>
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606064/b90d4c0b-dd91-9489-06af-1e205de6e424.png'>
上記はウィンドーのサイズが1920px以上の時に見える画像です。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/606064/7fd7fbe0-0970-dd7a-7654-b7422f7a429b.png)
上記はウィンドーサイズが1280pxの時に見える様子です。
ちょっとだっけ派手になりましたね。パパパと並べたら賑やかな感じがしてきました。

<h1>あとがき</h1>
前回も言ったと思いますが、こちらは「文系初心者」、「外国人」、「非IT企業の情シス」が書いている文章で、想定した対象は「ウェブ開発保守契約が切られて（もしくは切れて）いる会社」の情シス、ウェブサイト担当者などです。
<br>と言っても、現在の公式サイトは大体何らかのフレームワークで作られて、もしくはwordpressで改修したものが多いでしょう。
<br>弊社のような長寿で大幅改修したことのない公式サイトは、色々古い技術が残って、コード読みに時間は掛かりますが、初心者にとって教科書で見た上古時代の技術を鍛えられるかもしれません。
<br>（ちなみに、弊社のサイトはレスポンシブデザインをしておらず、別の「モバイル版のサイト」があるのです）

<br>でも、もし会社が新規サイトを立ち上げる計画があるなら、ちゃんとしたフレームワーク、レスポンシブデザインをした方が良いと思います。
理由は
1. ウェブ技術の移り変わりが早い。<br>古い技術を知っている人がどんどん減っていって、単価も上がっていきますから、バニラjsやバニラPHPで作られたサイトの保守費用がどんどん上がります。
1. 流行りの技術を使わないと、保守契約を別会社に変えたいとき、見積もり書で書かれた金額が高くなります。なぜというと、上記が原因です。
1. レスポンシブをしないと、後の保守は「PC向けサイト」と「モバイル向けサイト」の二つのサイトをやらなければならないので、単純にやることが二倍になります。
1. 保守契約が終わり、自社エンジニアが保守を行うときに、バニラだと書き方色々、ドキュメントを残さないと次の人が別の書き方をして、最終的に書き方がバラバラになって、コードがさらに読み辛くなります。<br>フレームワークだと、最低限フレームワークのルールがあるから、保守しやすいです。<br>（たとえば弊社のような8年ほど長寿で一回も改修したことのないサイトは、何人何代の担当者を経て、コメントアウトした旧コードを放置したり、コメントに日付と名前を記入したり、テストコードを削除しなかったり、実行しないコードを削除しなかったり、命名ルールがキャメルケースとスネークケースとケバブケースで混同していたり、しています。このようなサイトは修正箇所のコード読みがめちゃ時間掛かります）

長くなりましたが、ここまでお読みいただき、誠にありがとうございます。
所々変な日本語があったり、コード技術が初心者だったりしていると思いますが、できるだけ修正いたしますので、お気軽に指摘いただければ幸いです。


<h1>参考資料</h1>
<ul>
<li>https://ithelp.ithome.com.tw/articles/10277686
<li>https://and-ha.com/coding/slick/
<li>https://zero-plus.io/media/jquery-slick/
<li>https://weblasts.com/javascript/slick-basic-option
<li>https://b-risk.jp/blog/2020/01/slick-customize/
<li>https://kenwheeler.github.io/slick/
<li>https://github.com/kenwheeler/slick/
<li>https://api.jquery.com/children/
</ul>