vue-slickにyoutube|Vue

vue-slickにスライドの一つとしてyoutubeを埋め込む方法

動いたソースの必要箇所抜粋

実際に使用しているソースからの抜粋。

保存された画像一覧からデータを読み出してslickで展開する処理の一番うしろにyoutubeを静的に埋め込んだサンプルをテストとして追加したソース。※実際のソースなので変数等の一部はこの画面上では定義されてないものが使われている。

    <div class="c-carouselimage">
        <slick
        ref="slick"
        :options="slickOptions"
        @beforeChange="handleBeforeChange"
        >
        <div v-for="(image, index) in imagelist" :key="index" class="__imagelist">            
            <img
                :src="image.thumnail"
                alt=""
                v-if="image.thumnail"
            >
            <img
                :src="image"
                alt=""
                v-else-if="image.length > 0"
            >
            <srcset-component
                :c_src = image
                v-else
            ></srcset-component>
        </div>
        <div class="__image" v-if="qrImage">
            <img :src="qrImage + '?' + Math.random()*1" alt="">
        </div>
        <div class="__youtube">
            <div class="__youtube__item">
                <iframe width="560" height="315" src="https://www.youtube.com/embed/mh-UvrTco5w?enablejsapi=1" frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen>
                </iframe>
            </div>
        </div>
        </slick>
    </div>
<style scoped>
    .__youtube__item {
        position: relative;
        width: 100%;
        height: 0;
        /* padding-top: 56.25%; */
        padding-top: 100%;
    }
    .__youtube__item iframe{
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }
</style>
    methods: {
        handleBeforeChange(event, slick, currentSlide, nextSlide) {
            this.videoControl("pauseVideo",slick.$slides[currentSlide])
        },
        videoControl(action,slide){
            var $player = slide.getElementsByTagName("iframe")[0]
            if($player) {
                console.log("実行")
                $player.contentWindow.postMessage('{"event":"command","func":"'+action+'","args":""}', '*')
            }
        }
    },

レスポンシブ対応

iframeのソースをそのまま貼り付けただけでも動画閲覧的には問題なく稼働するが、レスポンシブで大きさを変更するなどの対応のため、slide要素には.__youtubeなどのclass名を付与し、一段階ネストして内側にボックス的な要素__youtube__itemでラップする。

slickのcssと干渉しないよう.__youtubeposition:relativeを定義して、.__youtube__itemを絶対配置にして、そこで大きさをコントロールする。

非アクティブで再生停止

スライド変更の検知

vue-slickのイベントハンドラを用いてスライド変更を検知し、非アクティブ担った場合にyoutubeを停止する。

イベントハンドラは以下のページを参照

今回はhandleBeforeChange()を使用。

slickのHTMLに@beforeChange="handleBeforeChange"をパラメータとして追加。

handleBeforeChange(event, slick, currentSlide, nextSlide) をmethodに関数として登録。

するとスライドが変更されるタイミングで実行される。

引数としてslick(該当のスライド一覧オブジェクト)とcurrentSlide(変更前のスライド番号),nextSlide(変更後のスライド番号)を取得できるので、ビデオコントロール関数を別途用意して、変更前のスライドオブジェクトと、停止命令である"pauseVideo"を渡して停止を実行させる。

再生停止処理

停止はyoutubeのAPIを使用して動画のiframepauseVideoという文字列をpostMessageするという形で行われる。

apiを使用するには動画に対してenablejsapiフラグをオンにする必要がある。

共有URLに?enablejsapi=1と付け加えるだけでOK。

参考ページ