Home / eCommerce / Product Video Cover Plugin Code
Duplicate Snippet

Embed Snippet on Your Site

Product Video Cover Plugin Code

Código para criar a função de videos como capa de produto

<10
Code Preview
php
<?php
/*
Plugin Name: WC Vídeo na Capa do Produto (Flatsome Ready)
Description: Substitui a imagem principal do produto por um vídeo local (MP4/WebM/GIF) no WooCommerce, compatível com Flatsome. Mostra também no catálogo/listagem com autoplay por visibilidade (60%).
Version: 1.2.1
Author: Seu Nome
License: GPLv2 or later
Text Domain: wc-video-capa-flatsome
*/
if (!defined('ABSPATH')) exit;
class WCV_Capa_Video_Flatsome {
    const META_KEY_ID = '_wcv_video_attachment_id';
    public function __construct() {
        // Metabox admin
        add_action('add_meta_boxes', [$this, 'add_metabox']);
        add_action('save_post_product', [$this, 'save_meta'], 10, 2);
        // Assets admin
        add_action('admin_enqueue_scripts', [$this, 'admin_assets']);
        add_action('admin_footer-post.php', [$this, 'admin_inline_js']);
        add_action('admin_footer-post-new.php', [$this, 'admin_inline_js']);
        // Front-end: single product (imagem principal)
        add_filter('woocommerce_single_product_image_html', [$this, 'replace_main_image_html'], 9999, 2);
        add_filter('woocommerce_single_product_image_thumbnail_html', [$this, 'maybe_replace_featured_in_gallery'], 9999, 2);
        // Front-end: catálogo/listagem (thumbnail do loop)
        add_filter('woocommerce_get_product_thumbnail', [$this, 'replace_loop_thumbnail'], 9999, 4);
        // CSS + JS front-end
        add_action('wp_enqueue_scripts', [$this, 'frontend_styles']);
        add_action('wp_enqueue_scripts', [$this, 'frontend_scripts']);
    }
    // ============== ADMIN ==============
    public function add_metabox() {
        add_meta_box(
            'wcv_capa_video',
            __('Vídeo de capa do produto', 'wc-video-capa-flatsome'),
            [$this, 'metabox_html'],
            'product',
            'side',
            'default'
        );
    }
    public function metabox_html($post) {
        wp_nonce_field('wcv_save_video_meta', 'wcv_video_nonce');
        $attachment_id = (int) get_post_meta($post->ID, self::META_KEY_ID, true);
        $url = $attachment_id ? wp_get_attachment_url($attachment_id) : '';
        $mime = $attachment_id ? get_post_mime_type($attachment_id) : '';
        $filename = $url ? wp_basename($url) : '';
        echo '<p>' . esc_html__('Selecione um arquivo MP4, WebM ou GIF da biblioteca de mídia. O arquivo ficará hospedado no próprio site.', 'wc-video-capa-flatsome') . '</p>';
        echo '<div id="wcv-video-wrapper">';
        echo '<input type="hidden" id="wcv_video_attachment_id" name="wcv_video_attachment_id" value="' . esc_attr($attachment_id) . '">';
        echo '<input type="text" id="wcv_video_url" class="widefat" value="' . esc_attr($url) . '" placeholder="' . esc_attr__('Nenhum arquivo selecionado', 'wc-video-capa-flatsome') . '" readonly>';
        echo '<p style="margin-top:8px;">';
        echo '<button type="button" class="button" id="wcv_select_video">' . esc_html__('Selecionar/Enviar arquivo', 'wc-video-capa-flatsome') . '</button> ';
        echo '<button type="button" class="button" id="wcv_remove_video">' . esc_html__('Remover', 'wc-video-capa-flatsome') . '</button>';
        echo '</p>';
        if ($url) {
            echo '<div id="wcv_preview" style="margin-top:8px;">';
            if ($mime === 'image/gif') {
                echo '<img src="' . esc_url($url) . '" style="max-width:100%;height:auto;" alt="">';
            } else {
                echo '<video src="' . esc_url($url) . '" style="max-width:100%;height:auto;" controls preload="metadata"></video>';
            }
            echo '<p style="font-size:12px;color:#666;margin-top:6px;">' . esc_html($filename) . '</p>';
            echo '</div>';
        } else {
            echo '<div id="wcv_preview" style="display:none;margin-top:8px;"></div>';
        }
        echo '</div>';
        echo '<p style="font-size:12px;color:#666;">' . esc_html__('Dica: mantenha o arquivo otimizado (tamanho/bitrate) para melhor performance.', 'wc-video-capa-flatsome') . '</p>';
    }
    public function admin_assets($hook) {
        global $post;
        if (!in_array($hook, ['post-new.php', 'post.php'], true)) return;
        if (empty($post) || get_post_type($post) !== 'product') return;
        wp_enqueue_media();
    }
    public function admin_inline_js() {
        global $post;
        if (empty($post) || get_post_type($post) !== 'product') return;
        ?>
        <script>
        (function($){
            function isAllowed(mime){
                return ['video/mp4','video/webm','image/gif'].indexOf(mime) !== -1;
            }
            $(document).on('click', '#wcv_select_video', function(e){
                e.preventDefault();
                var frame = wp.media({
                    title: 'Selecione um vídeo (MP4/WebM) ou GIF',
                    library: { type: ['video','image'] },
                    button: { text: 'Usar este arquivo' },
                    multiple: false
                });
                frame.on('select', function(){
                    var att = frame.state().get('selection').first().toJSON();
                    if(!isAllowed(att.mime)){
                        alert('Tipo de arquivo não permitido. Use MP4, WebM ou GIF.');
                        return;
                    }
                    $('#wcv_video_url').val(att.url);
                    $('#wcv_video_attachment_id').val(att.id);
                    var preview = $('#wcv_preview').empty().show();
                    if(att.mime === 'image/gif'){
                        $('<img/>',{src:att.url,css:{maxWidth:'100%',height:'auto'}}).appendTo(preview);
                    }else{
                        $('<video/>',{src:att.url,controls:true,preload:'metadata',css:{maxWidth:'100%',height:'auto'}}).appendTo(preview);
                    }
                });
                frame.open();
            });
            $(document).on('click', '#wcv_remove_video', function(e){
                e.preventDefault();
                $('#wcv_video_url').val('');
                $('#wcv_video_attachment_id').val('');
                $('#wcv_preview').hide().empty();
            });
        })(jQuery);
        </script>
        <?php
    }
    public function save_meta($post_id, $post) {
        if (!isset($_POST['wcv_video_nonce']) || !wp_verify_nonce($_POST['wcv_video_nonce'], 'wcv_save_video_meta')) return;
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
        if (!current_user_can('edit_product', $post_id)) return;
        $att_id = isset($_POST['wcv_video_attachment_id']) ? (int) $_POST['wcv_video_attachment_id'] : 0;
        if ($att_id) {
            $mime = get_post_mime_type($att_id);
            if (!in_array($mime, ['video/mp4','video/webm','image/gif'], true)) {
                return;
            }
            update_post_meta($post_id, self::META_KEY_ID, $att_id);
        } else {
            delete_post_meta($post_id, self::META_KEY_ID);
        }
    }
    // ============== FRONT-END (CSS/JS) ==============
    public function frontend_styles() {
        $css = '
        .wcv-video-wrapper video.wcv-video{width:100%;height:auto;display:block;}
        .wcv-video-wrapper img{max-width:100%;height:auto;display:block;}
        .wcv-video-wrapper{position:relative;}
        /* Catálogo/listagem */
        .wcv-video-thumb-wrapper{display:block;position:relative;overflow:hidden;}
        .wcv-video-thumb-wrapper video.wcv-loop-video{
            width:100%;height:100%;display:block;object-fit:cover;background:#000;
        }
        ';
        wp_register_style('wcv-capa-video', false);
        wp_enqueue_style('wcv-capa-video');
        wp_add_inline_style('wcv-capa-video', $css);
    }
    public function frontend_scripts() {
        // Carrega o JS apenas nas páginas de listagem (loja/categorias/tags/atributos/busca de produtos)
        if (!(is_post_type_archive('product') || is_shop() || is_product_taxonomy() || is_product_category() || is_product_tag() || (function_exists('is_product') && !is_product() && is_search()))) {
            return;
        }
        wp_register_script('wcv-capa-video-js', '', [], false, true);
        wp_enqueue_script('wcv-capa-video-js');
        $js = "
        (function(){
            var vids = document.querySelectorAll('video.wcv-loop-video');
            if(!vids.length) return;
            function pauseReset(v){
                v.pause();
                try{ v.currentTime = 0; }catch(e){}
            }
            if('IntersectionObserver' in window){
                var io = new IntersectionObserver(function(entries){
                    entries.forEach(function(entry){
                        var v = entry.target;
                        var visible = entry.intersectionRatio >= 0.6;
                        if(visible){
                            v.play().catch(function(){});
                        }else{
                            pauseReset(v);
                        }
                    });
                }, {root:null, rootMargin:'0px', threshold:[0,0.6,1]});
                vids.forEach(function(v){ io.observe(v); });
            } else {
                // Fallback leve para navegadores sem IntersectionObserver
                function rectRatio(el){
                    var r = el.getBoundingClientRect();
                    var vw = window.innerWidth || document.documentElement.clientWidth;
                    var vh = window.innerHeight || document.documentElement.clientHeight;
                    var w = Math.max(0, Math.min(r.right, vw) - Math.max(r.left, 0));
                    var h = Math.max(0, Math.min(r.bottom, vh) - Math.max(r.top, 0));
                    var interArea = w * h;
                    var area = (r.width * r.height) || 1;
                    return interArea / area;
                }
                function onScroll(){
                    vids.forEach(function(v){
                        if(rectRatio(v) >= 0.6){
                            v.play().catch(function(){});
                        }else{
                            pauseReset(v);
                        }
                    });
                }
                ['scroll','resize','orientationchange'].forEach(function(evt){
                    window.addEventListener(evt, onScroll, {passive:true});
                });
                onScroll();
            }
        })();
        ";
        wp_add_inline_script('wcv-capa-video-js', $js);
    }
    private function get_video_attachment_id($product_id) {
        return (int) get_post_meta($product_id, self::META_KEY_ID, true);
    }
    // ============== FRONT-END: SINGLE PRODUCT ==============
    public function replace_main_image_html($html, $post_id) {
        if (!function_exists('wc_get_product')) return $html;
        $product = wc_get_product($post_id);
        if (!$product) return $html;
        $att_id = $this->get_video_attachment_id($product->get_id());
        if (!$att_id) return $html;
        $video_url = wp_get_attachment_url($att_id);
        if (!$video_url) return $html;
        $mime = get_post_mime_type($att_id);
        $poster_id = $product->get_image_id();
        $poster_url = $poster_id ? wp_get_attachment_image_url($poster_id, 'full') : '';
        if ($mime === 'image/gif') {
            $gif_html = wp_get_attachment_image($att_id, 'full', false, [
                'class' => 'wp-post-image skip-lazy',
                'alt'   => $product->get_name(),
            ]);
            return '<div class="woocommerce-product-gallery__image wcv-video-wrapper">'.$gif_html.'</div>';
        }
        $sources = '';
        if ($mime === 'video/mp4') {
            $sources .= '<source src="'.esc_url($video_url).'?v2" type="video/mp4">';
        } elseif ($mime === 'video/webm') {
            $sources .= '<source src="'.esc_url($video_url).'" type="video/webm">';
        } else {
            $sources .= '<source src="'.esc_url($video_url).'">';
        }
        $poster_attr = $poster_url ? ' poster="'.esc_url($poster_url).'"' : '';
        $video = '<video class="wp-post-image wcv-video skip-lazy" playsinline muted loop autoplay preload="metadata"'.$poster_attr.'>'.$sources.'</video>';
        return '<div class="woocommerce-product-gallery__image wcv-video-wrapper">'.$video.'</div>';
    }
    public function maybe_replace_featured_in_gallery($html, $attachment_id) {
        if (!is_product()) return $html;
        if (!function_exists('wc_get_product')) return $html;
        global $product;
        if (!$product) return $html;
        $video_att = $this->get_video_attachment_id($product->get_id());
        if (!$video_att) return $html;
        $featured_id = $product->get_image_id();
        if (!$featured_id || (int)$attachment_id !== (int)$featured_id) return $html;
        return $this->replace_main_image_html($html, $product->get_id());
    }
    // ============== FRONT-END: CATÁLOGO/LOOP ==============
    public function replace_loop_thumbnail($html, $size = null, $attr = [], $product = null) {
        if (!function_exists('wc_get_product')) return $html;
        if (!$product instanceof WC_Product) {
            $product = wc_get_product(get_the_ID());
        }
        if (!$product) return $html;
        $att_id = $this->get_video_attachment_id($product->get_id());
        if (!$att_id) return $html;
        $mime = get_post_mime_type($att_id);
        $video_url = wp_get_attachment_url($att_id);
        if (!$video_url) return $html;
        // Tamanho padrão do catálogo
        if (!$size) {
            $size = apply_filters('single_product_archive_thumbnail_size', 'woocommerce_thumbnail');
        }
        // GIF => renderizar como imagem normal
        if ($mime === 'image/gif') {
            return wp_get_attachment_image($att_id, $size, false, [
                'class' => 'attachment-woocommerce_thumbnail size-woocommerce_thumbnail skip-lazy',
                'alt'   => $product->get_name(),
            ]);
        }
        // Poster do vídeo: imagem destacada do produto (tamanho do thumb)
        $poster_id = $product->get_image_id();
        $poster_url = $poster_id ? wp_get_attachment_image_url($poster_id, $size) : '';
        $type = ($mime === 'video/mp4') ? 'video/mp4' : (($mime === 'video/webm') ? 'video/webm' : '');
        $poster_attr = $poster_url ? ' poster="'.esc_url($poster_url).'"' : '';
        // JS controla o autoplay com IntersectionObserver (60%)
        $video = '<video class="wcv-loop-video skip-lazy" muted playsinline loop preload="metadata"'.$poster_attr.'>'
               . '<source src="'.esc_url($video_url).'"'.($type ? ' type="'.esc_attr($type).'"' : '').'>'
               . '</video>';
        return '<span class="wcv-video-thumb-wrapper">'.$video.'</span>';
    }
}
add_action('plugins_loaded', function(){
    if (class_exists('WooCommerce')) {
        new WCV_Capa_Video_Flatsome();
    }
});

Comments

Add a Comment