HTML5

CSS Flexbox – Um Guia Interativo (Parte 2 – Itens)

Olá Web Developers!

No post anterior vimos as propriedades que usamos no container ao trabalhar com Flexbox. Agora veremos as propriedades que utilizamos nos itens do container.

Itens

Lembre-se que temos propriedades CSS para trabalhar com o elemento que possui nossos itens (container ou elemento pai) e propriedades para os nossos itens (elementos filhos).

Neste post veremos as propriedades que ficam nos elementos filhos.
Teremos basicamente um container com alguns itens dentro.

Para vermos a diferença das propriedades aplicadas em um item específico, vamos adicionar a este item a classe .selected.

<div class="container" >
    <div class="item" ></div>
    <div class="item selected" ></div>
    <div class="item" ></div>
</div>

order

Por padrão, os itens de um Flex Container são exibidos na ordem presente no HTML.

Com a propriedade order nós podemos alterar a ordem dos elementos. O valor deve ser um número inteiro, negativo ou positivo.

flex-grow

Indica o quanto um item pode crescer caso seja necessário. Deve ser um número inteiro positivo.

Isso significa que se todos os itens tiverem o valor 1, o espaço disponível será distribuído igualmente a todos eles.

Caso um dos itens tenha o valor 2, este item poderá ter duas vezes mais espaço do que os outros.

flex-basis

Define o tamanho padrão de um elemento antes do espaço disponível ser distribuído. O valor pode ser em px, %, em, etc.

Se o valor for auto, ele irá olhar para o valor de width e height do item.

Se o valor for content, ele irá olhar para o tamanho do conteúdo do item.

flex-shrink

Indica o quanto um item pode encolher caso seja necessário. Deve ser um número inteiro positivo.

Isso significa que se todos os itens tiverem o valor 1, o espaço disponível será distribuído igualmente a todos eles.

Caso um dos itens tenha o valor 2, este item poderá ter metade do espaço do que os outros.

flex

Esta propriedade é apenas um atalho para flex-grow, flex-shrink e flex-basis, nos permitindo declarar os valores em uma única propriedade.

.item.selected{
    flex: 2 4 50px;
}

align-self

Você deve se lembrar da propriedade align-items que vimos no post sobre as propriedades do container.

A propriedade align-self nos permite sobrescrever o valor desta propriedade para um único item. Assim podemos, por exemplo, colocar um único item no final de uma linha enquanto todos os outros estão no começo.

CSS Flexbox – Um Guia Interativo (Parte 1 – Containers)

Olá Web Developers!

Há um bom tempo que os navegadores já suportam bem o Flexbox. Porém, ainda há pessoas com algumas dúvidas sobre o seu funcionamento. Por isso desenvolvi um guia interativo para te ajudar a entender como o Flexbox funciona.

Se estiver com dúvidas entre usar Flexbox ou CSS Grid, confira o nosso post de comparação: https://www.treinaweb.com.br/blog/flexbox-ou-css-grid/

O que é Flexbox?

O Flexbox (Flexible Box) nos permite organizar, alinhar e distribuir itens dentro de um container. Com ele fica mais simples definir o tamanho e o alinhamento vertical e horizontal de itens.

Primeiro de tudo temos que saber que teremos propriedades CSS para trabalhar com o elemento que possui nossos itens (container ou elemento pai) e propriedades para os nossos itens (elementos filhos).

Container

Neste primeiro post veremos as propriedades que ficam no elemento pai dos nossos itens, o container.
Teremos basicamente um container com três itens dentro.

<div class="container" >
    <div class="item" ></div>
    <div class="item" ></div>
    <div class="item" ></div>
</div>

display

Primeiro precisamos definir que o nosso container é do tipo “flex”; Fazemos isso com a propriedade “display”.
No exemplo abaixo, utilize o checkbox para ligar/desligar o Flexbox.

flex-direction

Indica a direção dos itens, definindo o que vamos chamar de eixo principal (main-axis).

  • row (padrão): da esquerda para direita
  • row-reverse: inverso de row
  • column: de cima para baixo
  • column-reverse: inverso de column

flex-wrap

O comportamento padrão dos itens de um elemento flex é ficar em uma única linha. Se a largura total de todos os itens for maior do que o espaço disponível, os itens continuarão na mesma linha.

Esta propriedade permite que os itens sejam jogados em outra linha caso não haja mais espaço na linha.

  • nowrap (padrão): todos os itens ficam em uma única linha
  • wrap: os itens que não cabem na linha são jogados para baixo
  • wrap-reverse: os itens que não cabem na linha são jogados para cima

flex-flow

Esta propriedade é apenas um atalho para flex-direction e flex-wrap, nos permitindo declarar o valor de ambos em uma única propriedade.

.container{
    display: flex;
    flex-flow: row wrap;
}

justify-content

Define o alinhamento dos itens ao longo do eixo principal.

  • flex-start (padrão): os itens ficam junto no começo da linha
  • flex-end: os itens ficam juntos no final da linha
  • center: os itens ficam centralizados na linha
  • space-between: os itens são distribuídos igualmente no espaço disponível. O primeiro item fica no começo da linha e o último fica no final.
  • space-around: os itens são distribuídos igualmente no espaço disponível ao redor deles.
  • space-evenly: os itens são distribuídos igualmente no espaço disponível.

flex-direction: column

Lembre-se que esta propriedade alinha os itens em relação ao eixo principal. Isso significa que se você mudar o valor de flex-direction, a direção do posicionamento será outra.

align-items

Define o alinhamento dos itens perpendicularmente em relação ao eixo principal.
Pense nele como um justify-content, mas que alinhará os itens no outro eixo.

  • stretch (padrão): estica os elementos para preencherem o container.
  • flex-start: os itens ficam junto no começo do eixo perpendicular
  • flex-end: os itens ficam juntos no final do eixo perpendicular
  • center: os itens ficam centralizados no eixo perpendicular
  • baseline: parecido com o center, mas usando a base da linha como referência. No exemplo abaixo, note como os textos dos itens ficam alinhados.

flex-direction: column

Lembre-se que esta propriedade alinha os itens em relação ao eixo principal. Isso significa que se você mudar o valor de flex-direction, a direção do posicionamento será outra.

align-content

Alinha as linhas do container.
Por alinhar as linhas, esta propriedade só tem efeito quando há mais de uma linha.

  • stretch (padrão): estica as linhas para preencherem o espaço restante.
  • flex-start: as linhas ficam juntas no começo do container
  • flex-end: as linhas ficam juntas no final do container
  • center: as linhas ficam centralizadas no container
  • space-between: as linhas são distribuídas igualmente. A primeira linha fica no começo do container e a última fica no final.
  • space-around: as linhas são distribuídas igualmente no espaço disponível ao redor delas.

flex-direction: column

Lembre-se que esta propriedade alinha os itens em relação ao eixo principal. Isso significa que se você mudar o valor de flex-direction, a direção do posicionamento será outra.

Playground

Para testar, brinque um pouco com cada uma das propriedades para ver as possibilidades:

Templates gratuitos para aplicações administrativas

Com a necessidade da criação de aplicações em um menor tempo possível, é cada vez mais viável a utilização de templates prontos para reduzir o tempo de desenvolvimento. Por isso, diversos templates, principalmente para áreas administrativas, foram sendo criados e compartilhados na internet, dos quais veremos alguns neste artigo.

AdminLTE

O AdminLTE é um template administrativo css gratuito todo construído sobre o Bootstrap 3. Em sua recente atualização, algumas novidades foram adicionadas, tais como: Reescrita completa do JavaScript, suporte NPM e Bower, além de sua documentação. Open source, o AdminLTE é uma excelente opção aos desenvolvedores que buscam componentes responsivos e reutilizáveis.

A partir do link (https://adminlte.io/themes/AdminLTE/index2.html) é possível ter um Live Preview do template e testar todas as suas funcionalidades antes de realizar seu download.

O download da ferramenta pode ser feito através do link: https://adminlte.io/

CoreUI

O CoreUI é um template gratuito baseado no Bootstrap 4 para criação de interfaces administrativas funcionais e sofisticadas. Trabalha com uma grande variedade de frameworks, tais como: Angular, Laravel e React, o que permite que este template seja utilizado nos mais diversos projetos.

A partir do link (https://coreui.io/demo/#main.html) é possível ter um Live Preview do template e analisar sua vasta biblioteca de componentes, que trás consigo as vantagens em adicionar diversos botões, formulários e muitos outros componentes para facilitar o desenvolvimento.

Seu download pode ser feito através do link: https://coreui.io/

Light Bootstrap

Seguindo a mesma linha dos dois templates citados anteriormente, o Light Bootstrap é um template administrativo gratuito baseado no Bootstrap 4, desenhado para ser bonito e simples, além de facilitar a criação de aplicações administrativas. Provê uma grande coleção de elementos que possibilita a criação de apps das mais variadas formas.

Sua barra lateral pode ser alterada entre 6 cores diferentes (preto, azul, verde, laranja, vermelho e roxo), tornando sua experiência muito mais confortável.

É possível acessar sua Live Preview através do link (https://demos.creative-tim.com/light-bootstrap-dashboard/).

Seu download pode ser realizado acessando o link: https://github.com/creativetimofficial/light-bootstrap-dashboard

Material Dashboard

O Material Dashboard, apesar de ser construído utilizando o Bootstrap 4, possui uma interface inspirada nos padrões de design do Google, o Material Design.

Seu visual é limpo e elegante, tornando-se uma ótima alternativa. Além disso, o Material Dashboard possui 60 componentes dos mais variados tipos e três páginas de exemplo para você iniciar seus projetos.

Sua Live Preview pode ser acessada no link (https://demos.creative-tim.com/material-dashboard/examples/dashboard.html?_ga=2.925873.104232430.1547748278-1145022817.1547748278) onde é possível ter uma breve visualização do template, antes de realizar seu download.

Após analisar suas funcionalidades, o download pode ser feito através do link: https://www.creative-tim.com/product/material-dashboard

Star Admin

Com uma aparência fantástica, o Star Admin é, com certeza, uma ótima opção a considerar quando queremos desenvolver um sistema administrativo. Também construído utilizando o Bootstrap 4, este template possui um visual único e arrojado, tornando sua aparência um ponto fortíssimo.

Além disso, o Star Admin possui uma grande coleção de widgets e componentes para os mais variados usos.

A partir do link (http://www.bootstrapdash.com/demo/star-admin-free/jquery/index.html) é possível acessar a Live Preview deste tamplete e seu download, feito através do link: https://www.bootstrapdash.com/product/star-admin-free/

Conclusão

Neste artigo vimos alguns templates para utilizarmos no desenvolvimento de aplicações administrativas e o quanto eles agilizam a criação de novos projetos.

Estilizando formulários automáticos do Django com Bootstrap

No artigo passado “Criando formulários automaticamente com Django“, vimos o quão simples é a criação de formulários automáticos com o Django. Porém, os formulários gerados utilizam HTML puro, ou seja, não há nenhuma estilização para melhorar o visual da aplicação. Sendo assim, neste artigo veremos como estilizar os formulários gerados automaticamente com o Django utilizando o Bootstrap.

Instalando e configurando o crispy-forms

O primeiro passo para estilizar os formulários de uma aplicação é instalar a biblioteca crispy-forms, é ela quem irá estilizar os formulários da nossa aplicação. Para isso, vamos até a aba Project Interpreter do PyCharm, buscamos por django-crispy-forms e instalamos a biblioteca:

Após isso, vamos até o arquivo settings.py do projeto e registramos a biblioteca. Para isso, no array INSTALLED_APPS, adicionamos a seguinte linha:

INSTALLED_APPS = [
    ...
    'crispy_forms',
    'app',
]

Com isso, indicamos ao nosso projeto que faremos uso da biblioteca crispy-forms. O próximo passo é determinar qual framework utilizaremos para estilizar nossos formulários. O crispy-forms possui suporte aos seguintes:

  • bootstrap
  • bootstrap3
  • bootstrap4
  • uni-form
  • foundation

Para definir qual será utilizado, precisamos adicionar a configuração CRISPY_TEMPLATE_PACK logo após o array INSTALLED_APPS do arquivo settings.py e determinar qual framework será utilizado. Neste artigo usaremos o bootstrap4, conforme podemos ver abaixo:

INSTALLED_APPS = [
    ...
    'crispy_forms',
    'app',
]
CRISPY_TEMPLATE_PACK = 'bootstrap4'

Estilizando os formulários

Após instalar e configurar o crispy-forms, precisamos configurar o formulário para utilizar o bootstrap4. Para isso, no arquivo responsável por renderizar o formulário de cadastro de usuários, precisamos carregar a biblioteca crispy-forms, importar o bootstrap via CDN e, por fim, indicar que usaremos o a biblioteca para estilizar o formulário do Django. No final, o conteúdo do formulário possuirá a seguinte estrutura:

<!DOCTYPE html>
{% load crispy_forms_tags %} ## Carregando a biblioteca
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cadastro</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> ## Importando o bootstrap
</head>
<body>
<main class="container">
{{ form|crispy }} ## Determinando que usaremos o crispy forms
<button class="btn btn-primary">Cadastrar</button>
</main>
</body>
</html>

Ao final, o formulário que antes era assim:

Será renderizado assim:

Tudo isso, novamente, de forma automática e sem escrever uma única linha de código HTML. 😀

Criando formulários automaticamente com Django

A criação dos formulários de uma aplicação pode se tornar um processo demorado e cansativo, caso tenhamos diversas entidades com vários atributos. Por exemplo, imagine criar os formulários de uma aplicação que possui 20 cadastros com 50 campos cada… É muito HTML, certo!?

Com o Django, podemos simplificar todo este processo criando formulários automaticamente a partir de como os models estão definidos. E é isso que veremos neste artigo 😀

Entendendo a aplicação

Vamos partir de uma aplicação pronta que possui apenas uma entidade definida em nosso arquivo models.py, como pode-se ver abaixo:

class Usuario(models.Model):
    SEXO_CHOICES = [
        ["F", "Feminino"],
        ["M", "Masculino"],
        ["N", "Nenhuma das opções"]
    ]

    nome = models.CharField(max_length=20, null=False)
    email = models.EmailField(null=False)
    sexo = models.CharField(max_length=1, choices=SEXO_CHOICES)

Além disso, a aplicação inicial possui um método no arquivo views.py que renderiza o template form.html, o qual nós usaremos para carregar o formulário automático:

from django.shortcuts import render

def cadastrar_usuario(request):
    return render(request, "form.html")

Já o arquivo form.html possui a seguinte estrutura:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cadastro</title>
</head>
<body>

Aqui será renderizado o formulário de cadastro

</body>
</html>

Criando forms.py

Agora, para gerar nosso formulário de cadastro com base nos campos que definimos no arquivo models.py, precisamos criar o arquivo forms.py. É ele quem é o responsável por determinar quais campos possuirá nosso formulário de cadastro de usuários.

Para criar nosso formulário, utilizaremos como base os tipos e regras de validação que definimos no arquivo models.py. Sendo assim, o arquivo forms.py terá o seguinte conteúdo:

from django import forms
from .models import *

class UsuarioForm(forms.ModelForm):
    class Meta:
        model = Usuario
        fields = ["nome", "email", "sexo"]

Gerando formulário automaticamente

Após criar o arquivo forms.py, podemos utilizá-lo para renderizar nosso formulário sem escrever uma única linha de HTML. Para isso, alteramos o método cadastrar_cliente do arquivo views.py da seguinte forma:

from django.shortcuts import render
from .forms import *

def cadastrar_usuario(request):
    form = UsuarioForm()
    return render(request, "form.html", {'form':form})

Com isso, estamos criando uma instância nova da nossa classe UsuarioForm e a enviando até o arquivo form.html. É lá que renderizamos nosso formulário de cadastro, como podemos ver abaixo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cadastro</title>
</head>
<body>
{{ form.as_p }}
</body>
</html>

Apenas utilizando o {{form.as_p}} conseguimos renderizar nosso formulário de cadastro completo. Isso se dá porque o Django converte o código definido no arquivo models.py e cria, para cada atributo da classe Usuario, um input HTML. No final, o resultado da página HTML é o seguinte:

Além disso, cada input gerado possui as regras de validação que determinamos no arquivo models.py, ou seja, todos eles são required e o input de e-mail só irá aceitar um e-mail válido como valor.

Concluindo

Uma das tarefas mais cansativas quando estamos criando aplicações web é a criação dos formulários de cadastro. Com o Django, conseguimos renderizar um formulário automaticamente, poupando tempo no desenvolvimento. Há também formas de estilizar este formulário automaticamente, mas veremos em um artigo futuro. Até lá! 😀

Criando páginas para repositórios com o GitHub Pages

O GitHub é uma das maiores ferramentas para armazenamento e gestão dos nossos projetos. Ele possui um recurso bem interessante que facilita a divulgação e apresentação dos projetos lá hospedados. Este recurso é o GitHub Pages, que permite que criemos uma página web para nossos repositórios totalmente gratuita. Legal né? Então fica ligado que neste artigo veremos como criar uma página de apresentação para um repositório.

Criando o repositório:

A primeira coisa a se fazer é criar um repositório no GitHub para que consigamos gerar a página web para ele. Para isso, vamos até a rota https://github.com/new e configuramos todas as suas preferências:

Nesta página vamos informar o nome do repositório, sua descrição e o tipo de visibilidade (público ou privado). Feito isso, clicamos no botão verde “Create repository”.

Ativando o GitHub Pages:

Após isso, o repositório será criado e seremos redirecionados para sua tela inicial. Lá, clicamos no botão “Settings” no menu superior da tela. A partir disso, seremos redirecionados para a tela de configurações do repositório que, dentre diversas configurações, existe uma seção chamada “GitHub Pages”, conforme podemos ver abaixo:

Nesta seção há duas opções. Podemos criar uma página a partir de um código presente no próprio repositório ou por meio de um modelo disponibilizado pelo próprio GitHub. Caso você queira desenvolver sua própria página, selecione a branch que você quer salvar seu arquivo index.html e clique no botão save (primeira parte da seção).

Selecionando o tema

Para este artigo, vamos selecionar um modelo disponibilizado pelo próprio GitHub. Sendo assim, clicamos no botão “Choose a theme”. Feito isso, uma nova página será aberta onde podemos ver a lista de todos os temas disponíveis para uso:

Agora é só selecionar o que você prefere e clicar no botão verde “Select Theme”. Feito isso, uma janela para que possamos customizar a página do nosso repositório será aberta. Vale lembrar que as informações são escritas em Markdown, por isso precisamos seguir este formato.

Após editar o conteúdo da nossa página, vamos até o final da mesma e clicamos em “Commit Changes”. Isso irá gerar um novo commit com as mudanças feitas.

Finalmente, após todos estes passos, já podemos acessar a página do repositório através da rota:

https://treinaweb.github.io/repositorio_teste_github_pages/

Concluindo:

Com isso, notamos o quão fácil é criar uma página de apresentação para nossos repositórios de forma totalmente gratuita. Podemos, também, utilizar projetos um pouco mais complexos utilizando HTML, CSS e JavaScript, mas isso fica para um próximo artigo, ok? 🙂

Um abraço e até lá!

Como um jogo digital é criado?

Olá, Web Developers!

Hoje vou mostrar como um jogo é criado. Para podermos ver ele funcionando aqui no navegador, usaremos JavaScript, mas esse conceito é basicamente o mesmo na criação de jogos com outras linguagens, frameworks e ferramentas, então nem é preciso conhecer a linguagem para entender.

Depois, mostrarei como os conceitos apresentados aqui estão presentes em ferramentas profissionais.

Vamos lá!

A tela (canvas)

Um jogo precisa de um lugar que nos possibilite exibir imagens. Normalmente esse elemento é chamado de canvas, que significa “tela de pintura”. Esse é um elemento que nos permite desenhar e renderizar imagens nele.

No Java e no C# por exemplo, temos a classe Canvas. No HTML5 possuímos o elemento <canvas>, que é o que iremos usar. Será o nosso único HTML. Todo o resto será desenhado no canvas.

Também teremos um CSS simples só para alinhar o canvas no meio da tela.

<canvas id="myCanvas" width="400" height="200" ></canvas>
canvas{
    border: 1px solid black;
    margin: 0 auto;
    display: block;
}

Agora todo o resto será JavaScript!

Desenhando na tela

Vamos fazer um simples desenho no canvas.

// primeiro selecionamos o elemento canvas
const canvas = document.querySelector('#myCanvas');
/* depois pegamos o contexto, que irá nos fornecer as funções
para desenhar no canvas.
*/
const ctx = canvas.getContext('2d');

/* a função "fillRect()" nos permite desenhar um retângulo.
Passamos a posição x, posição y, largura e altura.
*/
ctx.fillRect(25, 25, 50, 50);

Quadrado no Canvas

O que é uma animação?

Uma animação é basicamente a apresentação de várias imagens ligeiramente diferentes. Isso nos passa a ilusão de movimento.

Kirby Walking Sprite

Kirby Walking Sprite

No exemplo acima temos várias imagens que, ao serem exibidas uma após a outra, nos fazem pensar que estamos vendo o personagem se mover.

Cada imagem é chamada de frame(quadro). Quanto mais frames por segundo (FPS), mais natural será a ilusão de movimento. Os jogos hoje em dia costumam trabalhar em 60 FPS.

Então, o que acontece se pegarmos o canvas, limpá-lo, desenhar, limpá-lo novamente e fazer um desenho levemente diferente? Isso mesmo! Teremos a ilusão do movimento.

Para isso, basta desenharmos o quadrado com uma posição diferente a cada momento. Então podemos armazenar a posição em uma variável e criar um looping.

O Looping

Como os jogos são basicamente uma tela de desenho com vários elementos sendo desenhados a todo instante, uma das partes principais de um jogo é o Looping.

Basicamente teremos um Looping Infinito que limpa a tela, desenha os elementos no canvas baseado nas variáveis que possuímos e repete esse processo sem parar.

Vamos mudar um pouquinho o nosso código para ver o que acontece.

const canvas = document.querySelector('#myCanvas');
const ctx = canvas.getContext('2d');
/* declaramos uma variável que armazenará a posição
x do nosso quadrado.
*/
let x = 0;
/* o "setInterval()" repete a execução de uma
função de acordo com um tempo que passamos.
Neste caso, a função se repeta a cada 50 milissegundos.
Isso significa que desenharemos no canvas 20 vezes por
segundo, ou seja, teremos 20 frames por segundo.
*/
setInterval(function(){
    // aqui estamos limpando o canvas inteiro
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // após limpar o canvas, desenhamos o quadrado
    // na posição x
    ctx.fillRect(x, 25, 50, 50);
    // após desenhar o quadrado, alteramos nossa
    // variável x
    x+= 1;
    /* só para não perdermos o quadrado de vista,
    fiz com que o x volte a 0 caso o quadrado
    saia do canvas
    */
    if(x > canvas.width){
        x = 0;
    }
}, 50);

Isso fará com que o quadrado ande pela tela, como você pode ver logo abaixo:

Observação: No JavaScript, ao fazer animações, é recomendado o uso da função requestAnimationFrame() ao invés de setTimeout() ou setInterval();

Carregando imagens

Jogos utilizam vários recursos como áudio e imagens. Vamos criar uma função que irá carregar imagens.

Se tentarmos desenhar a imagem antes dela ter sido carregada, ocorrerá um erro. Então vamos aproveitar as Promises do JavaScript para iniciar o desenho no canvas apenas quando a imagem já estiver carregada.

// ...
/* essa função receberá o endereço de uma imagem
*/
function loadImage(src){
    /* ela retorna uma promise, que permite a
    execução de uma função apenas quando ela
    for resolvida
    */
    return new Promise(resolve => {
        /* criamos um elemento de imagem para
        carregar a imagem.
        */
        var img = document.createElement('img');
        /* criamos um listener que será executado
        assim que a imagem for carregada. Quando a
        imagem terminar de ser carregada, resolvemos
        a promise, retornando a imagem.
        */
        img.addEventListener('load', () => { 
            resolve(img); 
        });
        /* pegamos o elemento de imagem e passamos
        o endereço da imagem. Isso iniciará o
        carregamento
        */
        img.src = src;
    });
}

/* iniciamos o carregamento da imagem. Assim que
a imagem for carregada, a promise é resolvida e
a função seguinte é executada.
*/
loadImage('https://i.imgur.com/WyqxuaD.png')
    .then(function(sprite){
        setInterval(function(){
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            // desenhamos a imagem ao invés do retângulo
            ctx.drawImage(sprite, x, 25, 50, 50);
            x+= 1;
            if(x > canvas.width){
                x = 0;
            }
        }, 50);
  })

Com isso teremos o Kirby passando pela tela.

Para não termos que tratar a criação de uma animação, usei aqui uma imagem estática mesmo.

Organizando o código: O objeto Game

Até agora só fizemos bagunça. Vamos organizar mais o nosso código, o que nos permitirá ter mais controle também.

const canvas = document.querySelector('#myCanvas');

/* alterei levemente a função de carregar
imagens. Agora ele recebe um objeto em
que armazenaremos a imagem carregada,
e também passamos o nome do campo
em que a imagem será armazenada.
*/
function loadImage(src, storage, field){
    return new Promise(resolve => {
        var img = document.createElement('img');
        img.addEventListener('load', () => {
            storage[field] = img;
            resolve(img);
        });
        img.src = src;
    });
}
/* Todo o código que controla o jogo
ficará dentro desse objeto "Game"
*/
const Game = {
/* guardei o contexto do canvas dentro de Game
*/
    ctx : canvas.getContext('2d'),
/* a função start() será responsável por iniciar
o jogo. Ela executa a função load() e, quando
tudo estiver carregado, inicia o looping.
*/
    start(){
        this.load().then(() =>{
        /* guardo o interval na variável timer.
        Assim seremos capazes de parar o looping do
        jogo caso seja necessário.
        */
            this.timer = setInterval(() => {
            /* o looping executa essas duas funções.
            Logo veremos o que elas fazem.
            */
                this.update();
                this.draw();
            }, 30);
        })
    },
    /* a função stop() limpa o nosso interval, fazendo
    o jogo parar de ser executado.
    */
    stop(){
        clearInterval(this.timer);
    },
    /* a função load() é onde nós iremos carregar nossas
    imagens. Quando tudo é carregado, ele retorna uma promise.
    Assim garantimos que o jogo só será inicado quando
    todos os recursos estiverem carregados.
    */
    load(){ 
        return loadImage('https://i.imgur.com/k6heF1k.png', Game, 'background');
    },
    /* criei a função clear() para facilitar a limpeza do canvas.
    */
    clear(){
        this.ctx.clearRect(0, 0, canvas.width, canvas.height);
    },
    /* a função draw() será responsável por executar
    tudo o que for relacionado em desenhar algo no canvas.
    Em sua primeira linha nós já executamos o clear().
    */
    draw(){
        this.clear();
        this.ctx.drawImage(this.background, 0, 0, canvas.width, canvas.height);
    },
    /* a função update() serve para atualizarmos algum valor.
    Imagine que você queira criar um "relógio". Como a 
    função update() fica sendo executada pelo looping,
    podemos ir atualizando o tempo nela. Com o valor
    alterado, a função draw() cuidará do resto.
    */
    update(){
    }
}

/* chamamos essa função para iniciar o jogo.
Por enquanto tiramos o Personagem. Temos só
o fundo. Criaremos o personagem a seguir.
*/
Game.start();

Criando um personagem: O objeto Character

Agora que temos o objeto Game cuidando de tudo, está mais fácil criarmos outros objetos que estarão presentes no nosso jogo.

Vamos criar um personagem que poderemos controlar.

Em um jogo real, para poder reutilizar o código, seria mais comum criarmos uma classe. Mas como a ideia aqui é simplificar só para fins didáticos, eu vou criar um objeto literal mesmo.

// criamos o objeto Character para o nosso personagem
const Character = {
/* declaramos algumas variáveis que nos permitirão
ter mais controle do personagem.
Ao criar o seu jogo, poderá criar as variáveis que quiser.
*/
    x: 50, // controla a posição horizontal
    y: 125, // controla a posição vertical
    speed: 5, // controla a velocidade do movimento
    /* a função start() é executada apenas uma vez
    quando o personagem é inserido na tela
    */
    start(){
    /* aqui aproveitamos a funçõa start() para
    começar a escutar eventos do teclado.
    Verificamos se determinada tecla está sendo
    pressionada, e assim alteramos o valor da
    variável x, que fará com que o personagem
    seja desenhado em uma posição diferente,
    dando a ilusão de movimento.
    */
        window.addEventListener('keypress', (event) => {
            const key = event.key;
            switch(key){
                /* note que alteramos o valor
                da variável de posição com o valor
                que indicamos na variável de velocidade.
                */
                case 'a': this.x -= this.speed; break;
                case 'd': this.x += this.speed; break;
            }
        });
    },
    /* a função draw recebe o contexto do canvas e
    desenha a imagem do personagem, armazenada na
    variável sprite.
    Veja que desenhamos com base nas variáveis
    que declaramos.
    */
    draw(ctx){
        ctx.drawImage(this.sprite, this.x, this.y, 32, 30);
    },
    /* e também declaramos uma função update() caso
    seja preciso.
    */
    update(){
    }
}

Inserindo o personagem no jogo

Agora que temos um objeto Character pronto para ser usado, temos que inseri-lo no jogo. Vamos então fazer algumas alterações no objeto Game para inserir nosso personagem no jogo.

const Game = {
    // ...
    start(){
        // chamamos o start() do personagem.
        Character.start()
        this.load().then(() =>{
            this.timer = setInterval(() => {
                this.update();
                this.draw();
            }, 30);
        })
    },
    // ...
    load(){
    /* agora estamos fazendo com que o load()
    aguarde o carregamento do sprite do personagem
    e do background do jogo.
    */
        return Promise.all([
            /* carregamos o sprite do personagem
            e armazenamos a imagem na propriedade
            sprite dentro de Character
            */
            loadImage('https://i.imgur.com/WyqxuaD.png', Character, 'sprite'),
            loadImage('https://i.imgur.com/k6heF1k.png', Game, 'background'),
        ]);
    },
    // ...
    draw(){
        this.clear();
        this.ctx.drawImage(this.background, 0, 0, canvas.width, canvas.height);
        /* Adicionamos a chamada da função draw()
        de Character
        */
        Character.draw(this.ctx);
    },
    // ...
}

Agora sim temos a seguinte tela:

Kirby - Green Greens

E com as teclas “A” e “D” você pode controlar o Kirby para a direita e esquerda.

O que aprendemos sendo usado na prática

Vamos ver o que aprendemos sendo usado por ferramentas profissionais.

Phaser

Phaser

Uma ferramenta muito usada para criar jogos com JavaScript é o Phaser.

https://phaser.io/examples/v2/games/breakout

No link acima temos um exemplo de um jogo clássico. Se você olhar o código que está junto, verá que o funcionamento é bem parecido com o código que criamos manualmente:

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update });
/*
Iniciamos um novo jogo com a função "Phaser.Game()".
Para essa função, passamos o tamanho do canvas
(800x600).
No final, temos um objeto que passa as funções
preload(), create() e update().
preload() serve para carregar os recursos do
jogo antes dele ser iniciado, e para isso chamamos
"game.load".
create() é a função executada uma única vez
quando o jogo é criado.
update() é a função que é executada várias
vezes enquanto o looping estiver ativo.
*/

Game Maker

GameMaker Studio

O GameMaker é muito conhecido por possibilitar que as pessoas criem jogos sem saber programar. Você pode simplesmente arrastar ícones para criar a lógica do seu jogo.

Apesar disso, o GameMaker possui uma linguagem de programação própria que é bem simples de se aprender, possibilitando fazer coisas bem mais avançadas.

GameMaker IDE

Note que na edição da lógica temos a parte “Events”. Nele temos o evento “Create” (igual ao que conhecemos) e o evento “Step” (igual ao update). Vários outros eventos podem ser adicionados.

Unity3D

Unity3D

Outra ferramenta bem conhecida é o Unity3D, uma ferramenta bem completa para a criação de jogos e que exporta código nativo para mais de 25 plataformas. A linguagem usada é o C#.

Adam

Vamos dar uma pequena olhada em uma classe criada com C# para o Unity:

using UnityEngine;
using System.Collections;

public class Character : MonoBehaviour {

    public float speed = 0.5f;

    // Use this for initialization
    public void Start () {
        // ...
    }

    // Update is called once per frame
    public void Update () {
        // ...
    }
}

Com o Unity temos uma IDE completa para o desenvolvimento de jogos. Note que ainda temos funções como Start() e Update().
Agora você já sabe o que essas funções fazem né?

Também temos outros métodos que são chamados em determinados momentos, que facilitam muito na hora de desenvolver as ações. Um exemplo é o Awake(), OnGUI(), OnDestroy(), etc.

Conclusão

Entender como um jogo funciona é uma ótima base para conseguirmos entender como as ferramentas para a criação de jogos funcionam, facilitando o aprendizado.

Vimos então que jogos possuem um looping que desenha em uma tela com base nas variáveis, as quais podem ser alteradas de acordo com nossas ações. E esse conceito está presente em todas as ferramentas de desenvolvimento de jogos, desde as mais simples até as mais profissionais.

As ferramentas nos ajudam a tratar o carregamento de arquivos, como executar áudio e vídeo, como renderizar imagens, simular física (colisões, gravidade, atrito, etc), construção de cenários e posicionamento de objetos, desenvolvimento de animações, gerenciamento dos controles, otimização de memória, etc.

Novidades do HTML 5.2

Olá, Web Developers!

No final de 2017 o HTML 5.2 se tornou uma recomendação oficial da W3C. Vejamos algumas das novidades.

Elemento <dialog>

Uma das principais adições é o elemento “, que nos permite criar modais de forma nativa no HTML. No momento apenas o Chrome dá suporte a esse elemento.

Por padrão ele fica escondido. Para que ele apareça, basta selecioná-lo com JavaScript e executar o método show();

<dialog>
  <h1>Olá Web Developers!</h1>
</dialog>

<button id="open">Abrir Modal</button>
<button id="close">Fechar Modal</button>
const dialog = document.querySelector("dialog");

document.querySelector("#open").addEventListener("click", () => {  
  dialog.show();
});

document.querySelector("#close").addEventListener("click", () => {  
  dialog.close();
});

Usando a API Payment Request a partir de iframes

Antes do HTML 5.2, pagamentos que usassem a API Payment Request não poderiam ser feitos a partir de um iframe embutido em sua página.

Agora os iframes aceitam o atributo allowpaymentrequest, permitindo que a página com iFrame faça uso do serviço.

<iframe allowpaymentrequest>

Funcionalidades depreciadas

Algumas funcionalidades foram consideradas ruins, obsoletas ou foram trocadas por algo melhor.

  • elementos keygen, menu e menuitem
  • atributo inputmode do <input> e o atributo dropzone
  • o método showModalDialog() (como visto acima, agora é apenas show())
  • a API Plugin foi marcada como obsoleta

Práticas que agora são válidas

Há algumas práticas que antes não eram recomendadas, mas que agora elas são consideradas válidas.

<style> no <body>

Sim, isso já funcionava. Porém, seu documento ficaria como inválido. Agora é considerado válido ter elementos style no meio do body. Mesmo assim, prefira evitar.

Vários elementos <main>

O elemento <main> indica a parte principal de um documento e até então só podia existir um.

Isso mudou e agora é válido ter mais de um <main> em um mesmo documento, desde que apenas um esteja visível.

<main>...</main>
<main hidden >...</main>
<main hidden >...</main>

Cabeçalhos em elementos <legend> em um <fieldset>

Os elementos <legend> dentro de um <fieldset> apresentam uma legenda para os campos de um formulário.

Antes só era válido ter texto dentro dos elementos <legend>, mas agora pode-se colocar os elementos <h1>, <h2>, <h3>, etc

<fieldset>
    <legend>
        <h2>Contato</h2>
    </legend>
</fieldset>

<div> como elemento filho de <dl>

O elemento <dl> serve para criarmos listas descritivas, ou seja, uma lista de descrições de algo.

Antes não eram aceitas divs como elementos filhos, mas agora é.

<dl>
   <div>Treinaweb</div>
   <dt>JavaScript</dt>
   <dd>Linguagem Interpretada</dd>
   <dd>Multi Paradigma</dd>
</dl>

Práticas que não são mais válidas

Algumas práticas tornaram-se obsoletas.

Filhos de <p>, agora só textos

Agora o elemento <p> só poderá ter conteúdo de texto (e os marcadores de texto, como <a>, <span>, <strong>, etc).

Isso significa que elementos do tipo inline-blocks, inline-tables ou elementos do tipo block com alguma posição ou flutuantes não são mais considerados filhos válidos.

Conteúdo com strict doctype do HTML4 ou XHTML1

Isso significa que as seguintes declarações não são mais válidas:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

Já conhece os nossos cursos de HTML5? Se não, dê uma olhadinha! 🙂

Devo transformar meu site em uma PWA?

Olá, Web Developers!

Vocês sabem o que são PWA’s? Será que vale a pena transformar uma página web em uma PWA?

O que são PWA’s?

PWA vem de “Progressive Web App” e a ideia é juntar o melhor dos aplicativos nativos e tecnologias web. É importante notar que não estamos falando de aplicativos híbridos.

PWA’s são aplicações web comuns, então só precisamos de HTML, CSS e JavaScript. Porém, possuem características que fazem o usuário se sentir em um aplicativo nativo.

Aqui as características que definem uma PWA:

1. São progressivas

Elas vão funcionar em qualquer contexto, não importando o dispositivo ou navegador. Deve-se verificar se alguma funcionalidade que você vai usar encontra-se disponível no navegador do seu usuário. Se não, proporcionar algum comportamento para que a página não quebre e passe uma má experiência.

2. São responsivas

A interface e funcionalidades se adequam a qualquer tamanho de tela, desde um pequeno smartphone até uma grande Smart TV.

3. Não precisam de conexão

Nós projetamos essas aplicações para poderem funcionar mesmo quando o usuário não estiver conectado, usando o Cache para servir os arquivos e o Storage do navegador para armazenar dados.

4. Parecem aplicativos

Criamos a interface e as interações de modo que se pareçam com um aplicativo ao invés de um simples site.

5. Sempre Atualizadas

Fazemos com que a aplicação sempre esteja atualizada. As aplicações podem sincronizar em background, mesmo quando estiverem fechadas.

6. Seguras

PWAs devem ser obrigatoriamente fornecidas pelo protocolo HTTPS.

7. Fáceis de Descobrir

Criamos um arquivo de manifesto para que eles possam ser identificados como “aplicativos”, e por ser uma página web, os mecanismos de busca, como o Google, conseguem indexá-los.

8. Envolvente

Podemos estimular a interação do usuário com a aplicação graças às notificações.

9. Instaláveis

Os apps podem ser salvos na tela inicial como um aplicativo instalado, dispensando a necessidade do usuário abrir o navegador.

10. Simples de Compartilhar

Por serem páginas web, podem ser facilmente compartilhadas por sua URL.

Steve Jobs já pensava nisso em 2007

Em 2007, a ideia original de Steve Jobs para o iPhone era que os aplicativos fossem aplicações web.

Segundo ele:

Toda a engine do Safari está dentro do iPhone. Sendo assim, vocês podem escrever incríveis aplicativos para a Web 2.0 com Ajax que se parecem e se comportam exatamente como aplicativos no iPhone. E esses aplicativos podem se integrar perfeitamente com os serviços do iPhone. Eles podem fazer chamadas, enviar um email e procurar por uma localização no Google Maps.

E, adivinha? Não há SDK que você precise! Você tem tudo o que precisa se você souber como escrever aplicativos usando os mais modernos padrões web para escrever aplicativos incríveis para o iPhone hoje. Então, desenvolvedores, achamos que temos uma história muito doce para vocês. Vocês podem começar a construir seus aplicativos para iPhone hoje.

Mas, essa ideia foi alterada em 2008.

Quem usa?

Um ótimo lugar para ver uma lista de PWA’s é o site PWA Rocks.

Várias companhias grandes estão testando PWA e integrando em seus sites, como Washington Post e Flipboard, e outras estão começando a lançar sites betas para testes.

O Twitter Lite é uma PWA completa, e você pode acessá-la por: https://mobile.twitter.com

Quando usar PWA?

Caso precise de várias funcionalidades nativas do dispositivo ou um processamento mais pesado, então pode ser melhor criar um app nativo mesmo. Caso esteja pensando em criar um site ou webapp, criar como PWA é uma boa escolha.

Se você já tem um site ou uma aplicação web, você pode implementar aos poucos as características que definem uma PWA, como notificações, cache de arquivos e dados para o usuário poder acessar offline (que faz a página carregar mais rapidamente também), a possibilidade de salvar o app na tela inicial, receber atualizações de dados mesmo quando estiver com o app fechado, etc.

Implementar apenas algumas dessas características não fará com que você tenha uma PWA completa, mas terá pelo menos uma aplicação otimizada.

Caso queira saber mais sobre o assunto, acabamos de lançar um curso completo sobre PWA aqui no TreinaWeb. Confira:

Quando usar sessionStorage e localStorage?

Olá, Web Developers!

Hoje vou falar sobre um erro comum que vejo muitos colegas cometerem: usam o localStorage para armazenar variáveis temporárias.

Quem usa sabe que o localStorage nos permite armazenar dados de forma simples e sem expiração, ou seja, ficam lá enquanto não apagarmos por código ou pelo próprio navegador.

localStorage.setItem('name', 'Treinaweb');  // <- prefira esta forma
localStorage['name'] = 'Treinaweb';

Porém, já vi situações em que é necessário armazenar um valor logo que o usuário abre a página e manter esse valor enquanto o usuário estiver navegando, mesmo que ele mude de página.

Por ter a possibilidade do usuário clicar em um link e mudar de página (ou recarregá-la), uma variável comum não servirá, pois terá seu valor perdido.

Por isso, muitos desenvolvedores que conhecem o localStorage aproveitam-se dele para esse objetivo. No entanto, o localStorage não tem seus valores apagados, o que causa a necessidade do programador verificar se o usuário acabou de entrar na página para poder apagar ou reiniciar os valores que armazenou no localStorage.

É exatamente para essas ocasiões que existe o sessionStorage. Seu funcionamento e API são idênticos aos do localStorage, com a diferença de que os dados só duram durante a sessão. O usuário pode até mesmo ir para outro site, e as variáveis permanecerão. Elas só serão apagadas quando o usuário fechar o navegador.

sessionStorage.setItem('name', 'Treinaweb');
sessionStorage.getItem('name');

Imagine que o usuário está preenchendo um formulário e pensa em verificar uma informação em outra parte do seu site. Você poderia armazenar os dados do formulário para ele continuar quando voltar. Ao voltar ao formulário, o trabalho dele ainda estará lá.

Se não tem sentido o formulário continuar preenchido caso o usuário tenha fechado o navegador, sem problemas, pois isso irá apagar o sessionStorage, e quando ele voltar, o formulário estará em branco, pronto para um novo preenchimento.

Desta maneira você poderá iniciar suas variáveis temporárias, acessar seus valores enquanto o usuário navega (mesmo que seja para outro site), e não precisará se preocupar em apagar os valores, pois serão apagados automaticamente quando o usuário fechar a janela.

Então, quando precisar de uma variável temporária, lembre-se que o sessionStorage existe para isso. Use o localStorage apenas para dados que devem se manter gravados mesmo com o fechamento do navegador.

Até a próxima!

JUNTE-SE A MAIS DE 150.000 PROGRAMADORES