Igorcbraz/Calculadora

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub StarsForksNetlify StatusMIT LicenseIssuesLast CommitContributors

Logo

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
  • 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

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')

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.

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

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á:

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

Stargazers repo roster for @Igorcbraz/Calculadora