# full-screen-youtube-video

This component adds an easy way to load Youtube videos throughout your application, inside a full screen modal.

This module is a work in progress. This module can work with GIFs, but is inteneded for mp4s.

To do:
  • destroy and load mp4 on each button press

# Example

<template>
    <div>
        <FullScreenYoutubeVideo
            class="gtm-visibility"
            v-if="fullScreenYoutubeVideo.active"
            @close="fullScreenYoutubeVideo.active = false"
            :videoId="fullScreenYoutubeVideo.videoId"
            :ready="ready"
            :ended="ended"
            :paused="paused"
            :playing="playing"
            :buffering="buffering"
            :qued="qued"
        />

        <button
            class="gtm-click-link play-button"
            @click="fullScreenYoutubeVideo.active = true"
        >
            Click Me!
        </button>
    </div>
</template>

<script>
    import { FullScreenYoutubeVideo } from '@rescue/vue-modules';
    export default {
        components: {
            FullScreenYoutubeVideo,
        },
        data() {
            return {
                loader: true,
                fullScreenYoutubeVideo: {
                    active: false,
                    videoId: 'sVGn26bo9y4',
                },
            };
        },
        methods: {
            ready() {
                this.loader = false;
                console.log('ready');
            },
            ended() {
                console.log('ended');
            },
            playing() {
                console.log('playing');
            },
            paused() {
                console.log('paused');
            },
            buffering() {
                console.log('buffering');
            },
            qued() {
                console.log('qued');
            },
        },
    };
</script>

# Demo

# Installation

Install @rescue/vue-modules and vue-youtube-embed.

npm install @rescue/vue-modules vue-youtube-embed

You also need node-sass and sass-loader (If you don't have them already).

npm install node-sass sass-loader

# Usage

First import the component inside your script tags:

import { FullScreenYoutubeVideo } from '@rescue/vue-modules';

Then, register the component:

export default {
    components: {
        FullScreenYoutubeVideo,
    },
};

Create the following object inside your data object:

export default {
    components: {
        FullScreenYoutubeVideo,
    },
    data() {
        return {
            fullScreenYoutubeVideo: {
                active: false,
                videoId: '',
            },
        };
    },
};

Now add your component inside your template markup as such:

<template>
    <FullScreenYoutubeVideo
        v-if="fullScreenYoutubeVideo.active"
        @close="fullScreenYoutubeVideo.active = false"
        :video-id="fullScreenYoutubeVideo.videoId"
    />
</template>

To toggle a video, you need to set a youtube video ID, and a button to activate it, as such:

<template>
    <FullScreenYoutubeVideo
        v-if="fullScreenYoutubeVideo.active"
        @close="fullScreenYoutubeVideo.active = false"
        :video-id="fullScreenYoutubeVideo.videoId"
    />

    <button @click="fullScreenYoutubeVideo.active = true">
        Click Me!
    </button>
</template>

<script>
    export default {
        components: {
            FullScreenYoutubeVideo,
        },
        data() {
            return {
                fullScreenYoutubeVideo: {
                    active: false,
                    videoId: 'sVGn26bo9y4',
                },
            };
        },
    };
</script>

# props

videoId (Optional) (String) Youtube video ID.

ready (Optional) (Function) When video is ready.

ended (Optional) (Function) When video has ended.

playing (Optional) (Function) When video is playing.

paused (Optional) (Function) When video is paused.

buffering (Optional) (Function) When video is buffering.

qued (Optional) (Function) When video is qued.

loader (Optional) (Boolean) Set spinner loader to true or false.

# Source Code

<template>
    <div @click="$emit('close')" class="full-screen-youtube-video">
        <button @click="$emit('close')" class="close-btn gtm-click-link">
            <span></span>
            <span></span>
        </button>
        <component
            v-if="vidReady"
            :is="youtubeEmbed"
            @click.stop
            @ready="ready"
            :video-id="videoId"
            @ended="ended"
            @playing="playing"
            @paused="paused"
            @buffering="buffering"
            @qued="qued"
            :player-vars="{ autoplay: 1 }"
        ></component>
        <div @click.stop :class="{ active: loader }" class="loader">
            <svg
                class="spinner"
                width="65px"
                height="65px"
                viewBox="0 0 66 66"
                xmlns="http://www.w3.org/2000/svg"
            >
                <circle
                    class="path"
                    fill="none"
                    stroke-width="6"
                    stroke-linecap="round"
                    cx="33"
                    cy="33"
                    r="30"
                />
            </svg>
        </div>
    </div>
</template>

<script>
    import Vue from 'vue';

    export default {
        props: [
            'videoId',
            'ready',
            'ended',
            'playing',
            'paused',
            'buffering',
            'qued',
            'loader',
        ],
        data() {
            return {
                youtubeEmbed: null,
                vidReady: false,
            };
        },
        mounted() {
            import('vue-youtube-embed').then((module) => {
                module.default.install(Vue);
                this.youtubeEmbed = module.YouTubePlayer;
                this.vidReady = true;
            });
        },
    };
</script>

<style lang="scss">
    $offset: 187;
    $duration: 1.4s;

    .full-screen-youtube-video {
        width: 100vw;
        height: 100vh;
        background: rgba(0, 0, 0, 1);
        position: fixed;
        top: 0px;
        left: 0px;
        z-index: 50;
        opacity: 0;
        animation: opacity-in 0.25s linear;
        animation-fill-mode: forwards;

        @media (min-width: 767px) {
            background: rgba(0, 0, 0, 0.75);
        }

        .close-btn {
            position: absolute;
            right: 25px;
            top: 25px;
            border: 1px solid white;
            width: 50px;
            height: 50px;
            border-radius: 25px;
            cursor: pointer;
            z-index: 10;
            background: rgba(0, 0, 0, 0.4);
            box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.5);
            transition: 0.25s transform ease-in-out,
                0.25s background-color ease-in-out;

            &:hover,
            &:active {
                transform: scale(1.05);
                background-color: rgba(0, 0, 0, 0.4);
            }

            span {
                width: 30px;
                display: block;
                height: 1px;
                background: white;
                margin-left: 2px;

                &:nth-child(1) {
                    transform: rotate(45deg);
                }

                &:nth-child(2) {
                    transform: rotate(-45deg);
                }
            }

            i {
                font-size: 1.5em;
                color: white;
            }
        }

        iframe {
            position: absolute;
            left: 50%;
            width: 100%;
            height: 70%;
            transform: translate(-50%, -50%);
            top: 50%;
            box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.4);

            @media (min-width: 767px) {
                width: 90%;
            }
        }

        .loader {
            position: absolute;
            left: 50%;
            width: 100%;
            height: 70%;
            transform: translate(-50%, -50%);
            top: 50%;
            background: transparent;
            opacity: 0;
            pointer-events: none;
            transition: 0.25s opacity ease-in-out;
            transform-origin: 50% 50%;
            display: flex;
            justify-content: center;
            align-items: center;

            @media (min-width: 767px) {
                background: rgb(50, 50, 50);
                width: 90%;
            }

            &.active {
                opacity: 1;
                pointer-events: all;
            }

            .spinner {
                animation: rotator $duration linear infinite;
            }

            .path {
                stroke-dasharray: $offset;
                stroke-dashoffset: 0;
                transform-origin: center;
                animation: dash $duration ease-in-out infinite,
                    colors ($duration * 4) ease-in-out infinite;
            }
        }
    }

    @keyframes opacity-in {
        0% {
            opacity: 0;
        }

        100% {
            opacity: 1;
        }
    }

    @keyframes rotator {
        0% {
            transform: rotate(0deg);
        }

        100% {
            transform: rotate(270deg);
        }
    }

    @keyframes colors {
        0% {
            stroke: #4285f4;
        }

        25% {
            stroke: #de3e35;
        }

        50% {
            stroke: #f7c223;
        }

        75% {
            stroke: #1b9a59;
        }

        100% {
            stroke: #4285f4;
        }
    }

    @keyframes dash {
        0% {
            stroke-dashoffset: $offset;
        }

        50% {
            stroke-dashoffset: $offset/4;
            transform: rotate(135deg);
        }

        100% {
            stroke-dashoffset: $offset;
            transform: rotate(450deg);
        }
    }
</style>