Vídeo Interativo
Vídeo com pausas programadas que exibem perguntas, tarefas ou reflexões. O aprendiz responde antes de continuar, transformando a assistência passiva em aprendizagem ativa.
Experimente
Objetivos SMART: como definir metas claras
Código-fonte
Dados de exemplo
O vídeo, o segundo onde a reprodução pausa e a pergunta que aparece nesse ponto.
| 1 |
<?php
|
| 2 |
$titulo = 'Como as Nuvens se Formam';
|
| 3 |
$pausaSegundos = 8;
|
| 4 |
$pergunta = 'O que faz o vapor de água virar gotículas visíveis?';
|
| 5 |
$opcoes = [
|
| 6 |
['letra' => 'A', 'texto' => 'O ar esfria e o vapor condensa', 'correta' => true],
|
| 7 |
['letra' => 'B', 'texto' => 'O vento sopra mais forte', 'correta' => false],
|
| 8 |
['letra' => 'C', 'texto' => 'A pressão atmosférica aumenta', 'correta' => false],
|
| 9 |
];
|
| 10 |
?>
|
Player com controles próprios
O <video> não tem o atributo "controls" — sem ele, o navegador não desenha nenhum controle nativo, e tudo sai pelos botões abaixo.
| 1 |
<div class="vid-demo" data-tipo="video-pausa">
|
| 2 |
|
| 3 |
<div class="vid-cabecalho">
|
| 4 |
<p><?= htmlspecialchars($titulo) ?></p>
|
| 5 |
</div>
|
| 6 |
|
| 7 |
<div class="vid-player">
|
| 8 |
<!-- Troque pelo caminho do seu vídeo -->
|
| 9 |
<video class="vid-elemento" src="seu-video.mp4" preload="metadata"></video>
|
| 10 |
</div>
|
| 11 |
|
| 12 |
<div class="vid-trilha-linha">
|
| 13 |
<span class="vid-tempo">0:00</span>
|
| 14 |
<div class="vid-trilha">
|
| 15 |
<div class="vid-barra"></div>
|
| 16 |
<div class="vid-marcador" style="left: 40%"></div>
|
| 17 |
</div>
|
| 18 |
<span class="vid-duracao">0:20</span>
|
| 19 |
</div>
|
| 20 |
|
| 21 |
<div class="vid-controles">
|
| 22 |
<button type="button" class="vid-play-pause">Reproduzir</button>
|
| 23 |
</div>
|
Pergunta programada
Some por padrão; aparece quando o vídeo cruza o segundo configurado, com a reprodução já pausada.
| 1 |
<div class="vid-pergunta" hidden data-segundos="<?= $pausaSegundos ?>">
|
| 2 |
<p class="vid-pergunta-texto"><?= htmlspecialchars($pergunta) ?></p>
|
| 3 |
<div class="vid-opcoes">
|
| 4 |
<?php foreach ($opcoes as $opcao): ?>
|
| 5 |
<button type="button" class="vid-opcao" data-correta="<?= $opcao['correta'] ? 'true' : 'false' ?>">
|
| 6 |
<?= $opcao['letra'] ?> — <?= htmlspecialchars($opcao['texto']) ?>
|
| 7 |
</button>
|
| 8 |
<?php endforeach; ?>
|
| 9 |
</div>
|
| 10 |
<p class="vid-feedback" hidden></p>
|
| 11 |
<button type="button" class="vid-continuar" hidden>Continuar vídeo</button>
|
| 12 |
</div>
|
| 13 |
|
| 14 |
</div>
|
Card e cabeçalho
Contêiner geral e a caixa de título centralizada.
| 1 |
.vid-demo {
|
| 2 |
max-width: 560px;
|
| 3 |
border: 1px solid #e2e8f0;
|
| 4 |
border-radius: 16px;
|
| 5 |
background: #fff;
|
| 6 |
font-family: sans-serif;
|
| 7 |
overflow: hidden;
|
| 8 |
}
|
| 9 |
|
| 10 |
.vid-cabecalho {
|
| 11 |
padding: 20px 24px;
|
| 12 |
border-bottom: 1px solid #cbd5e1;
|
| 13 |
background: rgba(241, 245, 249, .6);
|
| 14 |
text-align: center;
|
| 15 |
}
|
| 16 |
|
| 17 |
.vid-cabecalho p {
|
| 18 |
margin: 0;
|
| 19 |
font-weight: 700;
|
| 20 |
font-size: 18px;
|
| 21 |
color: #0f172a;
|
| 22 |
}
|
Player e trilha
O vídeo preenche a área 16:9; a trilha abaixo mostra o progresso real e o marcador da pergunta.
| 1 |
.vid-player {
|
| 2 |
position: relative;
|
| 3 |
aspect-ratio: 16 / 9;
|
| 4 |
background: #000;
|
| 5 |
}
|
| 6 |
|
| 7 |
.vid-elemento {
|
| 8 |
width: 100%;
|
| 9 |
height: 100%;
|
| 10 |
display: block;
|
| 11 |
}
|
| 12 |
|
| 13 |
.vid-trilha-linha {
|
| 14 |
display: flex;
|
| 15 |
align-items: center;
|
| 16 |
gap: 12px;
|
| 17 |
padding: 12px 16px 4px;
|
| 18 |
font-size: 12px;
|
| 19 |
font-family: monospace;
|
| 20 |
color: #64748b;
|
| 21 |
}
|
| 22 |
|
| 23 |
.vid-trilha {
|
| 24 |
position: relative;
|
| 25 |
flex: 1;
|
| 26 |
height: 6px;
|
| 27 |
border-radius: 999px;
|
| 28 |
background: #e2e8f0;
|
| 29 |
cursor: pointer;
|
| 30 |
}
|
| 31 |
|
| 32 |
.vid-barra {
|
| 33 |
height: 100%;
|
| 34 |
width: 0%;
|
| 35 |
border-radius: 999px;
|
| 36 |
background: #6366f1;
|
| 37 |
}
|
| 38 |
|
| 39 |
.vid-marcador {
|
| 40 |
position: absolute;
|
| 41 |
top: 50%;
|
| 42 |
width: 10px;
|
| 43 |
height: 10px;
|
| 44 |
transform: translate(-50%, -50%);
|
| 45 |
border-radius: 999px;
|
| 46 |
background: #f59e0b;
|
| 47 |
border: 2px solid #fff;
|
| 48 |
}
|
Controles e pergunta
Um botão só alterna reproduzir/pausar; a pergunta some por padrão e ocupa a largura toda quando aparece.
| 1 |
.vid-controles {
|
| 2 |
padding: 4px 16px 16px;
|
| 3 |
text-align: center;
|
| 4 |
}
|
| 5 |
|
| 6 |
.vid-play-pause {
|
| 7 |
padding: 10px 24px;
|
| 8 |
border: none;
|
| 9 |
border-radius: 999px;
|
| 10 |
background: #6366f1;
|
| 11 |
color: #fff;
|
| 12 |
font: inherit;
|
| 13 |
font-weight: 600;
|
| 14 |
cursor: pointer;
|
| 15 |
}
|
| 16 |
|
| 17 |
.vid-pergunta {
|
| 18 |
padding: 16px 20px 20px;
|
| 19 |
border-top: 1px solid #e2e8f0;
|
| 20 |
}
|
| 21 |
|
| 22 |
.vid-pergunta-texto {
|
| 23 |
margin: 0 0 12px;
|
| 24 |
font-weight: 600;
|
| 25 |
color: #0f172a;
|
| 26 |
}
|
| 27 |
|
| 28 |
.vid-opcoes {
|
| 29 |
display: flex;
|
| 30 |
flex-direction: column;
|
| 31 |
gap: 8px;
|
| 32 |
margin-bottom: 12px;
|
| 33 |
}
|
| 34 |
|
| 35 |
.vid-opcao {
|
| 36 |
padding: 10px 14px;
|
| 37 |
border: 1px solid #cbd5e1;
|
| 38 |
border-radius: 10px;
|
| 39 |
background: #f8fafc;
|
| 40 |
text-align: left;
|
| 41 |
font: inherit;
|
| 42 |
font-size: 14px;
|
| 43 |
color: #334155;
|
| 44 |
cursor: pointer;
|
| 45 |
}
|
| 46 |
|
| 47 |
.vid-opcao:disabled { cursor: not-allowed; }
|
| 48 |
|
| 49 |
.vid-feedback {
|
| 50 |
margin: 0 0 12px;
|
| 51 |
font-weight: 600;
|
| 52 |
color: #4338ca;
|
| 53 |
}
|
| 54 |
|
| 55 |
.vid-continuar {
|
| 56 |
display: block;
|
| 57 |
width: 100%;
|
| 58 |
padding: 12px 16px;
|
| 59 |
border: none;
|
| 60 |
border-radius: 10px;
|
| 61 |
background: #4f46e5;
|
| 62 |
color: #fff;
|
| 63 |
font: inherit;
|
| 64 |
font-weight: 600;
|
| 65 |
cursor: pointer;
|
| 66 |
}
|
Controlar o vídeo sem os botões nativos
play(), pause() e currentTime já vêm de graça no elemento <video> — não precisa de nenhuma biblioteca.
| 1 |
document.addEventListener('DOMContentLoaded', function () {
|
| 2 |
var demo = document.querySelector('[data-tipo="video-pausa"]');
|
| 3 |
var video = demo.querySelector('.vid-elemento');
|
| 4 |
var playPauseBtn = demo.querySelector('.vid-play-pause');
|
| 5 |
var trilha = demo.querySelector('.vid-trilha');
|
| 6 |
var barra = demo.querySelector('.vid-barra');
|
| 7 |
var tempo = demo.querySelector('.vid-tempo');
|
| 8 |
var pergunta = demo.querySelector('.vid-pergunta');
|
| 9 |
var pausaSegundos = parseInt(pergunta.dataset.segundos, 10);
|
| 10 |
var opcoes = demo.querySelectorAll('.vid-opcao');
|
| 11 |
var feedback = demo.querySelector('.vid-feedback');
|
| 12 |
var continuar = demo.querySelector('.vid-continuar');
|
| 13 |
var jaPausou = false;
|
| 14 |
|
| 15 |
function formatarTempo(segundos) {
|
| 16 |
segundos = Math.max(0, Math.round(segundos));
|
| 17 |
return Math.floor(segundos / 60) + ':' + String(segundos % 60).padStart(2, '0');
|
| 18 |
}
|
Progresso e a pausa programada
"timeupdate" dispara continuamente enquanto o vídeo toca — é onde se checa se já é hora de pausar pra pergunta.
| 1 |
video.addEventListener('timeupdate', function () {
|
| 2 |
var duracao = video.duration || 0;
|
| 3 |
if (duracao > 0) barra.style.width = (video.currentTime / duracao * 100) + '%';
|
| 4 |
tempo.textContent = formatarTempo(video.currentTime);
|
| 5 |
|
| 6 |
if (!jaPausou && video.currentTime >= pausaSegundos) {
|
| 7 |
jaPausou = true;
|
| 8 |
video.pause();
|
| 9 |
pergunta.hidden = false;
|
| 10 |
}
|
| 11 |
});
|
| 12 |
|
| 13 |
playPauseBtn.addEventListener('click', function () {
|
| 14 |
if (video.paused) { video.play(); playPauseBtn.textContent = 'Pausar'; }
|
| 15 |
else { video.pause(); playPauseBtn.textContent = 'Reproduzir'; }
|
| 16 |
});
|
| 17 |
|
| 18 |
trilha.addEventListener('click', function (evento) {
|
| 19 |
var rect = trilha.getBoundingClientRect();
|
| 20 |
var razao = Math.min(1, Math.max(0, (evento.clientX - rect.left) / rect.width));
|
| 21 |
video.currentTime = razao * (video.duration || 0);
|
| 22 |
});
|
Responder e continuar
A trava é simples aqui: só existe um jeito de retomar (o botão "Continuar"), então não tem como furar respondendo e clicando em outro lugar.
| 1 |
opcoes.forEach(function (opcao) {
|
| 2 |
opcao.addEventListener('click', function () {
|
| 3 |
var correta = opcao.dataset.correta === 'true';
|
| 4 |
opcoes.forEach(function (o) { o.disabled = true; });
|
| 5 |
feedback.hidden = false;
|
| 6 |
feedback.textContent = correta ? 'Correto!' : 'Não foi dessa vez.';
|
| 7 |
continuar.hidden = false;
|
| 8 |
});
|
| 9 |
});
|
| 10 |
|
| 11 |
continuar.addEventListener('click', function () {
|
| 12 |
pergunta.hidden = true;
|
| 13 |
video.play();
|
| 14 |
playPauseBtn.textContent = 'Pausar';
|
| 15 |
});
|