かんろぐ Written by kan

Smart Custom Fieldで、1つ目のスライドを動画、2つ目以降は画像にするカスタマイズ【Slick】

CODE HTML/CSS JavaScript Web制作 WordPress

PR ※当サイトではアフィリエイト広告を利用しています

Smart Custom Fieldとslick.jsを使って1つ目のスライドを動画、2つ目以降は画像にする方法が知りたい。

本記事ではこのようなカスタマイズ方法を実現します。

まずは完成された状態を見てみましょう

  • 1枚目→動画
  • 2枚目→画像
  • 3枚目→画像
  • 4枚目→画像

このように、1枚目は動画、2枚目以降は画像・・・といったSmart Custom Field+slick.jsを使ってカスタマイズをすることができます。

また、この登録方法は管理画面から可能となっています。
管理画面からの登録方法
これならクライアント側でも自由に登録が可能となります。便利ですねー!\(^^)/

このカスタマイズをするにあたって、Smart Custom Fieldとslick.jsを使った一般的なカスタマイズ方法は下記を参考にしました。»Smart Custom Fieldsを使ってWordPressでスライダーを動的にする方法
本当にありがとうございます🙇‍!

この記事ではすべて画像の場合であれば問題ないのですが、1枚目だけ動画の場合のカスタマイズを構築してみました。

要望によってはメインビジュアルで動画→画像と見せたい場合もあるかと思います。

そんなときに使えるかと思います。

それではサクッと見ていきしょう!

Smart Custom Fieldで管理画面に登録画面を追加する

まずは、functions.phpに下記のソースコードを貼り付けます。

functions.php

//TOPスライダー設定
/**
 * @param string $page_title ページのtitle属性値 (必須)
 * @param string $menu_title 管理画面のメニューに表示するタイトル (必須)
 * @param string $capability メニューを操作できる権限 (必須)
 * @param string $menu_slug オプションページのスラッグ (必須)
 * @param string|null $icon_url メニューに表示するアイコンの URL
 * @param int $position メニューの位置
 */
SCF::add_options_page('TOPスライダー', 'TOPスライダー', 'edit_posts', 'top_slider', 'dashicons-admin-generic', 11);

/**
 * カスタムフィールドを定義
 * 
 * @param array  $settings  MW_WP_Form_Setting オブジェクトの配列
 * @param string $type      投稿タイプ or ロール
 * @param int    $id        投稿ID or ユーザーID
 * @param string $meta_type post | user
 * @return array
 * 
 */
function my_add_meta_box($settings, $type, $id, $meta_type)
{
    if ('top_slider' == $type) {
        $setting = SCF::add_setting('id-top_slider', 'TOPスライダー設定');
        $items = array(
            array(
                'type'        => 'text', //*タイプ
                'name'        => 'top_slider_movie', //*名前
                'label'       => '1つ目の動画URLを貼り付ける-2つ目以降は空白にする', //ラベル
            ),
            array(
                'type'        => 'image', //*タイプ
                'name'        => 'top_slider_img_pc', //*名前
                'label'       => '【PC】スライダー画像', //ラベル
                'size'        => 'medium' // プレビューサイズ
            ),
            // array(
            //     'type'        => 'image', //*タイプ
            //     'name'        => 'top_slider_img_sp', //*名前
            //     'label'       => '【SP】スライダー画像', //ラベル
            //     'size'        => 'medium' // プレビューサイズ
            // ),
            array(
                'type'        => 'textarea',                      // タイプ
                'name'        => 'top_slider_text',                   // 名前
                'label'       => 'スライダーテキスト設定',        // ラベル
                'rows'        => 3,                               // 行数
            ),
            array(
                'type'        => 'text', //*タイプ
                'name'        => 'top_slider_link', //*名前
                'label'       => 'リンク設定', //ラベル
            ),
        );
        $setting->add_group('top_slider_group', true, $items);
        $settings[] = $setting;
    }
    return $settings;
}
add_filter('smart-cf-register-fields', 'my_add_meta_box', 10, 4);

今回はスマホが必要なかったため、コメントアウトして削除しています。

必要であれば追加してください。

array(
 'type'        => 'text', //*タイプ
 'name'        => 'top_slider_movie', //*名前
 'label'       => '1つ目の動画URLを貼り付ける-2つ目以降は空白にする', //ラベル
),

注意点としては、こちらを追加しています。

動画URLをテキストで取得して表示させるためです。

設定画面を入力

続いて設定画面です。

Smart Costum Fieldと同じような画面が、管理画面に登録されていると思います。

ここからテキストや画像を埋め込んでいきます。
テキストや画像の埋め込み
動画のURLについては、2つ目、3つ目は空白のままでOKです。
動画のURLについて
表示する数は追加することもできます。

ソースコードの記入

設定画面が終了したら、HTML/CSS/JavaScrptのソースコードを記入していきます。

HTML

<?php
    $top_slider = SCF::get_option_meta('top_slider');
    $top_slider_group = $top_slider['top_slider_group'];
    if (!empty($top_slider_group)) :
    ?>
        <!--MV-->
        <div class="main-slider-box">
            <section class="main-slider">
                <?php foreach ($top_slider_group as $item) :
                    //画像
                    $top_img_pc_id = $item['top_slider_img_pc'];
                    $top_img_pc_src = wp_get_attachment_url($top_img_pc_id);
                    // $top_img_sp_id = $item['top_slider_img_sp'];
                    // $top_img_sp_src = wp_get_attachment_url($top_img_sp_id);
                    //動画
                    $top_slider_movie = $item['top_slider_movie'];
                    //alt
                    $alt_pc = get_post_meta($top_img_pc_id, '_wp_attachment_image_alt', true);
                    //テキスト
                    $top_slider_text = $item['top_slider_text'];
                    //ボタンリンク
                    $top_slider_link = $item['top_slider_link'];
                ?>
                    <?php if (!empty($top_slider_movie)) : ?>
                        <div class="item video">
                            <video class="slide-video slide-media" muted preload="metadata">
                                <source src="<?php echo $top_slider_movie; ?>" type="video/mp4" />
                            </video>
                            <a href="<?php echo $top_slider_link; ?>" class="caption"><?php echo $top_slider_text; ?></a>
                        </div>
                    <?php
                    // 動画がなく、画像が設定されている場合は画像を表示
                    elseif (!empty($top_img_pc_src)) : ?>
                        <div class="item image">
                            <figure>
                                <div class="slide-image slide-media" style="background-image:url('<?php echo $top_img_pc_src; ?>');">
                                    <img src="" data-lazy="<?php echo $top_img_pc_src; ?>" class="image-entity" alt="<?php echo $alt_pc; ?>" />
                                </div>
                                <a href="<?php echo $top_slider_link; ?>" class="caption"><?php echo $top_slider_text; ?></a>
                            </figure>
                        </div>
                <?php endif;
                endforeach; ?>
            <?php endif; ?>
            </section>
        </div> 

CSS

Scssで記入しているので注意。

//ブレイクポイント
$breakpoints: (sm: 699,
  md: 768,
  lg: 1024,
  xl: 1440,
);

//メディアクエリー
$mediaquerys: (sm: "screen and (max-width: #{map-get($breakpoints,'sm')}px)",
  md: "screen and (max-width: #{map-get($breakpoints,'md')}px)",
  lg: "screen and (max-width: #{map-get($breakpoints,'lg')}px)",
  xl: "screen and (max-width: #{map-get($breakpoints,'xl')}px)",
);

@mixin mq($mediaquery: md) {
  @media #{map-get($mediaquerys, $mediaquery)} {
    @content;
  }
}

%bv_hidden {
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
%filled_obj {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.main-slider-box .main-slider {
  position: relative;
  width: 100%;
  // height: 38vw;
  height: 80vh;
  min-height: 8vw;
  margin-top: 104px;
  margin-bottom: 100px;
  opacity: 0;
  visibility: hidden;
  transition:all 1.2s ease;
  &.slick-initialized {
    opacity: 1;
    visibility: visible;
  }
  @include mq(md){
    margin-top: 50px;
  }
}
.main-slider-box .slick-initialized .slick-slide{
  height: 80vh!important;
  @include mq(md){
    
  }
}
.main-slider-box .slick-slide {
  position: relative;
  height: 38vw;
  @extend %bv_hidden;
  @include mq(md){
    
  }
  &::before {
    @extend %filled_obj;
    @extend %bv_hidden;
    background-color: #000;
    opacity: .3;
    z-index: 1;
    @include mq(md){
    
    }
  }
  video {
    display: block;
    position: absolute;
    top: 50%;
    left: 50%;
    min-width: 100%;
    min-height: 100%;
    width: auto;
    height: auto;
    transform:translate(-50%, -50%);
    object-fit: cover;
    @include mq(md){
    
    }
  }
  iframe {
    position: relative;
    pointer-events: none;
  }
  figure {
    position: relative;
    height: 100%;
  }
  .slide-image {
    opacity: 0;
    height: 100%;
    background-size: cover;
    background-position: center;
    // background-color:rgba(#c46897,.38);
    // background-blend-mode:overlay;
    transition:all .8s ease;
    &.show {
      opacity: 1;
    }
  }
  .image-entity {
    width: 100%;
    opacity: 0;
    visibility: hidden;
  }
  .loading {
    position: absolute;
    top: 44%;
    left: 0;
    width: 100%;
  }
  .slide-media {
    animation:slideOut .4s cubic-bezier(0.4, 0.29, 0.01, 1);
  }
  &.slick-active {
    z-index: 1;
    .slide-media {
      animation:slideIn 2.4s cubic-bezier(0.4, 0.29, 0.01, 1);
    }
    .caption {
      opacity: 1;
      transform:translateY(0);
      transition:all .7s cubic-bezier(0.32, 0.34, 0, 1.62) .6s;
    }
  }
}
.caption {
  position: absolute;
  top: 44%;
  left: 5%;
  text-align: center;
  padding: 20px;
  border: 3px solid;
  color: #fff;
  margin: 0;
  font-size: 40px;
  font-weight: bold;
  letter-spacing: .02em;
  opacity: 0;
  z-index: 1;
  transition:all .3s ease;
  transform:translateY(100px);
  @extend %bv_hidden;
  @include mq(md){
    top: unset;
    bottom: 5%;
    font-size: 20px;
  }
}

.main-slider-box .slick-dots {
  text-align: center;
  padding-top: 15px;
  bottom: 10px!important;
  li {
    display: inline-block;
    vertical-align: top;
    margin: 0 8px;
    button {
      width: 16px;
      height: 16px;
      border: none;
      cursor: pointer;
      border-radius: 50%;
      border: 2px solid #fff;
      box-shadow: 0 0 0 0 transparent;
      vertical-align: middle;
      color: #fff;
      background-color: #fff;
      transition:all .3s ease;
      opacity: .4;
      &:focus {
        outline: none;
      }
      &:hover {
        opacity: 1;
      }
    }
    &.slick-active {
      button {
        border-color: $bg_color;
        box-shadow: 0 0 0 2px #fff;
        opacity: 1;
      }
    }
  }
}

.main-slider-box .slick-next{
  right: 30px!important;
}

.container {
  background-color: #f2f2f2;
  color: #444;
  line-height: 1.6;
  padding: 40px 0;
  .content {
    width: 90%;
    max-width: 980px;
    margin: 0 auto;
  }
  p {
    margin-bottom: 40px;
  }
}

@keyframes slideIn {
  from {
    filter:blur(15px);
  }
  to {
    filter:blur(0);
  }
}
@keyframes slideOut {
  from {
    filter:blur(0);
  }
  to {
    filter:blur(15px);
  }
}

JavaScript

var slideWrapper = $(".main-slider"),
    videos = slideWrapper.find('.slide-video'),
    lazyImages = slideWrapper.find('.slide-image'),
    lazyCounter = 0;

// When the slide is changing
function playPauseVideo(slick, control) {
    var currentSlide, slideType, video;

    currentSlide = slick.find(".slick-current");
    slideType = currentSlide.attr("class").split(" ")[1];
    video = currentSlide.find("video").get(0);

    if (slideType === "video") {
        if (video != null) {
            if (control === "play") {
                video.play();
            } else {
                video.pause();
            }
        }
    }
}

// DOM Ready
$(function () {
    // Initialize
    slideWrapper.on("init", function (slick) {
        slick = $(slick.currentTarget);
        setTimeout(function () {
            playPauseVideo(slick, "play");
        }, 1000);
    });
    slideWrapper.on("beforeChange", function (event, slick) {
        slick = $(slick.$slider);
        playPauseVideo(slick, "pause");
    });
    slideWrapper.on("afterChange", function (event, slick) {
        slick = $(slick.$slider);
        playPauseVideo(slick, "play");
    });
    slideWrapper.on("lazyLoaded", function (event, slick, image, imageSource) {
        lazyCounter++;
        if (lazyCounter === lazyImages.length) {
            lazyImages.addClass('show');
            // slideWrapper.slick("slickPlay"); // you might want to remove this line
        }
    });

    // all videos have ended listener
    videos.each(function () {
        this.onended = function () {
            slideWrapper.slick('slickNext');
        };
    });
    // Start the slider
    // Start the slider
    slideWrapper.slick({
        // normal options...
        infinite: true,
        slidesToShow: 1,
        slidesToScroll: 1,
        arrows: true,
        dots: true,
        // the magic
        lazyLoad: 'progressive',
        speed: 600,
        fade: true,
        // autoplay options
        autoplay: true, // これにより自動再生が有効になります
        autoplaySpeed: 5000, // 3000ミリ秒 = 3秒ごとにスライドが切り替わります
        // cssEase: 'cubic-bezier(0.87, 0.03, 0.41, 0.9)'
    });
});

解説

こちらはSlickスライダーを使用しており、スライドの表示と制御を行っています。

lazyLoad:progressiveというオプションが指定されているので、画像の遅延ローディングが有効になっています。

これは、data-lazy属性を使用して、画像の読み込みを遅らせるために使用されます。

そのため、src属性は使用しておりません。

src属性を使用して画像を即時に読み込む場合は、Slickスライダーの設定からlazyLoadオプションを削除または変更する必要があります。

lazyLoadオプションを無効にするには、Slickスライダーの設定からこのオプションを削除し、HTMLタグでsrc属性を使用してください。

Smart Custom Fieldの解説

Smart Custom Fieldの部分の解説です。


・$top_slider = SCF::get_option_meta('top_slider'); - Smart Custom Fieldsからtop_sliderというオプションを取得
・$top_slider_group = $top_slider['top_slider_group']; - top_sliderオプションの中からtop_slider_groupという配列を取得します。これが各スライダーアイテムの情報を含んでいます
・if (!empty($top_slider_group)) : - top_slider_groupが空でない場合(つまり、スライダーアイテムが存在する場合)、以下のコードを実行
・foreach ($top_slider_group as $item) : - 各スライダーアイテムに対して繰り返し処理をしてます
・a. 画像や動画、テキストなどの情報を変数に保存
・b. 例:$top_img_pc_id = $item['top_slider_img_pc']; - この行では、スライダーの画像IDを取得
・<div class="item video"> - 動画を含むスライダーアイテムを表示
・<div class="item image"> - 画像を含むスライダーアイテムを表示

Smart Custom Fieldはとても便利なのでぜひ活用してみてくださいね。

他にもSmart Custom Fieldの記事を見てみる

この記事を書いた人
かんろぐ/プロフィールアイコン
かん
未経験からWeb制作会社へ転職 | Webの楽しさや転職のあれこれを発信 | 転職サポート「CodeChange」主催 / 転職成功15名超 | WordPress・Shopify | CodeBegin転職講師 | マナブさん弟子 | カオマンガイとサウナ | ブロガー | ●かんろぐ運営/月間7,600PV達成 |

合わせて読みたい記事