0
0

【備忘録】ビデオ要素の動作を制御し、クリック時にレイアウトやスタイルを変更する

Posted at

やりたい事

ビデオをクリック時にレイアウトやスタイルを変更する

書いたJavaScript

JavaScript
document.addEventListener('DOMContentLoaded', function () {
    const videosPC = document.querySelectorAll('.topbrandforPC video');
    const containers = document.querySelectorAll('.topbrand_contents_inner');
    const nonWorkingContainer = document.querySelector('.topbrand_not_working');
    const nonWorkingWidth = '10%';
    const activeWidth = '60%';
    const inactiveWidth = '20%';
    const defaultNonWorkingWidth = ${100 - (2 * 40)}%; // 20%
    const videosSP = document.querySelectorAll('.topbrandforSP video');

    // 初期状態を設定
    containers.forEach(container => {
        if (container.classList.contains('topbrand_not_working')) {
            container.style.width = defaultNonWorkingWidth;
        } else {
            container.style.width = '40%';
        }
    });

    videosPC.forEach((video, index) => {
        if (video.closest('.topbrand_not_working')) {
            // topbrand_not_working内の動画コントロールを常に非表示に設定
            video.controls = false;
            video.addEventListener('mouseenter', () => video.controls = false);
            video.addEventListener('mousemove', () => video.controls = false);
            video.addEventListener('mouseleave', () => video.controls = false);
            return; // topbrand_not_workingクラスを持つコンテナはスキップ
        }

        const container = containers[index];
        const article = container.querySelector('.topbrand_article');

        video.addEventListener('click', () => {
            videosPC.forEach((v, i) => {
                const otherContainer = containers[i];
                const otherArticle = otherContainer.querySelector('.topbrand_article');

                if (v === video) {
                    otherContainer.style.width = activeWidth;
                    otherContainer.style.filter = 'none';
                    otherArticle.style.display = 'none'; // topbrand_articleを非表示
                    otherContainer.classList.add('video_start');
                    v.play();
                } else if (!otherContainer.classList.contains('topbrand_not_working')) {
                    otherContainer.style.width = inactiveWidth;
                    otherContainer.style.filter = 'brightness(0.5)';
                    otherArticle.style.display = 'block'; // topbrand_articleを表示
                    otherContainer.classList.remove('video_start');
                    v.pause();
                }
            });
            nonWorkingContainer.style.width = nonWorkingWidth;
            nonWorkingContainer.style.filter = 'brightness(0.5)';
        });

        // 再生停止時の処理
        video.addEventListener('pause', function () {
            if (!this.seeking) {
                containers.forEach(container => {
                    const article = container.querySelector('.topbrand_article');
                    if (container.classList.contains('topbrand_not_working')) {
                        container.style.width = defaultNonWorkingWidth;
                        container.style.filter = 'none';
                    } else {
                        container.style.width = '40%';
                        container.style.filter = 'none';
                        article.style.display = 'block'; // topbrand_articleを表示
                        container.classList.remove('video_start');
                    }
                });
            }
        });

        // 再生終了時の処理
        video.addEventListener('ended', () => {
            containers.forEach(container => {
                const article = container.querySelector('.topbrand_article');
                if (container.classList.contains('topbrand_not_working')) {
                    container.style.width = defaultNonWorkingWidth;
                    container.style.filter = 'none';
                } else {
                    container.style.width = '40%';
                    container.style.filter = 'none';
                    article.style.display = 'block'; // topbrand_articleを表示
                    container.classList.remove('video_start');
                }
            });
        });
    });

});

全体の流れ

  • 1.ページの読み込み完了時に初期設定を行う
  • 2.初期状態で各コンテナの幅を設定する
  • 3.ビデオ要素のクリック時に、他のビデオやコンテナの状態を変更する
  • 4.ビデオの再生停止時と終了時にコンテナの状態を元に戻す

1.ページの読み込み完了時に初期設定を行う。

JavaScript
document.addEventListener('DOMContentLoaded', function () {
    const videosPC = document.querySelectorAll('.topbrandforPC video');
    const containers = document.querySelectorAll('.topbrand_contents_inner');
    const nonWorkingContainer = document.querySelector('.topbrand_not_working');
    const nonWorkingWidth = '10%';
    const activeWidth = '60%';
    const inactiveWidth = '20%';
    const defaultNonWorkingWidth = `${100 - (2 * 40)}%`; // 20%
    const videosSP = document.querySelectorAll('.topbrandforSP video');

・document.addEventListener('DOMContentLoaded', function () {...}): ページの読み込みが完了したときに実行される関数を設定。
・const videosPC, const containers, const nonWorkingContainerなど: 各要素を取得し変数に格納。

2. 初期状態で各コンテナの幅を設定する。

JavaScript
      containers.forEach(container => {
        if (container.classList.contains('topbrand_not_working')) {
            container.style.width = defaultNonWorkingWidth;
        } else {
            container.style.width = '40%';
        }
    });

3. ビデオ要素のクリック時に、他のビデオやコンテナの状態を変更する。

JavaScript
      videosPC.forEach((video, index) => {
        if (video.closest('.topbrand_not_working')) {
            video.controls = false;
            video.addEventListener('mouseenter', () => video.controls = false);
            video.addEventListener('mousemove', () => video.controls = false);
            video.addEventListener('mouseleave', () => video.controls = false);
            return;
        }

        const container = containers[index];
        const article = container.querySelector('.topbrand_article');

        video.addEventListener('click', () => {
            videosPC.forEach((v, i) => {
                const otherContainer = containers[i];
                const otherArticle = otherContainer.querySelector('.topbrand_article');

                if (v === video) {
                    otherContainer.style.width = activeWidth;
                    otherContainer.style.filter = 'none';
                    otherArticle.style.display = 'none';
                    otherContainer.classList.add('video_start');
                    v.play();
                } else if (!otherContainer.classList.contains('topbrand_not_working')) {
                    otherContainer.style.width = inactiveWidth;
                    otherContainer.style.filter = 'brightness(0.5)';
                    otherArticle.style.display = 'block';
                    otherContainer.classList.remove('video_start');
                    v.pause();
                }
            });
            nonWorkingContainer.style.width = nonWorkingWidth;
            nonWorkingContainer.style.filter = 'brightness(0.5)';
        });

・video.addEventListener('click', () => {...}): ビデオがクリックされたときの動作を設定。
・クリックされたビデオは再生し、他のビデオは一時停止し、各コンテナの幅やスタイルを変更。

4.ビデオの再生停止時と終了時にコンテナの状態を元に戻す。

JavaScript
          video.addEventListener('pause', function () {
            if (!this.seeking) {
                containers.forEach(container => {
                    const article = container.querySelector('.topbrand_article');
                    if (container.classList.contains('topbrand_not_working')) {
                        container.style.width = defaultNonWorkingWidth;
                        container.style.filter = 'none';
                    } else {
                        container.style.width = '40%';
                        container.style.filter = 'none';
                        article.style.display = 'block';
                        container.classList.remove('video_start');
                    }
                });
            }
        });

        video.addEventListener('ended', () => {
            containers.forEach(container => {
                const article = container.querySelector('.topbrand_article');
                if (container.classList.contains('topbrand_not_working')) {
                    container.style.width = defaultNonWorkingWidth;
                    container.style.filter = 'none';
                } else {
                    container.style.width = '40%';
                    container.style.filter = 'none';
                    article.style.display = 'block';
                    container.classList.remove('video_start');
                }
            });
        });
    });

});

新しいスクリプト要素を作成し、そのsrc属性に指定されたURLを設定し、IDをlpcats_cv_scriptに設定します。

メソッドと関数の意味

document.addEventListener('DOMContentLoaded', function () {...})

JavaScript
document.addEventListener('DOMContentLoaded', function () {
    // ページが完全に読み込まれた後に実行されるコードをここに書く
});

意味: ページの全てのHTMLが読み込まれた後に、指定された関数を実行します。これにより、DOM要素に安全にアクセスし、操作することができます。

document.querySelectorAll(selector)

JavaScript
const videosPC = document.querySelectorAll('.topbrandforPC video');

意味: 指定されたCSSセレクターに一致する全ての要素をNodeListとして返します。ここでは、クラス名がtopbrandforPCのビデオ要素を全て取得します。

document.querySelector(selector)

JavaScript
const nonWorkingContainer = document.querySelector('.topbrand_not_working');

意味: 指定されたCSSセレクターに一致する最初の要素を返します。ここでは、クラス名がtopbrand_not_workingの要素を取得します。

element.querySelector(selector)

JavaScript
const article = container.querySelector('.topbrand_article');

意味: 指定されたCSSセレクターに一致する最初の子要素を返します。ここでは、各コンテナ内のクラス名がtopbrand_articleの要素を取得します。

element.addEventListener(event, function)

JavaScript
video.addEventListener('click', () => {
    // ビデオがクリックされたときに実行するコード
});

意味: 指定されたイベントが発生したときに、指定された関数を実行します。ここでは、ビデオがクリックされたときの処理を設定しています。

element.classList.contains(className)

JavaScript
if (container.classList.contains('topbrand_not_working')) {
    // 要素がクラス`topbrand_not_working`を持っているかをチェック
}

意味: 要素が指定されたクラスを持っているかを確認し、真偽値を返します。ここでは、コンテナがtopbrand_not_workingクラスを持っているかをチェックしています。

element.style.property

JavaScript
container.style.width = '40%';

意味: 要素のスタイルプロパティを設定します。ここでは、コンテナの幅を40%に設定しています。

video.play()

JavaScript
video.play();

意味: ビデオの再生を開始します。

video.pause()

JavaScript
video.pause();

意味: ビデオの再生を一時停止します。

コンテナの初期幅を設定

JavaScript
containers.forEach(container => {
    if (container.classList.contains('topbrand_not_working')) {
        container.style.width = defaultNonWorkingWidth;
    } else {
        container.style.width = '40%';
    }
});

意味: 各コンテナの初期幅を設定します。topbrand_not_workingクラスを持つコンテナはdefaultNonWorkingWidth、それ以外は40%に設定します。

ビデオがtopbrand_not_workingクラスを持つコンテナ内にある場合の処理

JavaScript
if (video.closest('.topbrand_not_working')) {
    video.controls = false;
    video.addEventListener('mouseenter', () => video.controls = false);
    video.addEventListener('mousemove', () => video.controls = false);
    video.addEventListener('mouseleave', () => video.controls = false);
    return;
}

意味: ビデオがtopbrand_not_workingクラスを持つコンテナ内にある場合、ビデオのコントロールを常に非表示に設定し、以降の処理をスキップします。

ビデオのクリック時の動作

JavaScript
video.addEventListener('click', () => {
    videosPC.forEach((v, i) => {
        const otherContainer = containers[i];
        const otherArticle = otherContainer.querySelector('.topbrand_article');

        if (v === video) {
            otherContainer.style.width = activeWidth;
            otherContainer.style.filter = 'none';
            otherArticle.style.display = 'none';
            otherContainer.classList.add('video_start');
            v.play();
        } else if (!otherContainer.classList.contains('topbrand_not_working')) {
            otherContainer.style.width = inactiveWidth;
            otherContainer.style.filter = 'brightness(0.5)';
            otherArticle.style.display = 'block';
            otherContainer.classList.remove('video_start');
            v.pause();
        }
    });
    nonWorkingContainer.style.width = nonWorkingWidth;
    nonWorkingContainer.style.filter = 'brightness(0.5)';
});

意味: ビデオがクリックされたときに、クリックされたビデオは再生し、それ以外のビデオは一時停止します。また、各コンテナの幅やフィルターを変更し、対応する記事要素の表示/非表示を切り替えます。

ビデオの再生停止時と終了時の動作

JavaScript
video.addEventListener('pause', function () {
    if (!this.seeking) {
        containers.forEach(container => {
            const article = container.querySelector('.topbrand_article');
            if (container.classList.contains('topbrand_not_working')) {
                container.style.width = defaultNonWorkingWidth;
                container.style.filter = 'none';
            } else {
                container.style.width = '40%';
                container.style.filter = 'none';
                article.style.display = 'block';
                container.classList.remove('video_start');
            }
        });
    }
});

video.addEventListener('ended', () => {
    containers.forEach(container => {
        const article = container.querySelector('.topbrand_article');
        if (container.classList.contains('topbrand_not_working')) {
            container.style.width = defaultNonWorkingWidth;
            container.style.filter = 'none';
        } else {
            container.style.width = '40%';
            container.style.filter = 'none';
            article.style.display = 'block';
            container.classList.remove('video_start');
        }
    });
});

意味: ビデオの再生が停止または終了したときに、全てのコンテナの幅やフィルターを元に戻し、記事要素を表示します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0