Skip to content

Igorcbraz/Calculadora

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Calculadora completa com comandos de voz, atalhos de teclado e temas adaptáveis utilizando apenas JavaScript puro

GitHub Stars Forks Netlify Status MIT License Issues Last Commit Contributors

Logo

Sobre

Este projeto foi criado como parte de um desafio, com o objetivo de desenvolver uma calculadora funcional e responsiva. Durante o processo, o escopo foi ampliado para incluir melhorias na arquitetura, acessibilidade e personalização, transformando o desafio em uma aplicação moderna e repleta de funcionalidades usando apenas html, css e javascript evitando ao máximo libs externas.


Desafio inicial feito por Frontend Mentor

Tabela de Conteúdos

Funcionalidades

  • Realizar operações matemáticas básicas (adição, subtração, multiplicação, divisão)
  • Suporte a comandos de voz para facilitar a interação
  • Temas personalizados para a interface (utilizando prefer-color-scheme)
  • Responsividade para diferentes tamanhos de tela
  • Integração com comandos via teclado
  • Shortcuts dinâmicos para troca de temas
  • Guia automático ensinando a utilizar a calculadora

Web Speech API

Para desenvolver o recurso de suporte a comando de voz, sem adicionar bibliotecas externas ao projeto, foi utilizado o recurso Web Speech API

Essa funcionalidade permite utilizar o recurso de áudio do próprio navegador e receber um ou mais resultados do que foi falado, em uma string.

No projeto, dentro da pasta JS temos o arquivo chamado Speak.js com a implementação necessária para a utilização dos comandos de voz, nele primeiro iremos começar a utilizar a web speech api na função setup:

if (!('webkitSpeechRecognition' in window)) { this.#startBtn.disabled = true console.error('Speech recognition not available') return } this.#recognition = new webkitSpeechRecognition() this.#recognition.continuous = true this.#recognition.lang = 'pt-BR' this.#recognition.interimResults = true this.addListeners() // Adiciona o toggle de escutar ou não o usuário

Após a configuração, podemos começar a processar a fala e tomar algumas ações com o que foi dito, na função start:

this.#recognition.onresult = (event) => { const results = Object.values(event.results) if (results.length) this.#startBtn.classList.add('listening') for (const result of results) { const { transcript } = result[0] const { isFinal } = result if (isFinal) this.#calculator.executeVoiceCommand(transcript.trim(), this.getVoiceActions()) } } this.#recognition.start()

Nesse caso, estamos iniciado o reconhecimento de fala e processando cada resultado (palavra ou frase dita) esperando até o momento da frase final ser completa, exemplo de resultados para uma frase "2+2":

  1. "dois" ou "2"
  2. "mais" ou "+"
  3. "dois" ou "2"
  4. ao terminar de falar a frase, entender que o resultado final deve ser "2+2"

No caso, é importante executar o comando de voz apenas com a frase final para ter a garantia do contexto como um todo foi processado e estamos obtendo o resultado mais próximo do desejado

Podemos também, lidar com o caso de erro:

this.#recognition.onend = () => { this.updateListeningState(false) }

A função updateListeningState, tem como objetivo alterar o estilo do botão de escuta.

Por fim, iremos precisar configurar uma função para parar de ouvir o usuário e manipular alguns estilos:

this.#recognition.stop() this.updateListeningState(false) this.#startBtn.classList.remove('listening')

Prefer Color Scheme

Para auxiliar os 3 diferentes temas da calculadora, foi usado o recurso de mídia prefer-color-scheme.

Esse recurso possibilita o entendimento de qual a preferência do usuário em relação aos temas, assim podendo receber dois valores:

  • Light (Claro)
  • Dark (Escuro)

A maneira de aplicar esse recurso, no css, de acordo com a developer.mozilla é da seguinte maneira:

@media (prefers-color-scheme: dark) { /* Configurações CSS para o tema dark */ } @media (prefers-color-scheme: light) { /* Configurações CSS para o tema light */ }

Mas com esse método o código irá ficar mais verboso e provavelmente com difícil manutenção, pois seria necessário repetir todas as propriedades desejadas com suas novas colorações.

Então qual a solução ? 🤔

Iremos apenas mudar os valores das variáveis do CSS com JS.

Primeiro iremos, na pasta de constantes, verificar o arquivo themes.js:

export const themes = { 'Default': { id: '1', colors: [ { name: '--background', value: '#3a4764' } ] }, 'Light': { id: '2', colors: [ { name: '--background', value: '#e6e6e6' } ] }, 'Dark': { id: '3', colors: [ { name: '--background', value: '#17062a' } ] } }

Note o Nome dos temas e os id's utilizados, eles serão utilizados no arquivo ThemeManager.js, na pasta JS, da seguinte forma:

function changeThemeById(themeId) { const theme = Object.values(this.themesConfig).find(theme => theme.id === themeId) if (!theme) return this.#btnTheme.value = theme.id this.applyTheme(theme.colors) } function setPreferColorSchemeTheme() { if (!this.#btnTheme || !window.matchMedia) return Object.keys(this.themesConfig).forEach(themeName => { const matchedPreferredScheme = window.matchMedia(`(prefers-color-scheme: ${themeName})`)?.matches if (matchedPreferredScheme) this.#btnTheme.value = this.themesConfig[themeName].id }) this.changeThemeById(this.#btnTheme.value) }

O objetivo aqui, está em fazer um código para troca de temas de forma versátil e de fácil manutenção. Nesse caso, conseguimos buscar a preferência do usuário, através do window.matchMedia('(prefers-color-scheme: ${themeName})'), concatenado com o nome do nosso tema (que é igual a nomenclatura desejada)

Após descobrir o tema desejado, podemos enviar o id do tema em questão para função changeThemeById com objetivo de obter a nova coloração desejada

Para entender exatamente o que cada função está fazendo, como a applyTheme, acesse o arquivo na pasta JS

Como é Possível fazer o Teste/Debug ? 🤔

Com a ferramenta de devtools do seu navegador, acesse a aba "Rendering" e logo após procure o título "Emulate CSS media feature prefers-colors-scheme":

Alterando os valores padrões pelo devtools, o resultado final será:

Você também pode gostar

  • Gitfest - Gere uma lineup de festival com base nos seus principais repositórios do Github
  • Enkoji - Site feito para o Enkoji, um templo zen-budista japonês fundado em 1920 no Japão

⭐ Stars ⭐

Stargazers repo roster for @Igorcbraz/Calculadora