Vídeo nativo para um produto

Neste tutorial vamos ver como implementar vídeos nativos na sua loja.

Para isso, vamos realizar ajustes na implementação atual de vídeos (YouTube/Vimeo), permitindo a reprodução de vídeos nativos e mantendo a compatibilidade com Swiper e Fancybox.

HTML

1. Vamos renomear o arquivo product-image-thumb.tpl para product-image-thumbs.tpl e realizar os seguintes ajustes:

Adicionamos a condição para verificar se o elemento é um vídeo, para que seja armazenado o ID do vídeo:

<a href="#" {% if media.isVideo %}data-video_id="{{ media.id }}"{% endif %}...>

Vamos adicionar a condição {% if media.isImage %} antes do elemento img para depois exibir o conteúdo de acordo com o tipo de mídia:

{% if media.isImage %}
   ...//Aqui trazer todo o código da imagem considerando a substituição de image por media.
{# Low quality img until final img is lazyloaded #}
<img src="{{ media | product_image_url('tiny') }}" class= "img-absolute img-absolute-centered blur-up visible-xs" 
  {% if media.alt %}alt="{{media.alt}}"{% endif %}/>
{% else %}
<div class="video-player-icon video-player-icon-small">
  <svg class="icon-inline icon-xs svg-icon-invert"><use xlink:href="#play"/></svg>
</div>

2. Dentro de product-image.tpl vamos substituir product.images_count por product.media_count e, dentro do elemento com a classe swiper-wrapper, vamos adicionar:

{% for media in product.media %}
  {% if media.isImage %}
   ...// Aqui o código igual, considerando a substituição de image por media.
{% else %}
  {% include 'snipplets/product/product-video.tpl' with {video_id:media.next_video, product_native_video: true} %}
{% endif %}

3. Em product-video.tpl, vamos atualizar a condição inicial {% if product.video_url %} para:

{% if product.video_url or product_native_video %}

Depois, vamos alterar as variáveis product.images_count para product.media_count.

No div com a classe product-video, vamos incluir as versões onde, por um lado, o vídeo é exibido no carrossel e, por outro, é preparada uma cópia oculta para o modal.
<div class="js-product-slide js-product-video-slide swiper-slide slider-slide {% if product_native_video %}
product-native-video-slide{% endif %} {% if home_main_product %}w-100{% endif %}"data-image-position="{{ video_index }}">
 ...
   <div class="product-video"
    {# Visible video inside slider #}
    {% include 'snipplets/video-item.tpl' with {video_id: video_id, product_modal_trigger: true,product_video: true, 
      product_native_video: product_native_video} %}
    {# Hidden video inside modal #}
    {% include 'snipplets/video-item.tpl' with {video_id: video_id, product_modal: true, product_video: true, 
      product_native_video: product_native_video} %}
   </div>

4. Em video-item.tpl, vamos alterar o ID do modal e as condições para exibir na página inicial, no primeiro elemento <a>:

<a id="trigger-video-modal-{{ media.id }}" href="#product-video-modal-{{ media.id }}" data-fancybox="product-gallery" class="js-play-button video-player {% if not home_main_product %}d-block  d-md-none{% endif %} {% if home_main_product %}d-none{% endif %}">

Vamos adicionar as classes condicionais dependendo se é um vídeo nativo:

<div class="{% if not thumb and not product_native_video %}js-video{% endif %} {% if product_video and not product_modal %}
js-video-product{% endif %} embed-responsive embed-responsive-16by9 visible-when-content-ready {% if product_native_video %}
product-native-video-container{% endif %}">

Vamos realizar o seguinte ajuste no elemento <a> para lidar com vídeo nativo:

<a href="javascript:void(0)" {% if product_native_video %}data-video_uid="{{ media.next_video }}"{% endif %} class="{% if product_native_video %}js-play-native-button{% else %}js-play-button{% endif %} video-player {% if product_modal_trigger and not home_main_product %}d-none d-md-block{% endif %}">

Na miniatura do vídeo (thumbnail) teremos:

{# Video thumbnail #}
  {% if product_native_video %}
  <div class="js-video-native-image w-100">
   <div data-video_uid="{{ media.uid }}"  class="js-external-video-iframe-container embed-responsive" data-video-color="{{ settings.primary_color | trim('#') }}" style="display:none;">
    {{ media.render | raw }}
   </div>
  <img data-video_uid="{{ media.uid }}" src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ media.thumbnail }}" class="video-image lazyload" alt="{{ 'Video de' | translate }} {% if template == 'product' %}{{ product.name }}{% else %}{{ store.name }}{% endif %}">
</div>
  {% else %}
  <div class="js-video-image">
      <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="" class="lazyload video-image fade-in" alt="{{ 'Video de' | translate }} {% if template == 'product' %}{{ product.name }}{% else %}{{ store.name }}{% endif %}" style="display: none;">
      <div class="placeholder-fade">
      </div>
 </div>
{% endif %}

CSS

Requisito:

Ter adicionadas no seu layout as helper classes. Você pode seguir este pequeno tutorial para fazê-lo (é apenas copiar e colar algumas classes, leva menos de 1 minuto).
Como neste exemplo usamos um slider com Swiper, precisamos adicionar o plugin. Para ver como fazer isso, você pode ler este artigo curto e depois continuar com este tutorial.

No arquivo style-critical.scss, vamos adicionar os seguintes estilos para contêineres e elementos de vídeo nativo:
.icon-inline {
 z-index: 1;
}

.video-player-icon-small {
  z-index: 10;
 }

.product-native-video-slide{
  height: auto;
}
.product-native-video-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  overflow: visible;
}

@media (min-width: 768px) {
...
/* //// Product detail */
.product-native-video-slide {
    height: 100%;
  }
}

JS

Dentro de store.js.tpl, vamos fazer as alterações onde definimos a lógica de inicialização e controle dos vídeos nativos.

Para isso, vamos substituir referências de product.images_count por product.media_count.

Depois vamos adicionar as funções initAllVideos() e pauseAllVideos():

{% set native_videos_enabled = false %}
    {% if template == 'product' and product.hasNativeVideos %}
        {% set native_videos_enabled = true %}
    {% endif %}
    {% if home_product_main %}
        {# on the home, if there is at least one featured product with native videos, we enable them #}
        {% for product in sections.featured.products %}
            {% if product.hasNativeVideos %}
                {% set native_videos_enabled = true %}
            {% endif %}
        {% endfor %}
    {% endif %}


{% if template == 'product' or home_product_main %} 

{% if native_videos_enabled %}
       var stream_videos = [];
            function initAllVideos(){
                jQueryNuvem(".js-external-video-iframe").each(function($el){
                    const player = Stream(document.getElementById($el.id));
                    stream_videos.push(player);
                });
            }
            initAllVideos();
            function pauseAllVideos(){
                stream_videos.forEach(function(player){
                    player.pause();
                });
            }
            jQueryNuvem(".js-play-native-button").on("click", function($el){
                pauseAllVideos();
                const link = jQueryNuvem(this);
                const id = jQueryNuvem(this).data("video_uid");
                const iframe = jQueryNuvem("#video-" + id);
                const image = jQueryNuvem("img[data-video_uid='" + id + "']");
                const parent = jQueryNuvem(this).parent(".embed-responsive-16by9");
                const container = jQueryNuvem("div[data-video_uid='" + id + "']");
                iframe.attr("src", iframe.data("src"));
                container.show();
                image.hide();
                link.hide().removeClass("d-md-block");
                parent.removeClass("embed-responsive-16by9");
            });
        {% endif %}


  var has_multiple_slides = false;
        {% if template == 'product' and (product.media_count > 1 or video_url) %}

Dentro da configuração do Swiper (Product-slider ou dentro de createSwiper):

Vamos adicionar a função pauseAllVideos() no evento slideChange, para evitar que um vídeo continue reproduzindo ao trocar de slide.

{% if native_videos_enabled %}
     slideChange : function () {
     pauseAllVideos();
    },
{% endif %}

Depois vamos alterar em LS.registerOnChangeVariant, dentro do bloco {% if has_multiple_slides %}, adicionando a condição para detectar e abrir o vídeo correspondente:

var video_id = jQueryNuvem(e.currentTarget).data("video_id");
       if(video_id){
            jQueryNuvem('#trigger-video-modal-' + video_id).trigger('click');
            return;
       }

Também vamos ajustar a condição dentro do bloco “on”:

// Antes:
},
{% if product.video_url and template == 'product' %}
    on: {
        init: function () {
            if (window.innerWidth < 768) {
                ...
            }
        }
    }
{% endif %}

Anteriormente, a condição que controlava a inicialização do vídeo ({% if product.video_url and template == 'product' %}) ficava fora do bloco on: na configuração do Swiper.

//Ahora:
},
on: {
    {% if product.video_url and template == 'product' %}
        init: function () {
            if (window.innerWidth < 768) {
                ...
            }
        },
    {% endif %}

Agora ela foi movida para dentro do bloco on, o que permite definir corretamente os eventos do carrossel e adicionar novos comportamentos, como pausar os vídeos nativos quando o usuário navega entre os slides.

Em external.js.tpl, vamos adicionar o código do serviço interno que permite reproduzir e controlar os vídeos nativos dentro do site.

{% set home_product_main = template == 'home' and sections.featured.products %}


{% set native_videos_enabled = false %}
{% if template == 'product' and product.hasNativeVideos %}
    {% set native_videos_enabled = true %}
{% endif %}
{% if home_product_main %}
    {# on the home, if there is at least one featured product with native videos, we enable them #}
    {% for product in sections.featured.products %}
        {% if product.hasNativeVideos %}
            {% set native_videos_enabled = true %}
        {% endif %}
    {% endfor %}
{% endif %}


{% if native_videos_enabled %}
    {% raw %}
     // Copiar aqui o código do repositório a seguir
      {% endraw %}
{% endif %}

Activação

No administrador, no formulário do produto, na seção Fotos e vídeos, podemos enviar o vídeo, respeitando o tamanho máximo e o formato especificado.

Depois de enviar e salvar o vídeo no admin, ele já pode ser visualizado na loja.