Skip to content

Instantly share code, notes, and snippets.

@andrewinsidelazarev
Last active November 12, 2024 14:38
Show Gist options
  • Save andrewinsidelazarev/70f581460419813773aeb848f4ad8c62 to your computer and use it in GitHub Desktop.
Save andrewinsidelazarev/70f581460419813773aeb848f4ad8c62 to your computer and use it in GitHub Desktop.
Shortcode for Youtube video
function youtube_embed_shortcode($atts) {
// Extract the video ID from the shortcode parameters
$atts = shortcode_atts(array(
'id' => ''
), $atts);
// Check if the video ID is provided
if (empty($atts['id'])) {
return '<p>Please provide a video ID.</p>';
}
// Construct the thumbnail URL in WebP format
$thumbnail_url = 'https://i.ytimg.com/vi_webp/' . esc_attr($atts['id']) . '/maxresdefault.webp';
// Generate HTML with a thumbnail, SVG play button overlay, and video iframe
$output = '<div style="position: relative; width: 100%; padding-top: 56.25%;">';
$output .= '<img src="' . esc_url($thumbnail_url) . '" alt="Video Thumbnail" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; cursor: pointer;" onclick="this.style.display=\'none\'; this.nextElementSibling.style.display=\'none\'; this.nextElementSibling.nextElementSibling.src=\'https://www.youtube.com/embed/' . esc_attr($atts['id']) . '?autoplay=1\'; this.nextElementSibling.nextElementSibling.style.display=\'block\';">';
// Inline SVG play button
$output .= '<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: pointer; z-index: 1;" onclick="this.previousElementSibling.click();">';
$output .= '<svg width="68" height="48" viewBox="0 0 68 48" xmlns="http://www.w3.org/2000/svg">
<path d="M66.52 7.68C65.76 5.23 63.97 3.44 61.52 2.68C57.68 1.48 34 1.48 34 1.48C34 1.48 10.32 1.48 6.48 2.68C4.03 3.44 2.24 5.23 1.48 7.68C0.28 11.52 0.28 24 0.28 24C0.28 24 0.28 36.48 1.48 40.32C2.24 42.77 4.03 44.56 6.48 45.32C10.32 46.52 34 46.52 34 46.52C34 46.52 57.68 46.52 61.52 45.32C63.97 44.56 65.76 42.77 66.52 40.32C67.72 36.48 67.72 24 67.72 24C67.72 24 67.72 11.52 66.52 7.68Z" fill="red"/>
<path d="M45 24L27 14V34L45 24Z" fill="white"/>
</svg>';
$output .= '</div>';
$output .= '<iframe src="" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen loading="lazy" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none;"></iframe>';
$output .= '</div>';
return $output;
}
add_shortcode('youtube_embed', 'youtube_embed_shortcode');
@andrewinsidelazarev
Copy link
Author

andrewinsidelazarev commented Nov 2, 2024

Explanation:
Play Button Overlay: A red circular div with border-radius: 50% is used to create the play button.
Play Icon: inline SVG

Use [youtube_embed id="VIDEO_ID"] to test it.

@andrewinsidelazarev
Copy link
Author

В старых видео, бывает, что миниатюра есть с максимальным разрешением 720p.

Вот код, учитывающий это:

function youtube_embed_shortcode($atts) {
// Извлекаем ID видео из параметров шорткода
$atts = shortcode_atts(array(
'id' => ''
), $atts);

// Проверяем, указан ли ID видео
if (empty($atts['id'])) {
    return '<p>Please provide a video ID.</p>';
}

// URL миниатюр в формате WebP
$thumbnail_url_webp = 'https://i.ytimg.com/vi_webp/' . esc_attr($atts['id']) . '/maxresdefault.webp';
$fallback_url_webp = 'https://i.ytimg.com/vi_webp/' . esc_attr($atts['id']) . '/sddefault.webp';

// Генерация HTML с невидимым элементом для проверки
$output = '<div style="position: relative; width: 100%; padding-top: 56.25%;">';
$output .= '<img id="yt-thumb-' . esc_attr($atts['id']) . '" src="" alt="Video Thumbnail" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; cursor: pointer; display: none;" onclick="this.style.display=\'none\'; this.nextElementSibling.style.display=\'none\'; this.nextElementSibling.nextElementSibling.src=\'https://www.youtube.com/embed/' . esc_attr($atts['id']) . '?autoplay=1\'; this.nextElementSibling.nextElementSibling.style.display=\'block\';">';

// SVG кнопка Play
$output .= '<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: pointer; z-index: 1;" onclick="this.previousElementSibling.click();">';
$output .= '<svg width="68" height="48" viewBox="0 0 68 48" xmlns="http://www.w3.org/2000/svg">
                <path d="M66.52 7.68C65.76 5.23 63.97 3.44 61.52 2.68C57.68 1.48 34 1.48 34 1.48C34 1.48 10.32 1.48 6.48 2.68C4.03 3.44 2.24 5.23 1.48 7.68C0.28 11.52 0.28 24 0.28 24C0.28 24 0.28 36.48 1.48 40.32C2.24 42.77 4.03 44.56 6.48 45.32C10.32 46.52 34 46.52 34 46.52C34 46.52 57.68 46.52 61.52 45.32C63.97 44.56 65.76 42.77 66.52 40.32C67.72 36.48 67.72 24 67.72 24C67.72 24 67.72 11.52 66.52 7.68Z" fill="red"/>
                <path d="M45 24L27 14V34L45 24Z" fill="white"/>
            </svg>';
$output .= '</div>';

$output .= '<iframe src="" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen loading="lazy" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none;"></iframe>';
$output .= '</div>';

// Скрипт для скрытой загрузки и применения миниатюры
$output .= '<script>
    document.addEventListener("DOMContentLoaded", function() {
        var visibleImg = document.getElementById("yt-thumb-' . esc_attr($atts['id']) . '");
        var testImg = new Image();
        testImg.src = "' . esc_url($thumbnail_url_webp) . '";

        testImg.onload = function() {
            if (testImg.naturalWidth <= 120 && testImg.naturalHeight <= 90) {
                visibleImg.src = "' . esc_url($fallback_url_webp) . '";
            } else {
                visibleImg.src = "' . esc_url($thumbnail_url_webp) . '";
            }
            visibleImg.style.display = "block";
        };

        testImg.onerror = function() {
            visibleImg.src = "' . esc_url($fallback_url_webp) . '";
            visibleImg.style.display = "block";
        };
    });
</script>';

return $output;

}
add_shortcode('youtube_embed', 'youtube_embed_shortcode');

@andrewinsidelazarev
Copy link
Author

function youtube_embed_shortcode($atts) {
// Извлекаем параметры шорткода, включая необязательный параметр "sd"
$atts = shortcode_atts(array(
'id' => '',
'sd' => false
), $atts);

// Проверяем, указан ли ID видео
if (empty($atts['id'])) {
    return '<p>Please provide a video ID.</p>';
}

// Выбор миниатюры на основе параметра "sd"
$thumbnail_file = $atts['sd'] ? 'sddefault.webp' : 'maxresdefault.webp';
$thumbnail_url = 'https://i.ytimg.com/vi_webp/' . esc_attr($atts['id']) . '/' . $thumbnail_file;

// Генерация HTML с миниатюрой, кнопкой Play и iframe
$output = '<div style="position: relative; width: 100%; padding-top: 56.25%;">';
$output .= '<img src="' . esc_url($thumbnail_url) . '" alt="Video Thumbnail" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; cursor: pointer;" onclick="this.style.display=\'none\'; this.nextElementSibling.style.display=\'none\'; this.nextElementSibling.nextElementSibling.src=\'https://www.youtube.com/embed/' . esc_attr($atts['id']) . '?autoplay=1\'; this.nextElementSibling.nextElementSibling.style.display=\'block\';">';

// SVG кнопка Play
$output .= '<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: pointer; z-index: 1;" onclick="this.previousElementSibling.click();">';
$output .= '<svg width="68" height="48" viewBox="0 0 68 48" xmlns="http://www.w3.org/2000/svg">
                <path d="M66.52 7.68C65.76 5.23 63.97 3.44 61.52 2.68C57.68 1.48 34 1.48 34 1.48C34 1.48 10.32 1.48 6.48 2.68C4.03 3.44 2.24 5.23 1.48 7.68C0.28 11.52 0.28 24 0.28 24C0.28 24 0.28 36.48 1.48 40.32C2.24 42.77 4.03 44.56 6.48 45.32C10.32 46.52 34 46.52 34 46.52C34 46.52 57.68 46.52 61.52 45.32C63.97 44.56 65.76 42.77 66.52 40.32C67.72 36.48 67.72 24 67.72 24C67.72 24 67.72 11.52 66.52 7.68Z" fill="red"/>
                <path d="M45 24L27 14V34L45 24Z" fill="white"/>
            </svg>';
$output .= '</div>';

$output .= '<iframe src="" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen loading="lazy" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none;"></iframe>';
$output .= '</div>';

return $output;

}
add_shortcode('youtube_embed', 'youtube_embed_shortcode');

@andrewinsidelazarev
Copy link
Author

Теперь вы можете использовать шорткод так:

[youtube_embed id="VIDEO_ID"] для загрузки maxresdefault.webp.
[youtube_embed id="VIDEO_ID" sd="true"] для загрузки sddefault.webp.
Этот подход позволит гибко переключаться между вариантами миниатюр.

@andrewinsidelazarev
Copy link
Author

andrewinsidelazarev commented Nov 12, 2024

Решение проблемы с переходом в полноэкранный режим:

`
function youtube_embed_shortcode($atts) {
$atts = shortcode_atts(array(
'id' => '',
'sd' => false
), $atts);

if (empty($atts['id'])) {
    return '<p>Please provide a video ID.</p>';
}

$videoId = esc_attr($atts['id']);
$thumbnail_file = $atts['sd'] ? 'sddefault.webp' : 'maxresdefault.webp';
$thumbnail_url = 'https://i.ytimg.com/vi_webp/' . $videoId . '/' . $thumbnail_file;

$output = '<div style="position: relative; width: 100%; padding-top: 56.25%;">';
$output .= '<img src="' . esc_url($thumbnail_url) . '" alt="Video Thumbnail" class="youtube-thumbnail" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; cursor: pointer;" onclick="playVideo(this, \'' . $videoId . '\');">';

$output .= '<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: pointer; z-index: 1;" onclick="playVideo(this.previousElementSibling, \'' . $videoId . '\');">';
$output .= '<svg width="68" height="48" viewBox="0 0 68 48" xmlns="http://www.w3.org/2000/svg">
                <path d="M66.52 7.68C65.76 5.23 63.97 3.44 61.52 2.68C57.68 1.48 34 1.48 34 1.48C34 1.48 10.32 1.48 6.48 2.68C4.03 3.44 2.24 5.23 1.48 7.68C0.28 11.52 0.28 24 0.28 24C0.28 24 0.28 36.48 1.48 40.32C2.24 42.77 4.03 44.56 6.48 45.32C10.32 46.52 34 46.52 34 46.52C34 46.52 57.68 46.52 61.52 45.32C63.97 44.56 65.76 42.77 66.52 40.32C67.72 36.48 67.72 24 67.72 24C67.72 24 67.72 11.52 66.52 7.68Z" fill="red"/>
                <path d="M45 24L27 14V34L45 24Z" fill="white"/>
            </svg>';
$output .= '</div>';

$output .= '<iframe id="youtube-iframe-' . $videoId . '" src="" class="youtube-iframe" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen loading="lazy" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: none;"></iframe>';

// Кнопка для перехода в полноэкранный режим
$output .= '<button onclick="goFullscreen(\'youtube-iframe-' . $videoId . '\');" style="position: absolute; bottom: 10px; right: 10px; width: 35px; height: 35px; background: rgba(0, 0, 0, 0.7); color: white; border: 1px solid white; cursor: pointer; display: none; border-radius: 5px; padding: 0;" title="Fullscreen">'; 
$output .= '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M4 4H10V2H2V10H4V4Z" fill="white"/>
                <path d="M14 2V4H20V10H22V2H14Z" fill="white"/>
                <path d="M20 14H22V22H14V20H20V14Z" fill="white"/>
                <path d="M4 14H2V22H10V20H4V14Z" fill="white"/>
            </svg>';
$output .= '</button>';
$output .= '</div>';

$output .= '
<script>
    function playVideo(thumbnail, videoId) {
        thumbnail.style.display = "none";
        thumbnail.nextElementSibling.style.display = "none";
        const iframe = document.getElementById("youtube-iframe-" + videoId);
        iframe.src = "https://www.youtube.com/embed/" + videoId + "?autoplay=1";
        iframe.style.display = "block";

        // Показать кнопку для перехода в полноэкранный режим
        iframe.nextElementSibling.style.display = "block";
    }

    function goFullscreen(iframeId) {
        const iframe = document.getElementById(iframeId);
        if (iframe.requestFullscreen) {
            iframe.requestFullscreen();
        } else if (iframe.webkitRequestFullscreen) { // для Safari
            iframe.webkitRequestFullscreen();
        } else if (iframe.mozRequestFullScreen) { // для Firefox
            iframe.mozRequestFullScreen();
        } else if (iframe.msRequestFullscreen) { // для IE/Edge
            iframe.msRequestFullscreen();
        }
    }
</script>';

return $output;

}
add_shortcode('youtube_embed', 'youtube_embed_shortcode');
`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment