Teste de Visão Online:
O "Teste de Visão Online" é uma ferramenta interativa e acessível projetada para avaliar rapidamente aspectos fundamentais da sua visão diretamente no conforto da sua casa, sem a necessidade de visitas presenciais a uma clínica oftalmológica. Este teste simula de forma simples uma análise inicial de como sua visão está se comportando em relação à identificação de letras e cores.
Como Funciona:
1. Geração Aleatória de Letras e Cores:
O teste apresenta letras aleatórias do alfabeto (de A a Z), geradas de maneira dinâmica, que aparecem na tela em três cores possíveis: vermelho, amarelo e verde. A cada nova rodada, uma combinação de letra e cor é exibida, e o usuário deve identificá-las corretamente.
2. Entrada de Respostas:
O usuário deve inserir a letra que vê no campo de entrada e selecionar a cor correspondente a partir de opções pré-definidas (vermelho, amarelo ou verde). O sistema verifica se a letra e a cor estão corretas, fornecendo feedback imediato após cada tentativa.
3. Modo Cronometrado e Modo de Treinamento:
Modo Cronometrado: Se o usuário optar por este modo, ele terá um tempo limitado para responder a cada letra apresentada. O temporizador conta o tempo restante para cada rodada e avisa quando o tempo se esgotar, forçando a submissão automática da resposta.
Modo de Treinamento: Este modo permite que o usuário pratique sem pressão de tempo, ideal para treinar reconhecimento de letras e cores sem o cronômetro.
4. Níveis de Dificuldade:
O teste oferece múltiplos níveis de dificuldade que ajustam o tamanho da letra e o grau de desfoque:
Fácil: Letras grandes e nítidas.
Médio: Letras um pouco menores e com leve desfoque.
Difícil: Letras menores com desfoque mais acentuado.
Muito Difícil: Letras pequenas e altamente desfocadas, desafiando a acuidade visual do usuário.
5. Pontuação e Feedback Imediato:
Cada resposta recebe feedback instantâneo: se correta, o usuário ouve um som positivo e vê uma mensagem de acerto; se incorreta, um som de erro é tocado e o sistema exibe a resposta correta, informando qual era a letra e cor exibida.
A pontuação é atualizada em tempo real, mostrando quantas respostas corretas e incorretas o usuário teve ao longo do teste.
6. Resumo Final e Reinício:
Após completar 10 perguntas, o usuário é apresentado a um resumo final que exibe o número total de acertos e erros.
O sistema bloqueia novas tentativas após as 10 perguntas, forçando o usuário a clicar no botão de Reiniciar Teste para começar uma nova rodada de avaliação.
7. Funcionalidades Extras:
Salvar como PDF: Após concluir o teste, o usuário tem a opção de salvar os resultados e o resumo do teste em formato PDF.
Compartilhamento em Redes Sociais: Com botões integrados, o usuário pode compartilhar os resultados diretamente no Facebook, Twitter ou WhatsApp.
Público-Alvo:
O "Teste de Visão Online" é ideal para qualquer pessoa que deseja verificar rapidamente sua acuidade visual, avaliar sua capacidade de reconhecimento de cores ou treinar sua visão de uma maneira simples e divertida. Ele pode ser usado tanto por pessoas que suspeitam de problemas na visão quanto por quem busca manter suas habilidades visuais em dia.
Aviso!
Este teste não substitui uma avaliação oftalmológica profissional. Para diagnósticos mais precisos, é recomendado que o usuário consulte um especialista.
Veja o Teste de Visão Online em funcionamento neste link. Teste de Visão Online.
Veja o vídeo no YouTube:
Começando o Tutorial:
1° Passo: Abra seu VS Code, ou qualquer IDE da sua preferência e crie três pastas com os nomes... index.html, style.css e script.js.
Logo em seguida copie o código html abaixo e cole na pasta "index.html".
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Teste de Visão Online</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.2/html2pdf.bundle.min.js"></script>
</head>
<body>
<div class="container">
<h1>Teste de Visão Online</h1>
<p id="instructions">Digite a letra que você vê e escolha a cor ao lado:</p>
<div class="test-area">
<div id="letter" class="letter">A</div>
<div class="color-selection">
<label>
<input type="radio" name="color" value="red"> Vermelho
</label>
<label>
<input type="radio" name="color" value="yellow"> Amarelo
</label>
<label>
<input type="radio" name="color" value="green"> Verde
</label>
</div>
</div>
<input type="text" id="userInput" placeholder="Digite a letra" maxlength="1">
<div class="button-area">
<button onclick="submitAnswer()">Submeter</button>
<button onclick="nextLetter()">Próxima Letra</button>
</div>
<p id="feedback"></p>
<div class="settings">
<div class="level">
<label for="difficulty">Selecione a dificuldade:</label>
<select id="difficulty" onchange="setDifficulty()">
<option value="easy">Fácil</option>
<option value="medium">Médio</option>
<option value="hard">Difícil</option>
<option value="veryHard">Muito Difícil</option>
</select>
</div>
<div class="mode">
<label for="mode">Modo:</label>
<select id="mode" onchange="setMode()">
<option value="practice">Treinamento</option>
<option value="timed">Cronometrado</option>
</select>
</div>
<div class="time">
<label for="timeSelect">Tempo por letra (s):</label>
<input type="range" id="timeSelect" min="10" max="20" value="10" onchange="updateTimeDisplay()">
<span id="timeDisplay">10s</span>
</div>
</div>
<p id="timer">Tempo restante: 10s</p>
<p id="score">Pontuação: 0</p>
<div class="summary" style="display: none;">
<h3>Resumo Final</h3>
<p id="correctAnswers">Respostas Corretas: 0</p>
<p id="incorrectAnswers">Respostas Incorretas: 0</p>
<button onclick="restartTest()">Reiniciar Teste</button>
</div>
<div class="share-buttons">
<h3>Compartilhe:</h3>
<button onclick="shareOnFacebook()"><i class="fab fa-facebook"></i> Facebook</button>
<button onclick="shareOnTwitter()"><i class="fab fa-twitter"></i> Twitter</button>
<button onclick="shareOnWhatsApp()"><i class="fab fa-whatsapp"></i> WhatsApp</button>
</div>
<div class="pdf-button">
<button onclick="saveAsPDF()"><i class="fas fa-file-pdf"></i> Salvar como PDF</button>
</div>
<audio id="correctSound" src="https://github.com/Ninja1375/Testes/raw/main/correct.mp3"></audio>
<audio id="incorrectSound" src="https://github.com/Ninja1375/Testes/raw/main/incorrect.mp3"></audio>
</div>
<script src="script.js" defer></script>
</body>
</html>
2° Passo: Copie o código abaixo e cole na pasta "style.css".
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
text-align: center;
margin: 0;
padding: 0;
}
.container {
margin-top: 20px;
padding: 20px;
}
h1 {
color: #333;
}
.test-area {
display: flex;
justify-content: center;
align-items: center;
margin: 20px 0;
flex-wrap: wrap;
}
#letter {
font-size: 100px;
margin-right: 30px;
color: #000;
border: 2px solid #333;
display: none;
padding: 20px;
transition: filter 0.3s ease, color 0.3s ease;
}
.color-selection {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.color-selection label {
display: flex;
align-items: center;
margin: 10px 0;
}
.color-selection input[type="radio"] {
margin-right: 10px;
}
input[type="text"] {
padding: 10px;
font-size: 20px;
width: 180px;
margin: 20px auto;
display: block;
text-align: center;
box-sizing: border-box;
}
.button-area {
margin-top: 20px;
}
button {
padding: 10px 20px;
font-size: 16px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin: 5px;
}
button:hover {
background-color: #0056b3;
}
/* Centralização e Alinhamento das Configurações */
.settings {
margin-top: 30px;
display: flex;
flex-direction: column;
align-items: center;
}
.level, .mode, .time {
display: flex;
align-items: center;
justify-content: flex-start;
margin-top: 20px;
width: 100%;
max-width: 400px;
}
.level label, .mode label, .time label {
margin-right: 10px;
flex: 1;
text-align: left;
}
.time input[type="range"] {
margin-left: 10px;
flex: 2;
}
#feedback {
margin-top: 20px;
font-size: 20px;
font-weight: bold;
}
#timer, #score, #timeDisplay {
margin-top: 20px;
font-size: 24px;
}
.summary {
display: none;
margin-top: 30px;
}
.summary h3 {
font-size: 24px;
}
.summary p {
font-size: 20px;
}
.share-buttons {
margin-top: 20px;
}
.share-buttons button {
display: inline-flex;
align-items: center;
padding: 10px 20px;
font-size: 16px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin: 5px;
transition: background-color 0.3s;
}
.share-buttons button i {
margin-right: 8px;
}
.share-buttons button:hover {
background-color: #0056b3;
}
.pdf-button {
margin-top: 20px;
}
.pdf-button button {
display: inline-flex;
align-items: center;
padding: 10px 20px;
font-size: 16px;
background-color: #FF0000;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.pdf-button button:hover {
background-color: #cc0000;
}
/* Regras para Dispositivos Móveis */
@media (max-width: 600px) {
.test-area {
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
}
#letter {
font-size: 80px;
margin: 0;
padding: 15px;
flex: 1;
}
.color-selection {
margin-left: 20px;
flex: 1;
}
input[type="text"] {
width: 100%;
max-width: 300px;
font-size: 18px;
}
button {
font-size: 14px;
padding: 8px 16px;
}
#timer, #score {
font-size: 20px;
}
.settings {
align-items: center;
}
.level, .mode, .time {
justify-content: flex-start;
width: 100%;
}
}
3° Passo: Copie o código abaixo e cole na pasta "script.js".
// Variáveis globais para o teste de visão
let correctAnswers = 0;
let incorrectAnswers = 0;
let currentLetter = '';
let currentColor = '';
let timeLeft = 10;
let timerInterval;
let mode = 'practice'; // Modo padrão
let isTimedMode = false;
let totalQuestions = 10; // Definimos o número de perguntas para o resumo final
let questionsAnswered = 0;
let testEnded = false; // Flag para impedir novas respostas até reiniciar
// Função para compartilhar no Facebook
function shareOnFacebook() {
const url = encodeURIComponent(window.location.href);
window.open(`https://www.facebook.com/sharer/sharer.php?u=${url}`, '_blank');
}
// Função para compartilhar no Twitter
function shareOnTwitter() {
const url = encodeURIComponent(window.location.href);
const text = encodeURIComponent('Confira este teste de visão!');
window.open(`https://twitter.com/intent/tweet?url=${url}&text=${text}`, '_blank');
}
// Função para compartilhar no WhatsApp
function shareOnWhatsApp() {
const url = encodeURIComponent(window.location.href);
const text = encodeURIComponent('Confira este teste de visão!');
window.open(`https://api.whatsapp.com/send?text=${text}%20${url}`, '_blank');
}
// Função para salvar como PDF usando a biblioteca html2pdf
function saveAsPDF() {
const element = document.querySelector('.container');
html2pdf(element, {
margin: 1,
filename: 'teste_visao.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2 },
jsPDF: { unit: 'in', format: 'letter', orientation: 'portrait' }
});
}
// Função para gerar uma nova letra e cor aleatórias
function nextLetter() {
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const colors = ['red', 'yellow', 'green'];
currentLetter = letters.charAt(Math.floor(Math.random() * letters.length));
currentColor = colors[Math.floor(Math.random() * colors.length)];
const letterElement = document.getElementById('letter');
letterElement.textContent = currentLetter;
letterElement.style.color = currentColor;
// Exibe a div da letra
letterElement.style.display = 'block'; // Torna visível a div da letra
// Reinicia o temporizador no modo cronometrado
if (isTimedMode) {
timeLeft = document.getElementById('timeSelect').value;
document.getElementById('timer').textContent = `Tempo restante: ${timeLeft}s`;
clearInterval(timerInterval);
timerInterval = setInterval(countdown, 1000);
}
}
// Função para verificar a resposta do usuário
function submitAnswer() {
if (testEnded) return; // Impede a continuação após 10 perguntas
const userInput = document.getElementById('userInput').value.toUpperCase();
const feedbackElement = document.getElementById('feedback');
// Verifica se o usuário escolheu uma cor
const selectedColor = document.querySelector('input[name="color"]:checked');
if (!selectedColor) {
feedbackElement.textContent = 'Por favor, selecione uma cor.';
feedbackElement.style.color = 'orange';
return;
}
const userColor = selectedColor.value;
// Verificação da resposta da letra e da cor
if (userInput === currentLetter && userColor === currentColor) {
feedbackElement.textContent = 'Correto!';
feedbackElement.style.color = 'green';
document.getElementById('correctSound').play();
correctAnswers++;
} else {
feedbackElement.textContent = `Incorreto! A letra era ${currentLetter} e a cor era ${currentColor}.`;
feedbackElement.style.color = 'red';
document.getElementById('incorrectSound').play();
incorrectAnswers++;
}
questionsAnswered++;
// Verifica se o número de perguntas foi atingido
if (questionsAnswered >= totalQuestions) {
displaySummary();
testEnded = true; // Impede novas respostas
} else {
// Limpa o campo de input e prepara a próxima letra
document.getElementById('userInput').value = '';
clearInterval(timerInterval); // Para o temporizador
nextLetter(); // Gera a próxima letra e cor
}
// Atualiza a pontuação
document.getElementById('score').textContent = `Pontuação: ${correctAnswers} corretas, ${incorrectAnswers} incorretas`;
}
// Função para exibir o resumo final
function displaySummary() {
document.querySelector('.summary').style.display = 'block';
document.getElementById('correctAnswers').textContent = `Respostas Corretas: ${correctAnswers}`;
document.getElementById('incorrectAnswers').textContent = `Respostas Incorretas: ${incorrectAnswers}`;
document.getElementById('feedback').textContent = '';
clearInterval(timerInterval); // Para o temporizador
}
// Função para definir a dificuldade
function setDifficulty() {
const difficulty = document.getElementById('difficulty').value;
const letterElement = document.getElementById('letter');
// Ajusta o tamanho da letra e o desfoque com base na dificuldade
switch (difficulty) {
case 'easy':
letterElement.style.fontSize = '100px';
letterElement.style.filter = 'blur(0px)';
break;
case 'medium':
letterElement.style.fontSize = '70px';
letterElement.style.filter = 'blur(2px)';
break;
case 'hard':
letterElement.style.fontSize = '50px';
letterElement.style.filter = 'blur(4px)';
break;
case 'veryHard':
letterElement.style.fontSize = '40px';
letterElement.style.filter = 'blur(6px)';
break;
}
}
// Função para definir o modo de jogo
function setMode() {
mode = document.getElementById('mode').value;
isTimedMode = mode === 'timed'; // Verifica se o modo é cronometrado
if (!isTimedMode) {
clearInterval(timerInterval); // Para o temporizador no modo de treinamento
document.getElementById('timer').textContent = 'Modo de Treinamento';
} else {
nextLetter(); // Reinicia a letra e o temporizador no modo cronometrado
}
}
// Função para atualizar o display do tempo por letra
function updateTimeDisplay() {
const time = document.getElementById('timeSelect').value;
document.getElementById('timeDisplay').textContent = `${time}s`;
}
// Função para contar o tempo no modo cronometrado
function countdown() {
timeLeft--;
document.getElementById('timer').textContent = `Tempo restante: ${timeLeft}s`;
if (timeLeft <= 0) {
clearInterval(timerInterval);
submitAnswer(); // Submete a resposta automaticamente quando o tempo acaba
}
}
// Função para reiniciar o teste
function restartTest() {
correctAnswers = 0;
incorrectAnswers = 0;
questionsAnswered = 0;
testEnded = false; // Permite que o teste continue após reiniciar
document.getElementById('score').textContent = 'Pontuação: 0 corretas, 0 incorretas';
document.getElementById('feedback').textContent = '';
document.querySelector('.summary').style.display = 'none';
nextLetter(); // Reinicia o teste com uma nova letra e cor
}
// Inicializa o teste assim que a página carrega, gerando a primeira letra e cor aleatórias sem atraso
window.onload = function() {
nextLetter(); // Chama a função nextLetter() ao carregar a página
};
4° Passo: Testar o Projeto!
Agora, com os três arquivos (index.html, style.css, e script.js) criados, você pode abrir o index.html no seu navegador e ver seu projeto funcionando perfeitamente!
Se preferir os códigos estão no meu Repositório no GitHub.
Comentários
Postar um comentário
Obrigado pelo seu feedback!