Pilhas e Filas (Estrutura de dados)

[download id=”589″]

Neste artigo estarei explicando o funcionamento das estruturas de dados conhecidas como Pilha e Fila. O código fonte JavaScript será deixado disponível e uma breve explicação junto com o uso serão dados para cada uma delas.

Pilha

Conceito Básico

A pilha é uma estrutura de dados básica que fornece a lógica conhecida por LIFO(Last In, First out). Isso significa que o ultimo dado adicionado a estrutura será o primeiro removido dela e por isso foca a entrada e saída de dados na mesma ponta do vetor/lista.

Na prática, a pilha como um controle para serviços que dependem da conclusão do ultimo recurso ativado antes de prosseguirem. Exemplos de rotinas que utilizam essa lógica são o “desfazer” do Word e o gerenciamento da execução de funções (de programação), que causa o conhecido erro de stackoverflow.

Código Fonte

O código fonte abaixo não vai usar o vetor do JavaScript simplesmente para podermos ver em mais detalhes o funcionamento desta estrutura de dados. não será uitlizado um vetor, mas sim nós (nodes) que se conectam uns aos outros.

function Pilha() {
    var topo = null;
    var quantidade = 0;

    //Retorna o número de itens na Pilha
    this.GetCount = function () {
        return quantidade;
    }
    //Push: Adiciona itens ao topo da pilha
    this.Push = function (dados) {
        var node = {
            dados: dados,
            proximo: null
        };

        node.proximo = topo;
        topo = node;

        quantidade++;
    }
    //Pop: Remove itens do topo da pilha
    this.Pop = function () {
        if (topo === null) {
            return null;
        } else {
            var removido = topo;
            topo = topo.proximo;

            if (quantidade > 0) {
                quantidade--;
            }

            return removido.dados;
        }
    }
    //Exibe o Item do topo da pilha
    this.VerTopo = function () {
        if (topo === null) {
            return null;
        } else {
            return topo.dados;
        }
    }
    //Retorna um vetor com todos iitens da Pilha
    this.VerTodos = function () {
        if (topo === null) {
            return null;
        } else {
            var arr = new Array();
            var current = topo;

            for (var i = 0; i < quantidade; i++) {
                arr[i] = current.dados;
                current = current.proximo;
            }

            return arr;
        }
    }
}

Fila

Conceito Básico

Fila é um tipo de estrutura de dados com um controle definido pela lógica FIFO (do inglês first in, last out). Esse controle quer dizer que os dados contidos nela são podem entrar apenas por uma ponta e deverão sair pela outra. Com isso, garante-se que o primeiro dado que entrou será o primeiro a sair da fila.

A fila é uma estrutura de dados muito útil quando se possui um serviço ao qual o sistema recebe alimentação de diversas fontes, mas precisa manter uma ordem do “primeiro que chegou será o primeiro servido”. Um exemplo simples é o sistema que administra diversos computadores ligados a uma única impressora.

Código Fonte

O código fonte abaixo não vai usar o vetor do JavaScript simplesmente para podermos ver em mais detalhes o funcionamento desta estrutura de dados. Não será utilizado um vetor como forma de controle mas sim nós contectados uns aos outros, irei também fazer com que o ato de adicionar o faça no começo da fila e o de remover será na outra ponta.

function Fila() {
    var quantidade = 0;
    var primeiro = null;
    var ultimo = null;

    //Retorna a quantidade na fila
    this.GetQuantidade = function () {
        return quantidade;
    }
    //adiciona um item a fila
    this.Adicionar = function (data) {
        var node = {
            data: data,
            prox: primeiro
        };

        if (primeiro === null) {
            ultimo = node;
        }

        primeiro = node;

        quantidade++;
    }
    //Remove um item da fila
    this.Remover = function () {
        //se a fila estiver vaiza, retorna nulo
        if (ultimo === null) {
            return null;
        }
        else {
            //senão percorre a fila até o ultimo item para removelo e ajusta a lista
            var current = primeiro;
            var previous = null;

            while (current.prox) {
                previous = current;
                current = current.prox;
            }

            if (quantidade > 1) {
                previous.prox = null;

                ultimo = previous;
            }
            //zera/reseta a fila
            else {
                primeiro = null;
                ultimo = null;
            }
            quantidade--;
        }
        //Exibe todos os itens da fila
        this.ExibirTodos = function () {
            if (primeiro === null) {
                return null;
            } else {
                var arr = new Array();
                var current = primeiro;

                for (var i = 0; i < quantidade; i++) {
                    arr[i] = current.data;
                    current = current.prox;
                }

                return arr;
            }
        }
    }
}

 

O que é ECMAScript, ES6, ES8?

Aprender JavaScript pode ser confuso por uma série de razões. Não permita que essas siglas o confundam mais. Vamos dividir e conquistar as abreviaturas do JS eES neste post!

O que é ECMAScript?

Aqui está o que aconteceu há muito tempo atrás: O JavaScript foi originalmente chamado de assim na esperança de capitalizar o sucesso do Java. Então a Netscape enviou JavaScript para a organização que padroniza informações, conhecida como ECMA International for Standardization. Isso resultou em um novo padrão de idioma, conhecido como ECMAScript.

Simplificando, o ECMAScript é um padrão. Enquanto o JavaScript é a implementação mais popular desse padrão. O JavaScript implementa o ECMAScript e constrói em cima dele.

 

Ok, então é o ‘ES’?

ES é simplesmente curto para ECMAScript. Toda vez que você vê ES seguido de um número, ele está fazendo referência a uma edição do ECMAScript. Na verdade, existem oito edições do ECMAScript publicadas. Abaixo listaremos quais foram as primeiras 4 edições do ECMAScript, e para economizar tempo, não vamos também em profundidade. Apenas saiba que as três primeiras edições foram anuais, e a quarta foi abandonada devido a diferenças políticas.

  • ES1: junho de 1997
  • ES2: junho de 1998
  • ES3: dezembro de 1999
  • ES4: Abandonado

Agora veremos as versões mais recentes e o que elas fizeram de diferente

ES5

Dezembro de 2009: quase 10 anos depois, o ES5 foi lançado em 2009. Levaria quase seis anos para que a próxima versão do ECMAScript fosse divulgada. Adiciona “strict mode”, ao subconjunto destinado a fornecer uma verificação de erros mais completas e construções propensas a erros. Esclarece muitas ambiguidades nas especificações da 3ª edição e acomoda o comportamento de implementações do mundo real que diferiram consistentemente dessa especificação. Adiciona alguns novos recursos, como getters e setters, suporte de biblioteca para JSON e reflexão mais completa sobre propriedades do objeto.

 

ES6 / ES2015

Talvez a causa de toda a sua confusão começa aqui. Você vê, ES6 e ES2015 são a mesma coisa. ES6 foi o nome popularizado antes da liberação. No entanto, o comitê que supervisiona as especificações do ECMAScript tomou a decisão de passar às atualizações anuais. Com essa mudança, a edição foi renomeada para ES 2015 para refletir o ano de lançamento. Os lançamentos subsequentes também serão nomeados de acordo com o ano em que forem divulgados.

Adiciona nova sintaxe significativa para escrever aplicativos complexos, incluindo classes e módulos, mas os define semanticamente nos mesmos termos que o modo estrito ECMAScript 5. Outros novos recursos incluem iteradores e repetições for/of, funções de seta (arrow), dados binários, arrays digitados, coleções (mapas, conjuntos e mapas fracos), promessas, número e aprimoramentos matemáticos.

 

ES2016 (ES7)

A Sétima Edição, também conhecida como ECMAScript 2016, pretende continuar os temas de reforma da linguagem, isolamento de código, controle de efeitos e habilitação de biblioteca / ferramenta de ES2015, inclui dois novos recursos: o operador de exponenciação (**) e Array.prototype.includes.

 

ES2017 (ES8)

Novos recursos propostos incluem simultaneidade e atômica, transferência de dados binários de cópia zero, mais número e aprimoramentos de matemática, integração sintática com promessas (aguardar / assíncrono), fluxos observáveis, tipos de SIMD, melhor meta-programação com classes, propriedades de classe e instância, sobrecarga de operador, Tipos de valor, registros, tuplas and traits.

Inteligência Artificial: Deeplearn.js

A biblioteca Deeplearn.js permite o treinamento de redes neurais, não exigindo instalação de software ou back-end. “Uma biblioteca de aprendizado de máquina do lado do cliente pode ser uma plataforma para explicações interativas, para prototipagem e visualização rápidas, e até para computação offline”, disseram pesquisadores do Google. “E se nada mais, o navegador é uma das plataformas de programação mais populares do mundo”.

Ela é oferecida pelo Google no formato código aberto, com aceleração de hardware para aprendizagem de máquina que é executada em pelo seu navegador. Atualmente ela é suportada apenas na versão desktop do Google Chrome, mas o projeto está para oferecer suporte a outros dispositivos.

Usando a API JavaScript para o WebGL, o Deeplearn.js pode realizar cálculos no GPU. Isso oferece um desempenho significativo, passando assim os limites de velocidade do JavaScript, segundo os pesquisadores.

O Deeplearn.js imita a estrutura da biblioteca de inteligência de máquina TensorFlow da empresa e NumPy, um pacote de computação científica baseado em Python. “Também implementamos versões de algumas das operações TensorFlow mais utilizadas. Com o lançamento do Deeplearn.js, estaremos fornecendo ferramentas para exportar pesos dos pontos de verificação TensorFlow, o que permitirá aos autores importá-los para páginas da internet para a inferência Deeplearn.js “.

Embora o TypeScript da Microsoft seja o idioma escolhido, Deeplearn.js pode ser usado com JavaScript puro. As demonstrações de Deeplearn.js são apresentadas na página inicial do projeto. O Deeplearn.js junta outros projetos que trazem aprendizado de máquina para JavaScript e o navegador, incluindo TensorFire, que permite a execução de redes neurais dentro de uma página e ML.js, que fornece ferramentas de aprendizado de máquina e análise numérica em JavaScript para Node.js.

Caso você tenha interesse em conhecer mais, o site oficial deles é o https://deeplearnjs.org/index.html e eles oferecem diversos demos para que os novos programadores possam ter uma ideia do potencial do Deeplearn. Caso você queira brincar com o código, veja este link: https://deeplearnjs.org/index.html#demos

Nova versão do Reason

Para quem não conhece o Reason (veja o reasonml) não é uma nova linguagem; É uma nova sintaxe e toolchain alimentado pela linguagem OCaml. Ele dá a OCaml uma sintaxe familiar voltada para programadores de JavaScript, e atende aos usuários de fluxo de trabalho NPM / Yarn já conhecidos.

Agora com a versão 3, uma das mudanças mais visíveis na sintaxe do Reason é o uso da sintaxe de aplicação/abstração JavaScript em vez de Ocaml. Isso significa que no Reason 3 você chamaria uma função de dois parâmetros, colocando parênteses em torno deles, como você faz em JavaScript:

myFunction(arg1, arg2) // novo, sintaxe C-like
myFunction arg1 arg2   // antigo, sintaxe OCaml-like

 

Outras mudanças importantes são as seguintes:

  • Nova sintaxe para declarar o tipo de um objeto em Javascript, usando {. }, ex.:
type payload = {.  // Não precisa chamar o no need to call Js.t aqui
    "name": string,
    "age": int
};

 

  • Suporte ampliado para type punning com parâmetros marcados e nova sintaxe usando “~” em vez de “::”. É assim que você declara e chama uma função com o parâmetro marcados:

 

let addCoordinates = (~x, ~y) => {
    /* use x e y aqui */
};
...
addCoordinates(~x=5, ~y=6);

 

Compara a nova implementação com a antiga:

let addCoordinates x::x y::y => {
  /* use x e y aqui */
};
...
addCoordinates x::5 y::6;

 

Além disso, type punning (que, no exemplo acima, permite escrever ~x em vez do mais tedioso ~x como x) pode ser usado junto com tipos de anotações, que não haviam sido suportadas anteriormente:

let add = (~first: int, ~second: int) : int => first + second;

 

  • Concatenação de String agora pode ser feito usando o operador “++” ao invés do “^”.
  • Lógicas de negação agora será pelo operador “!” ao invés do “not”

Os desenvolvedores que possuem uma base de código Reason existente não devem se preocupar com a extensão das mudanças de sintaxe, que foram principalmente impulsionadas pela idéia de torná-lo mais “natural” para desenvolvedores de JavaScript. Na verdade, o Reason 3 vem com um script de migração que promete facilitar a transição.

Outra nova característica promissora do ecossistema Reason é a disponibilidade de uma API oficial para acesso programático ao Parser Reason, refmt, que já possui várias ferramentas como o Klipsereason-tools, a documentação no site do Reason, etc.

fonte:

https://reasonml.github.io/

https://www.infoq.com/br/news/2017/12/facebook-releases-reason-3

https://www.infoq.com/news/2017/11/facebook-releases-reason-3

Codificando um jogo de carrinho

[download id=”467″]

Olá galera do MundoJs

Vamos a mais um tutorial sobre javascript e games !
Desta vez algo um pouco mais avançado.
Se você está começando agora é melhor tentar antes esse tutorial e esse aqui também.

Este artigo mostra uma maneira de fazer um jogo de carrinho em javascript sem nenhuma imagem.

Para começar vamos desenhar o carrinho com HTML5 e Css:

<div style='position:relative; z-index:2; top:254px; left:254px; width:20px; height:40px; background-color:#000000; border-radius:4px;'>
  <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
  <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
</div>

Este carrinho ficará no meio da tela.
A pista irá se mover sob o carrinho.

Vamos desenhar a pista num <canvas>

<canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  ctx.fillStyle = "#385383";
  ctx.fillRect(200, 200, 200, 200);
</script>

Vamos fazer esta pista se mover sob o carrinho com a função setTimeout atualizando a posição:

<div style='position:relative; z-index:2; top:254px; left:254px; width:20px; height:40px; background-color:#000000; border-radius:4px;'>
  <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
  <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
</div>
<canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  function move() {
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x + 10;
    if (x > 300) x = -400;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 100);
  }
  move();
</script>

O próximo passo é centralizar tudo usando a tag <center>

Depois disto interceptar o pressionamento das teclas com o atributo onKeydown

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro>
      <div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px;'>
        <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
        <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
      </div>
    </div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  function move() {
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x + 10;
    if (x > 300) x = -400;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 100);
  }
  move();
  function vira(k) {
    alert(k);
  }
</script>
</html>

A função ‘vira()’ é executada quando o usuário pressiona qualquer tecla.
Com isso podemos descobrir o código das teclas direcionais.

O próximo passo é fazer o carro rotacionar com o comando <body onKeyDown>

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro>
      <div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(180deg);'>
        <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
        <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
      </div>
    </div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  function move() {
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x + 10;
    if (x > 300) x = -400;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 100);
  }
  move();
  angulo = 18;
  function vira(k) {
    //alert(k);
    if (k == 37) angulo = (angulo + 35) % 36;
    if (k == 39) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
  }
</script>
</html>

Repare que o angulo começa em 18.
O carro rotacionado 180 graus.
Apontado pra baixo.

’37’ e ’39’ são os códigos das teclas ‘esq’ e ‘dir’ do teclado.

Quando ‘esq’ é apertado o valor do angulo aumenta 35.
Como é sempre o resto da divisão por 36… nunca fica maior que 35.
Praticamente (angulo+35)%36 significa angulo-1.

Esse é o movimento básico do carrinho!

Mas tem uns detalhes a mais.

Enquanto o usuário manter a tecla pressionada o carro tem que ficar girando.
Isso complica um pouco porque o sistema operacional dá uma margem… um intervalo… um delay… quando user pressiona.

Para contornar essa situação vamos usar ‘onkeydown’ e ‘onkeyup’.
Mais duas variáveis ‘esq’ e ‘dir’.

E vamos colocar a atualização da variável angulo, e o desenho do carro, dentro da função ‘move()’

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" onKeyUp="para(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro></div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  angulo = 18;
  esq = false;
  dir = false;
  function vira(k) {
    if (k == 37) esq = true;
    if (k == 39) dir = true;
  }
  function para(k) {
    esq = false;
    dir = false;
  }
  function move() {
    if (esq) angulo = (angulo + 35) % 36;
    if (dir) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x - 10;
    if (x < -400) x = 460;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 50);
  }
  move();
</script>
</html>

Agora começa a parte complicada!
Fazer o carro se mover em relação à pista.

Para isso vamos usar umas variáveis ‘fatorx’ e ‘fatory’.
Elas vão definir o deslocamento do carro em relação a pista… no eixo x e no eixo y.

Por exemplo… quando o carro estiver inclinado 30 graus ele irá se deslocar 6 pixels no eixo x e -3 pixels no eixo y…

fatorx=[9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8];
fatory=[0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1];
<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" onKeyUp="para(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro></div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  fatorx = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8];
  fatory = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1];
  px = 10;
  py = 10;
  angulo = 18;
  esq = false;
  dir = false;
  function vira(k) {
    if (k == 37) esq = true;
    if (k == 39) dir = true;
  }
  function para(k) {
    esq = false;
    dir = false;
  }
  function move() {
    if (esq) angulo = (angulo + 35) % 36;
    if (dir) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);

    px += fatorx[angulo] * 3.7;
    py += fatory[angulo] * 3.7;

    ctx.fillStyle = "#385383";
    ctx.fillRect((200) + py + 38, (200) + px + 28, 200, 200);

    setTimeout('move()', 75);
  }
  move();
</script>
</html>

Agora já temos um carro completamente dirigível !!!
Uhu!!!

Agora vamos à pista.

Vamos criar um ‘array de arrays’ com zeros representando grama e um representando asfalto.

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" onKeyUp="para(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro></div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  fatorx = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8];
  fatory = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1];
  pista = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1],
  ];
  px = 10;
  py = 10;
  angulo = 18;
  esq = false;
  dir = false;
  function vira(k) {
    if (k == 37) esq = true;
    if (k == 39) dir = true;
  }
  function para(k) {
    esq = false;
    dir = false;
  }
  function move() {
    if (esq) angulo = (angulo + 35) % 36;
    if (dir) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    px += fatorx[angulo] * 3.7;
    py += fatory[angulo] * 3.7;
    ctx.fillStyle = "#385383";
    for (x = 0; x < pista.length; x++)for (y = 0; y < pista[x].length; y++)if (pista[x][y] != 0) ctx.fillRect((200 * y) + py + 38, (200 * x) + px + 28, 200, 200);
    setTimeout('move()', 75);
  }
  move();
</script>
</html>

A linha 48 desenha a pista inteira com os ‘for’ e os parâmetros em ‘fillrect’…

Um próximo passo pode ser fazer o carro diminuir a velocidade quando está sobre a grama!

Fazer outras fases…

Fazer a velocidade ir aumentado.

Usar imagens para o carro. Imagens para a pista. pngs transparentes.

‘O céu é o limite.’

Dá para melhorar bem.

Essa é só uma simples versão de 53 linhas

Cursos gratuitos de JavaScript para iniciantes

Até onde sei, estudar JavaScript não está incluso em cursos de CC, nem em cursos técnicos (quando muito um basicão para web designers). Por isso, estudar e achar cursos acaba ficando a critério daqueles que querem aprender a programar com essa linguagem.

Acredito que não seja somente comigo, mas quando quero aprender uma tecnologia nova, prefiro não investir dinheiro antes de saber se realmente vale apena me aprofundar no conhecimento. Com o fim de ajudar que está começando ou migrando, estou colocando aqui uma lista de cursos Grátis e material de JavaScript para iniciantes.

Udacity – JavaScript básico

Segundo eles: “Neste curso, você vai explorar a linguagem de programação JavaScript, criando uma versão interativa do seu currículo. Você vai aprender os fundamentos de programação JavaScript que você precisa enquanto a constrói novos elementos e seções para melhorar o seu currículo.”

 

W3Cx – JavaScript Introduction (Ingles)

Ótimo curso feito pela equipe da W3C (não confundir com W3schools). Nele, além do JavaScript básico, é visto várias coisas que se tornam necessárias para aqueles que precisaram trabalhar com aplicações web
Continue lendo “Cursos gratuitos de JavaScript para iniciantes”

Comparando JavaScript

Primeiro vou comparar JavaScript com linguagens que não são derivadas da linguagem C

 

JavaScript x Pascal

Pascal foi muito bom na época do Delphi7. Era muito integrado com o Windows. Naquela época o JavaScript estava começando.

O problema é que Delphi é praticamente só para Windows. Delphi ficou pra trás por causa da evolução dos browsers.

De certa maneira código Pascal/Delphi é muito bom pois permite ao programador acessar o hardware mais diretamente que js, mas, de certa maneira, Pascal perdeu a briga por causa da ‘portabilidade’ (que era e ainda é a vantagem dos browsers).

Um código escrito em JavaScript para browser roda no Windows, no Linux, no mac, no android… Pascal se tornou engessado.

Para alguns casos ainda vale a pena, mas JavaScript está muito mais acessível.

 

JavaScript x Python

Python é relativamente moderno. Python é uma linguagem interpretada (não compilada) assim como JavaScript. E isso parece ser uma tendência.

Escrever código JavaScript é ligeiramente mais fácil que escrever código em Python.

Em questão de portabilidade JavaScript ganha de longe porque todo dispositivo aceita. Python precisa ser instalado na maioria das vezes.

Em algumas vezes funciona como linguagem server-side, e nesses casos a performance de Python é comparável com a do JavaScript. Talvez Python até ganhe essa disputa.

Mas não ganha a guerra.

 

JavaScript x Asp (Vbscript)

Asp era uma opção. Existia a ‘browser wars’ e também existia a disputa entre PHP e Asp. Entre mySQL e SQL server. Entre Windows server e l.a.m.p.

Parece que isso evoluiu. Ouvi falar dos azure. Ouvi sobre os .net

Parece que ser parceiro da Microsoft tem suas vantagens. Tenho a impressão que existe um suporte ao consumidor. Quem continua investindo em Asp recebe junto no pacote acessória.

Mas de certo modo cai no mesmo buraco que o Delphi: faz software apenas para Windows.

Existe a opção Asp Windows-server, mas considero que a concorrência está na frente.

 

JavaScript x Assembly

Assembly parece ser a mais difícil de escrever. E parece que é a que dá ao programador maior domínio sobre o hardware. Em Assembly dá para fazer coisas que em JavaScript não dá.

Mas por ser tão difícil perde a disputa. E a questão da portabilidade é ainda mais severa. Parece que determinado código Assembly que funciona em um equipamento não funciona em outro determinado equipamento.

Por isso criaram as outras linguagens… o programador escreve o source em linguagem de auto nível e depois o compilador de cada máquina gera o Assembly específico.

 

JavaScript x HTML

HTML é uma linguagem ligada ao js. Na forma mais usual o JavaScript serve para alterar o HTML.

Mas o HTML não aceita instruções como o JavaScript. Html é uma linguagem de marcação.

 

JavaScript x CSS

Css é moderno. É a linguagem irmã-menor do trio: HTML, JavaScript e CSS.

É possível criar belas formas e animações interessantes com CSS, mas seu potencial é alcançado na junção com js.

 

JavaScript x SQL

Sql é uma linguagem tradicional. A história é que antigamente cada desenvolvedor armazenava os dados seguindo seu próprio padrão. Em um determinado momento decidiram facilitar e criaram o padrão SQL. A partir daí surgiu uma camada. Se antes o software era uma peça inteira, depois disso se dividiu em questões relativas a armazenagem de dados e questões relativas a como apresentar dados ao usuário e permitir que ele os edite.

SQL tem essa limitação. Não é para efeitos visuais. Serve por debaixo dos panos.


Agora vamos comprar JavaScript com linguagens que são derivadas da linguagem C

 

JavaScript x c

A linguagem c hoje em dia é referencial.

As outras linguagens são influenciadas por ela.

Ela é muito utilizada no ensino de linguagens de programação.

A sintaxe da linguagem C é a mesma da linguagem js.

Considero que JavaScript é descendente direta de C. A descendente mais famosa.

 

JavaScript x Java

Java também é descendente de C. A descendente mais certinha.

Funciona como linguagem desktop, apesar de que eu não recomendo. E também funciona como server-side, mas eu também não recomendo. Para mim a gloria do Java é ser a linguagem oficial do android.

São duas linguagens em níveis diferentes. Apesar de serem parecidas e terem o nome parecido.

Java é bem mais difícil porque mostra ao programador o hardware.

 

JavaScript x PHP

PHP já reinou absoluto no server-side. Apesar da concorrência com a Microsoft.

Agora concorre com nodejs, Python, Java e Microsoft. E outras.

Também é descendente de C.

É a linguagem C com o símbolo de dólar na frente dos nomes das variáveis.

Eu ainda vivo na época do PHP…

Gosto de PHP server-side e JavaScript client-side


E agora vou comparar JavaScript com ela mesma

 

JavaScript x JavaScript server-side

A linguagem JavaScript é muito permissiva. O programador pode escrever a mesma instrução de várias maneiras diferentes. Nada é tipado.

Isso facilita muito pra quem tá começando.

E oferece a possibilidade de o desenvolvedor fazer de várias maneiras.

Mas nem sempre isso é vantagem.

Considero que o server deve ser rápido na sua simples tarefa de receber a ‘requisição’, buscar como ‘resolvê-la’ e entregar o HTML para o browser.

E a permissividade pode acarretar perda de performance pelo tempo do server ‘entender’ um comando e pelo programador optar por um paradigma e abrir mão de outros…

Como disse acima: gosto de PHP.

 

JavaScript x JavaScript unity

A unity permite que o usuário codifique em JavaScript. Isso é bom pois facilita para o usuário.

Em relação ao JavaScript tradicional, a diferença está no interpretador.

No js tradicional é o browser que executa os comandos, no caso da unity o compilador lida com outros objetos.

Nos dois casos, escrever código JavaScript é abrir mão de lidar diretamente com o hardware.

Para finalizar afirmo que JavaScript é minha linguagem de programação favorita. Por ser executada em qualquer dispositivo.

Iniciando com Chart.js

 

[download id=”404″]

Caso queira ver meu próximo artigo, acesse: Gráficos Dinâmicos com Eventos – Chart.js

Hoje em dia, criar gráficos do zero é uma missão complicada, pois além de ter que escrever todo o Javascript também precisamos pensar no design responsivo, felizmente temos bibliotecas que facilitam nossa vida e deixam o trabalho ainda mais rápido.

O Chart.js é uma biblioteca muito utilizada pela comunidade, é uma biblioteca excelente e muito fácil de usar, mesmo se você não tiver conhecimentos avançados de Javascript você vai conseguir criar gráficos bons, bonitos e responsivos.

Importando Chart.js

Para começar, precisamos escolher a forma de importação, podemos fazer isso por um CDN ou fazendo download.

Existem dois tipos de arquivos Chart.min.js e Chart.js, os arquivos com a extensão .min.js são arquivos que foram minificados, comprimidos para que o carregamento em tela seja mais rápido.

Se você deseja utilizar um CDN, basta clicar neste Link para pegar a versão mais recente do Chart.js ou simplesmente copiar a linha de código abaixo e colar no corpo do seu HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>

Se você prefere fazer download dos arquivos do Chart.js basta clicar neste Link para fazer o download e fazer uma importação normal de Javascript.

<script src="SuaPasta/Chart.min.js"></script>

Gerando o primeiro gráfico

A primeira coisa que precisamos para gerar o nosso plano cartesiano é criar uma tag canvas no HTML e atribuir um id para ela:

<canvas id="primeiroGrafico"></canvas>

Indo para o arquivo Javascript, precisamos criar uma variável capturando nosso canvas e contexto:

let primeiroGrafico = document.getElementById('primeiroGrafico').getContext('2d');

O próximo passo é criar outra variável e instanciar a classe do chart.js passando por parâmetro o nosso canvas e um Objeto Javascript de preferencias deste gráfico:

let primeiroGrafico = document.getElementById('primeiroGrafico').getContext('2d');
                        
let chart = new Chart(primeiroGrafico, {});

É nesse objeto que vamos configurar nosso gráfico, em primeiro lugar vamos dizer qual é o tipo de gráfico que queremos, usando a propriedade type, atribuindo a ela o tipo que desejamos, os tipos que o chart.js disponibiliza são line (gráfico comum de linhas), bar (gráfico de barras), pie (gráfico de pizza), e muito mais, neste exemplo iremos utilizar o tipo line:

let chart = new Chart(primeiroGrafico, {
    type: 'line'             
});

Logo após iniciarmos o plano cartesiano, iremos configurar os dados do nosso gráfico usando a propriedade data:

let chart = new Chart(primeiroGrafico, {
    type: 'line',
                        
    data: {
        labels: ['2000', '2001', '2002', '2003', '2004', '2005'],
                    
        datasets: [
            {
                label: 'Crecimento Populacional',
                data: [173448346, 175885229, 178276128, 180619108, 182911487, 185150806]
            }
        ]
    }
});

A propriedade data também é um objeto, no exemplo acima configuramos duas propriedades para o objeto data, que são labels e datasets.

Na propriedade labels inserimos um array de string referente aos pontos do gráfico no eixo X

Na propriedade datasets inserimos um array de Objetos, referente aos dados apresentados no Gráfico, a propriedade label é o título do gráfico, na propriedade data inserimos um array de number referente aos pontos do Gráfico no eixo Y

Importante:

Você deve inserir um array de Strings na propriedade labels, na propriedade data você deve inserir um array de Number

Os itens do array de data serão ligados aos itens correspondentes no array de labels, é importante que os dois arrays estejam na ordem desejada, por exemplo:

labels: [‘2000’, ‘2001’, ‘2002’, ‘2003’, ‘2004’, ‘2005’]
data: [173448346, 175885229, 178276128, 180619108, 182911487, 185150806]

Nesse caso o primeiro ponto será colocado no ano 2000 (eixo X) e no número 173.448.346 (eixo Y), e assim sucessivamente


Continue lendo “Iniciando com Chart.js”

Como fazer um jogo em JavaScript com a tag canvas

[download id=”396″]

Esse tutorial apresenta uma maneira de desenvolver o jogo pong. Um jogo básico e simples.
Vamos começar criando um arquivo em branco chamado jogo.htm. Nesse arquivo vamos digitar o código:

<!doctype html>
<html>
    <body>
        Daqui vai surgir o jogo
    </body>
</html>

Vamos apagar a frase e colocar o elemento canvas

<canvas></canvas>

Se você salvar o arquivo e clicar duas vezes sobre ele, o navegador irá exibir uma página em branco.
Mas o canvas está lá…
Para deixar ele visível vamos colocar uma borda:

<canvas style="border:1px solid #4a4a4a;"></canvas>

Para o jogo ficar de um jeito legal vamos colocar o canvas no meio da tela e dar o tamanho 400x450px
O motivo que me levou a usar o elemento canvas é que ele possibilita desenhar na tela codificando… escrever ‘desenhe uma linha azul;’ ou ‘desenhe um quadrado no canto’
Os primeiros jogos eletrônicos eram em modo texto. Em seguida eram em blocos quadrados. Depois eram desenhados através de codificação… Depois vieram os bmp os gif os jpg… os 3d…
Mas esse jogo é da época do quadrado
E usa o canvas que é um elemento que ‘emula’ um recurso inventado na época do ‘desenhar com código’

Quando fiz esse jogo no canvas pela primeira vez em 2010 eu estava acompanhando o surgimento do html5 e li sobre o canvas e sobre como era possível desenhar nele. O jogo foi resultado de testes que começaram com a pergunta: ‘Como eu desenho uma bola nesse canvas?’
Eu pesquisei… em vários sites e tutoriais… inclusive no site do w3c e w3schools

Para desenhar no canvas eu preciso de um ‘context’
Para isso eu dou um id pro canvas que criei… e uso JavaScript

<html>
<body>
    <center><canvas id=canvas width=400 height=450 style='border:1px solid #4a4a4a;'></canvas></center>
    <script>
        canvas=document.getElementById('canvas').getContext('2d');
    </script>
</body>
</html>

Para desenhar o círculo em vermelho dentro do canvas em preciso de algumas propriedades do ‘context’… alguns métodos e atributos:
fillStyle
beginPath();
arc();
fill();

canvas.fillStyle='#ff0000'; 
canvas.beginPath(); 
canvas.arc(50,125,16,0,Math.PI*2,false); 
canvas.fill();

Recomendo que vc entenda esses parâmetros.

Vamos usar a função setTimeout();
Pegar esse código que desenha a bolinha e fazer ele ser executado a cada 10 milissegundos.
E mudar os dois primeiros parâmetros da função arc para variáveis x e y, e incrementar essas variáveis cada vez para a bolinha se mover.

x=30;
y=15;
function anda()
{	
    x+=2;
    y+=2;
    canvas.fillStyle='#ff0000';
    canvas.beginPath();
    canvas.arc(x,y,16,0,Math.PI*2,false);
    canvas.fill();
    setTimeout('anda();',10);
}
anda();
canvas.fillStyle='#ffffff'; 
canvas.fillRect(0,0,400,450);

Para isso vamos precisar de novas variáveis dx e dy que vão armazenar quanto a bolinha avança (ou retrocede) no eixos x e y
Vamos mudar o valor de dx e de dy quando a bolinha pingar na parede… quando ela chegar no chão o dx vai mudar de +2 para -2

<script>
canvas=document.getElementById('canvas').getContext('2d');
x=20;
y=200;
tamanho=10;
dx=2;
dy=2;
function anda()
{	
    x+=dx;
    y+=dy;
    if(x<tamanho)dx*=-1;
    if(y<tamanho)dy*=-1;
    if(x>400-tamanho)dx*=-1;
    if(y>450-tamanho)dy*=-1;
    canvas.fillStyle='#ffffff';
    canvas.fillRect(0,0,400,450);
    canvas.fillStyle='#ff0000';
    canvas.beginPath();
    canvas.arc(x,y,tamanho,0,Math.PI*2,false);
    canvas.fill();
    setTimeout('anda();',10);
}
anda();
</script>
barrax=150;
canvas.fillStyle='#000000'; 
canvas.fillRect(barrax,430,100,20);

Para fazer a barra se mover vamos usar o atributo onKeyDown da tag body

<body onkeyDown='movebarra(event.which);'>

E vamos escrever a função movebarra
Inicialmente vamos por um alert para identificar o código de cada tecla

function movebarra(tecla)
{	
    alert(tecla);
}

E agora vamos fazer a barra se mover

function movebarra(tecla)
{	
    /*alert(tecla);*/
    if(tecla==37)barrax-=40;
    if(tecla==39)barrax+=40;
}

Quando a bola acertar a barra a bola deve voltar a subir… E dependendo de que parte da barra a bola acertar a bola deve voltar em um certo ângulo
Vamos modificar a função anda

if(y <450-tamanho)setTimeout( 'anda();',10);
else alert('Fim de jogo');
 if(y>430-tamanho)
{	
    var dif=x-barrax;
    if(dif>-10&&dif<110)
    {	
        dy*=-1;
        if(dif>-10&&dif<15)dx=-3;
        if(dif>=15&&dif<50)dx=-2;
        if(dif>=50&&dif<85)dx=2;
        if(dif>=85&&dif<110)dx=3;
        y=430-tamanho;
    }
}

O código até aqui fica:

<!doctype html>
<html>
<body onkeyDown='movebarra(event.which);'>
<center><canvas id=canvas width=400 height=450 style='border:1px solid #4a4a4a;'></canvas></center>
<script>
canvas=document.getElementById('canvas').getContext('2d');
x=20;
y=200;
tamanho=10;
dx=2;
dy=2;
barrax=150;
function anda()
{	
    x+=dx;
    y+=dy;
    if(x<tamanho)dx*=-1;
    if(y<tamanho)dy*=-1;
    if(x>400-tamanho)dx*=-1;
    if(y>450-tamanho)dy*=-1;
    canvas.fillStyle='#ffffff';
    canvas.fillRect(0,0,400,450);
    canvas.fillStyle='#000000';
    canvas.fillRect(barrax,430,100,20);
    canvas.fillStyle='#ff0000';
    canvas.beginPath();
    canvas.arc(x,y,tamanho,0,Math.PI*2,false);
    canvas.fill();
    if(y>430-tamanho)
    {	
        var dif=x-barrax;
        if(dif>-10&&dif<110)
        {	dy*=-1;
            if(dif>-10&&dif<15)dx=-3;
            if(dif>=15&&dif<50)dx=-2;
            if(dif>=50&&dif<85)dx=2;
            if(dif>=85&&dif<110)dx=3;
            y=430-tamanho;
        }
    }
    if(y<450-tamanho)setTimeout('anda();',10);
    else alert('Fim de jogo');
}
anda();
function movebarra(tecla)
{	
    /*alert(tecla);*/
    if(tecla==37)barrax-=40;
    if(tecla==39)barrax+=40;
}
</script>
</body>
</html>

Para começar vamos apenas desenhar um bloquinho.
Vamos criar uma variável bloco que será um array com três índices:

 

  • A posição x do bloco
  • A posição y
  • Se o bloco deve ser exibido (começa com true e fica false assim que a bola atingir)
bloco=[10,20,true];
if(bloco[2])
{	
    canvas.fillStyle='#0000ff';
    canvas.fillRect(bloco[0],bloco[1],50,20);
}
if(bloco[2])
{	
    var dif=y-bloco[1]-tamanho;
    if((dy<0&&(dif>0&&dif<20))||(dy>0&&(dif<0&&dif>-20)))
    {	if(x>bloco[0]&&x<bloco[0]+50)
        {	dy*=-1;
            bloco[2]=false;
        }
    }
}

Por enquanto fizemos o jogo funcionar com um bloco
Vamos transformar em um array de blocos
Vários blocos
Vamos colocar antes da declaração do x=20 e y=200 esse trecho de código que inicializa o array de blocos:

blocos=[]; 
for(x=0;x<8;x++)for(y=0;y<5;y++)blocos.push([x*50,y*20,true]);

E vamos ‘refatorar’ o código… transformar todas a ocorrencias de bloco em blocos[indice]:

for(c=0;c<blocos.length;c++)if(blocos[c][2])
{	
    var dif=y-blocos[c][1]-tamanho;
    if((dy<0&&(dif>0&&dif<20))||(dy>0&&(dif<0&&dif>-20)))
    {	if(x>blocos[c][0]&&x<blocos[c][0]+50)
        {	blocos[c][2]=false;
            dy*=-1;
        }
    }
}
for(c=0;c<blocos.length;c++)if(blocos[c][2])
{	
    canvas.fillStyle='#0000ff';
    canvas.fillRect(blocos[c][0],blocos[c][1],50,20);
}

O código completo fica:

<!doctype html>
<html>
<body onkeyDown='movebarra(event.which);'>
<center><canvas id=canvas width=400 height=450 style='border:1px solid #4a4a4a;'></canvas></center>
<script>
canvas=document.getElementById('canvas').getContext('2d');
blocos=[];
for(x=0;x<8;x++)for(y=0;y<5;y++)blocos.push([x*50,y*20,true]);
x=20;
y=200;
tamanho=10;
dx=2;
dy=2;
barrax=150;
function anda()
{	
    x+=dx;
    y+=dy;
    if(x<tamanho)dx*=-1;
    if(y<tamanho)dy*=-1;
    if(x>400-tamanho)dx*=-1;
    if(y>450-tamanho)dy*=-1;
    canvas.fillStyle='#ffffff';
    canvas.fillRect(0,0,400,450);
    canvas.fillStyle='#000000';
    canvas.fillRect(barrax,430,100,20);
    canvas.fillStyle='#ff0000';
    canvas.beginPath();
    canvas.arc(x,y,tamanho,0,Math.PI*2,false);
    canvas.fill();
    for(c=0;c<blocos.length;c++)if(blocos[c][2])
    {	
        canvas.fillStyle='#0000ff';
        canvas.fillRect(blocos[c][0],blocos[c][1],50,20);
    }
    for(c=0;c<blocos.length;c++)if(blocos[c][2])
    {	
        var dif=y-blocos[c][1]-tamanho;
        if((dy<0&&(dif>0&&dif<20))||(dy>0&&(dif<0&&dif>-20)))
        {	
            if(x>blocos[c][0]&&x<blocos[c][0]+50)
            {	blocos[c][2]=false;
                dy*=-1;
            }
        }
    }
    if(y>430-tamanho)
    {	
        var dif=x-barrax;
        if(dif>-10&&dif<110)
        {	
            dy*=-1;
            if(dif>-10&&dif<15)dx=-3;
            if(dif>=15&&dif<50)dx=-2;
            if(dif>=50&&dif<85)dx=2;
            if(dif>=85&&dif<110)dx=3;
            y=430-tamanho;
        }
    }
    if(y<450-tamanho)setTimeout('anda();',10);
    else alert('Fim de jogo');
}
anda();
function movebarra(tecla)
{	
    /*alert(tecla);*/
    if(tecla==37)barrax-=40;
    if(tecla==39)barrax+=40;
}
</script>
</body>
</html>

Módulo para criação de tags e componentes

[download id=”390″]

Introdução

Nesse artigo serão mostradas funções que podem ser utilizadas para a criação de componentes HTML. O projeto será uma versão simplificada de uma biblioteca que estou montando para agilizar o desenvolvimento e gerenciamento de objetos criados dinamicamente.

Como requisito, você precisa ter conhecimentos básicos de JavaScript e HTML5, acesso a biblioteca CSS w3.css e um navegador atualizado que aceite o básico do ES6.

  • Criando as Tags básicas

    Como você deve saber, o JavaScript oferece uma função que permite a criação de qualquer tag. Basta fornecer corretamente o nome da tag como uma string por parâmetro que a função retornará o elemento para que você possa manipulá-lo. Segue abaixo um exemplo:

    document.createElement("p");

    O código acima retorna um elemento do tipo paragrafo. Ele pode ser manipulado (adicionadas, classes, estilo, texto, etc..) da mesma maneira que os elementos da função getElementById() também podem ser manipulados. Mas ele é simples e dependendo das necessidades, você acabará tendo diversos trechos de código onde cria uma tag, adiciona classes e adiciona conteúdo. Para nos ajudar com isso, teremos as duas seguintes funções:

    function CriarElementoComClasse(nomeTag, listaDeClasses) {
        let element = document.createElement(nomeTag);
        if (listaDeClasses) {
            listaDeClasses.forEach(classe => {
                element.classList.add(classe);
            });
        }
        return element;
    }
    
    function CriarElementoComClasseTexto(nomeTag, listaDeClasses, texto) {
        let element = CriarElementoComClasse(nomeTag, listaDeClasses);
        element.innerHTML = texto;
        return element;
    }

     

    A primeira função recebe uma string com o nome da tag e uma lista de strings com o nome das classes que serão adicionadas. Ela cria o elemento, confere se a lista não é nula ou indefinida e a percorre adicionando as classes uma a uma.

    A segunda função faz o mesmo que a primeira, mas também adiciona texto dentro da tag. É importante notar que esta função depende da anterior e que texto talvez seja uma definição muito ampla pois foi utilizado a propriedade innerHTML que permite que sejam adicionadas mais coisas. Por enquanto vamos com a ideia de adicionar texto, isso a torna uma boa candidata para criar <span>, <p>, <strong>, stc…

  • Criando Links e Imagens

    Como a parte simples e mais abstrata já foi feita, agora iremos implementar funções que nos auxiliaram a criar mais rapidamente tags de imagens e para links de hipertexto. Segue abaixo o código de implementação de ambas funções

    function CriarImagemCompleta(src, imgClasses, imgAlt = "imagem") {
        let element = CriarElementoComClasse("img", imgClasses);
        element.alt = imgAlt;
        element.src = src;
        return element;
    }
    
    function CriarLinkCompleto(link, linkClasses, texto) {
        let element = CriarElementoComClasseTexto("a", linkClasses, texto);
        element.href = link;
        return element;
    }

    Após analisar o código você poderá notar que ambas funções reutilizam as rotinas que criamos anteriormente, sendo que apenas implementamos o código que falta para que a criação de tag de imagem e link possam ser implementadas sem precisarmos ficar repetindo o código adicional que cada uma precisa toda vez que precisarmos cria-las.

  • Anexando diversos elementos juntos

    Até agora vimos 4 funções que nos permitem criar alguns componentes que podem ser bem úteis. No entanto, se você trabalha com códigos mais extensos, coisas parecidas ou piores que o código abaixo podem aparecer

    let umaDiv = CriarElementoComClasse("div", ["classe1","classe2","classe3"]);
    let umaDiv2 = CriarElementoComClasse("div",["classe1","classe2","classe3"]);
    let umSpan = CriarElementoComClasseTexto("span", ["classe2","classe2","classe3"],"Lorem Ipsum"); 
    let umSpan2 = CriarElementoComClasseTexto("span", ["classe2","classe2","classe3"],"Lorem Ipsum dolor"); 
    let umaImagem = CriarImagemCompleta("https://mundojs.com.br/images/logo.png", ["classe1","classe2","classe3"], "Logo MundoJS"); 
    let umLink = CriarLinkCompleto("https://mundojs.com.br", ["classe1","classe2","classe3"], "MundoJS"); 
    let umLink2 = CriarLinkCompleto("https://mundojs.com.br/artigos/index.html", ["classe1","classe2","classe3"], "MundoJS - artigos");
    
    umaDiv.appendChild(umSpan); 
    umaDiv.appendChild(umaImagem);
    umaDiv.appendChild(umLink); 
    umaDiv.appendChild(umaDiv2); 
    
    umaDiv2.appendChild(umSpan2); 
    umaDiv2.appendChild(umLink2);

    E quanto mais elementos tivermos, maior será o comprimento de código repetido. Por isso, iremos criar uma função ao qual passamos o elemento onde será feito o append e uma lista dos arquivos que serão adicionados a ele.

    function AppendElementos(pai, filhos) {
        filhos.forEach(element => {
            pai.appendChild(element);
        });
    }

    E isso nos permite transformar os diversos append anteriores em 2 linhas de código

    AppendElementos(umaDiv, [umSpan, umaImagem, umLink, umaDiv2]); 
    AppendElementos(umaDiv2, [umSpan2, umLink2]);
  • Criação de Thumbnail

    Por padrão, um thumbnail é uma área com uma imagem no topo seguida de um titulo e/ou texto descritivo. O interessante deste tipo de componente o fato que ele pode ser facilmente incorporado em páginas responsivas devido ao seu formato. Antes de continuarmos, no seu arquivo CSS será necessário adicionar as seguintes classes:

    .mundojs-media{
        overflow: hidden;
        display: block;
        text-decoration: none;
        -webkit-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
        -moz-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
        box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
    }

    Segue abaixo o código para implementarmos thumbnails utilizando nossas funções já criadas e a formatação fornecida pelo w3.css:

    function CriarThumbnail(linkArquivo, titulo, descricao, imagem) {
        let linkThumbnail = CriarLinkCompleto(linkArquivo, ["w3-third", "w3-margin-bottom", "mundojs-media"]);
        let divCard = CriarElementoComClasse("div", ["w3-card-4"]);
        linkThumbnail.appendChild(divCard);
    
        let imgThumbnail = CriarImagemCompleta(imagem, ["w3-image"]);
    
        let divConteudo = CriarElementoComClasse("div", ["w3-container", "w3-center"]);
        let h4Titulo = CriarElementoComClasseTexto("h4", null, titulo);
        let pDescricao = CriarElementoComClasseTexto("p", ["w3-small"], descricao);
    
        AppendElementos(divConteudo, [h4Titulo, pDescricao]);
        AppendElementos(linkThumbnail, [imgThumbnail, divConteudo]);
    
        return linkThumbnail;
    }

    Você poderá ver pelo código que ele sempre terá 1/3 do comprimento do container dele em telas maiores e 100% em telas de smartphones. Isso pode ser adaptado simplesmente trocando as classes fornecidas no elemento linkThumbnail.

  • Criado um Media Card

    Por último criaremos o media card, uma espécie de cartão que possui uma imagem em sua lateral. Ele é um estilo bem utilizado para a criação de objetos representando notícias, lista de notícias ou posts com o gravatar.

    function CriarMedia(linkArquivo, titulo, descricao, imagem) {
        function AreaImagem() {
            let divImagem = CriarElementoComClasse("div", ["w3-quarter"]);
            divImagem.appendChild(CriarImagemCompleta(imagem, ["w3-image"]));
    
            return divImagem;
        }
    
        function AreaConteudo() {
            let divConteudo = CriarElementoComClasse("div", ["w3-threequarter", "w3-container", "w3-margin-bottom"])
            let h2Titulo = CriarElementoComClasseTexto("h2", ["w3-xlarge"], titulo);
            let pDescricao = CriarElementoComClasseTexto("p", null, descricao);
            let linkArquivo = CriarLinkCompleto(linkArquivo, ["w3-btn", "w3-theme-l4", "w3-border", "w3-border-theme", "w3-round-large"], "Saiba Mais");
    
            AppendElementos(divConteudo, [h2Titulo, pDescricao, linkArquivo]);
    
            return divConteudo;
        }
    
        let divMedia = CriarElementoComClasse("div", ["w3-row", "w3-margin", "w3-border-bottom", "w3-border-theme-l4", "mundojs-media"]);
    
        AppendElementos(divMedia, [AreaImagem(), AreaConteudo()]);
    
        return divMedia;
    }

    Apesar de ser um pouco mais extenso que as funções anteriores, o resultado fica bem legal e pode ser utilizado facilmente para gerar uma lista de newsfeed, comentários de posts entre outras opções.

Conclusão

Como você pode ver, foi possível criar diversas ferramentas para auxiliar na montagem de itens na tela. Na minha experiência pessoal, eles não auxiliam muito se você utiliza um site estático. No entanto, caso você esteja trabalhando com dados dinâmicos ou simplesmente informações que se repetem muito, este tipo de técnica auxilia muita a reduzir o HTML e o JS comparado a criação manual sob demanda.