Desenvolvendo a Intro do Star Wars com HTML, CSS, JavaScript & Node.js!
Tags: tutorial, javascript, staticwebapps, node
Published: 2019-12-21 04:21:56

---
title: Desenvolvendo a Intro do Star Wars com HTML, CSS, JavaScript & Node.js!
published: true
cover_image: https://thepracticaldev.s3.amazonaws.com/i/armxrvwgr8wjn3ocaw1l.PNG
description: Desenvolvimento da Intro do Star Wars e com deploy no Azure Web App Service/Azure Blog Storage.
tags: tutorial, javascript, staticwebapps, nodejs
---

Fala pessoal! Tudo certo?! Hoje o post será bem diferente! E épico! Estarei explicando aqui para vocês como podemos desenvolver a Intro do filme mais filme mais geek de todos os tempos: Star Wars! E melhor: usando Node.js & Express.js😀😀😀

Quem aqui ama Star Wars levantem as mãos!! 😀😀😀😀 (incluindo eu, claro!!!)

[![mao.gif](https://i.postimg.cc/BvKkPyHf/mao.gif)](https://postimg.cc/DW7Btxxx)

Então, se você curte, vamos aprender agora mesmo a desenvolver essa intro e melhor que no final vamos disponibilizar na nuvem para que vocês possam mostrar o que vocês aprenderam aos seus amigos(as)!

Vamos nessa?!

## Entendendo a Intro do Star Wars

Toda pessoa que é fã de Star Wars sabe como funciona a Intro! Mas, deixo aqui um vídeo para quem nunca viu ou se esqueceu: **[Video - Star Wars Intro](https://www.youtube.com/watch?v=tGsKzZtRwxw)**

E será justamente essa intro que estarei desenvolvendo juntamente com vocês. Usando o Vue.js e claro: HTML, CSS & JavaScript. Será tudo feito na unha! Hoje com os recursos do HTML5 e do CSS3 nos ajuda e muito para conseguir desenvolver essa proeza! 

Mas, bora começar pois já falei demais aqui!

## Recursos Utilizados

Durante o desenvolvimento dessa intro estaremos fazendo uso dos seguintes recursos:

* **[Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=javascript-63934-gllemos)**
* **[Node.js](https://nodejs.org/en/)**
* **[Azure Static Web Apps](https://azure.microsoft.com/services/app-service/static/?WT.mc_id=javascript-63934-gllemos)**
* **[Visual Studio Code Extension - Azure Static Web Apps](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurestaticwebapps&WT.mc_id=javascript-63934-gllemos)**
* **[Azure Storage Account](https://azure.microsoft.com/pt-br/services/storage/?WT.mc_id=javascript-15678-gllemos)**
* **[Conta - Azure](https://azure.microsoft.com/pt-br/?WT.mc_id=javascript-63934-gllemos)**

Caso você seja um(a) estudante de alguma Instituição de Ensino de Faculdade ou Universidade, poderá criar sua conta no **[Azure for Students](https://azure.microsoft.com/pt-br/free/students/?WT.mc_id=javascript-15678-gllemos)**. Essa conta te dará o benefício em possuir crédito de USD 100,00 para usar os serviços de maneira gratuita, sem necessidade de possuir um cartão de crédito. Para ativar essa conta, bastam acessar o link ao lado: **[AQUI](https://azure.microsoft.com/pt-br/free/students/?WT.mc_id=javascript-15678-gllemos)**

## Iniciando o Desenvolvimento

Como usaremos o Node.js & Express, precisamos antes criar o arquivo `package.json`. Para criar bastam digitar o seguinte comando abaixo:

```bash
> npm init
```

Agora, vamos instalar o `express.js` digitando o seguinte comando:

```bash
> npm install express --save
```

Eu, particularmente gosto muito de trabalhar com eslint a fim de deixar o projeto de maneira padronizada e organizada. Vamos instalar ele digitando o seguinte comando:

```bash
> npm install -g eslint
> npm install eslint --save-dev
```

E vamos configurar ele no nosso projeto com o seguinte comando:

```bash
> eslint --init
```

E vamos escolher as seguintes opções:

1. To check syntax, find problems, and enforce code style
2. JavaScript modules (import/export)
3. None of these
4. Node
5. Use a popular style guide
6. Airbnb
7. JavaScript
8. Would you like to install them now with npm? Yes

Feito isso, instalaremos corretamente o eslint no nosso projeto.

Agora vamos instalar os outros pacotes:

```bash
> npm i nodemon
> npm i eslint-friendly-formatter
> npm i prettier
> npm i husky --save-dev
```

Após isso, o arquivo `package.json` ficará da seguinte maneira:

* **arquivo: package.json**

```json
{
  "name": "intro-starwars-app",
  "version": "1.0.0",
  "description": "Desenvolvimento da Intro do Star Wars com deploy no Azure.",
  "main": "app.js",
  "scripts": {
    "dev": "nodemon",
    "lint": "eslint --ext .js -f ./node_modules/eslint-friendly-formatter . --fix"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/glaucia86/intro-starwars-app.git"
  },
  "keywords": [
    "nodejs",
    "azure",
    "javascript",
    "express"
  ],
  "author": "Glaucia Lemos",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/glaucia86/intro-starwars-app/issues"
  },
  "homepage": "https://github.com/glaucia86/intro-starwars-app#readme",
  "dependencies": {
    "eslint-friendly-formatter": "^4.0.1",
    "express": "^4.17.1",
    "nodemon": "^2.0.2",
    "prettier": "^1.19.1"
  },
  "devDependencies": {
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.0.0",
    "eslint-plugin-import": "^2.19.1",
    "husky": "^3.1.0"
  },
  "husky": {
    "pre-commit": "lint-staged",
    "pre-push": "npm run lint"
  },
  "lint-staged": {
    "*.js": [
      "prettier --write",
      "git add"
    ]
  }
}
```

Ótimo! Vamos dar continuidade!

## Criando a Estrutura da Aplicação

Vamos fazer algumas alterações significativas nesse projeto recém criado. Para isso, abram o * **[Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=javascript-15678-gllemos)** e façam as seguintes alterações:

1. Criem um arquivo chamado `app.js`
2. Crie uma pasta chamada `public`
3. Dentro da pasta `public` crie as seguintes pastas: `js` e `css` 
4. Dentro da pasta `css` crie o arquivo `style.css`
5. Dentro da pasta `js` crie o arquivo `intro.js`
6. Dentro da pasta `public` crie o arquivo `index.html`

A estrutura do projeto deverá ficar da seguinte forma:

 [![Screen-Shot-12-20-19-at-07-52-PM.png](https://i.postimg.cc/cJ8z4y1Y/Screen-Shot-12-20-19-at-07-52-PM.png)](https://postimg.cc/xkn5tZzT)

Caso tenham dúvidas em como está estruturado o projeto, bastam acessar o código fonte que se encontra disponível no GitHub: **[AQUI](https://github.com/glaucia86/intro-starwars-app)**

Vamos dar continuidade e começar a desenvolver a nossa aplicação.

## Habilitando o Express para Executar Arquivos Estáticos

Como estamos criando uma aplicação estática dentro do Node.js, precisaremos fazer uso do Express.js. Para isso, abram o arquivo `app.js` e incluam o seguinte bloco de código:

* **arquivo: app.js**

```javascript
/**
 * File: app.js
 * Description: File responsible for running the application
 * Data: 05/04/2022
 * Author: Glaucia Lemos <Twitter: @glaucia_lemos86>
 */


const express = require('express');

const app = express();

app.use(express.static('public'));

app.get('/', (req, res) => {
  res.send('App - Star Wars Intro');
});

app.listen(3000, () => console.log('Application is running on port 3000!'));
```

Ótimo! Agora a nossa aplicação estará habilitada para executar arquivos estáticos dentro do Node.js. Para testar e ver se de fato irá funcionar, vamos fazer o seguinte: abram o arquivo `index.html` e inclua o seguinte bloco de código:

* **arquivo: index.html**

```html
<!DOCTYPE html>
<html lang="pt-br">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>App intro Star Wars</title>
</head>
<body>
  <h1>“A Long Time Ago, in a galaxy far far away…”</h1>
</body>
</html>
``` 

Execute a aplicação com o comando `nodemon`, abre o browser no `localhost:3000` e vejam o que acontece:

[![Screen-Shot-12-20-19-at-08-03-PM.png](https://i.postimg.cc/FsLGLgX5/Screen-Shot-12-20-19-at-08-03-PM.png)](https://postimg.cc/zVqnmhf0)

Se aparecer conforme a imagem acima é porque configuramos devidamente o Express.js na nossa aplicação! 

Vamos agora continuar a desenvolver a nossa aplicação?

## “A Long Time Ago, in a galaxy far far away…”

Como vocês puderam perceber no vídeo acima, a Intro do Star Wars vem com a lendária frase:

***"A Long Time Ago, in a galaxy far, far away..."***

Que traduzindo seria: **“Há muito tempo atrás, numa galáxia muito distante…”** no nosso tutorial, usaremos a frase em inglês. Porque curto muito mais! 

Vamos desenvolver o nosso primeiro bloco de código: que é escrever a frase inicial da intro. Para isso, abram o arquivo: `index.html` e vamos alterar novamente e incluindo o CDN do Bootstrap uma vez que precisaremos dele para algumas animações a frente:

* **arquivo: index.html**

```html
<!DOCTYPE html>
<html lang="pt-br">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">

  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

  <!-- Optional theme -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">  
  <link rel="stylesheet" href="css/style.css">

  <title>App - Intro Star Wars</title>
</head>
<body>
  <script src="js/intro.js"></script>
</body>
</html>
```

Nada muito diferente aqui. Observem que estou incluindo aqui o CDN do bootstrap. Uma vez que, mais a frente precisaremos fazer alguns ajustes na nossa aplicação. Outro ponto muito importante, precisaremos usar a nova estrutura do HTML, pois vamos precisar muito da tag: `<section>` para poder incluir as classes que serão responsáveis pela animação da nossa aplicação.

Nesse mesmo arquivo: ‘index.html’ vamos até a tag `<section>` e inclua a seguinte classe: `intro intro_texto`

* **arquivo: index.html**

```html
<!DOCTYPE html>
<html>

(...)

</head>
<body>

  <section class="intro intro_texto">
    A Long Time Ago, in a galaxy far,<br> far away ...  
  </section>

  <script src="js/intro.js"></script>
</body>
</html>
```

Agora, abram o arquivo `style.css` e vamos criar a classe contida na tag `section`:

* **arquivo: style.css**

```css
@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);

body {
  margin: 0;
  background: #000;
  overflow: hidden;
}

.intro {
  position: absolute;
  top: 40%;
  left: 20%;
  z-index: 1;    
  opacity: 0;
}
```

Bom vamos antes entender o que está acontecendo aqui.

1. Estamos incluindo a tipografia chamada `News Cycle` que é a que mais se parece com a tipografia da intro do filme.

2. Depois, criamos um elemento body, a qual incluímos um fundo de cor preto e retiramos todas as margens para que seja padrão para diferentes navegadores.

3. Criamos uma classe chamada `intro`. Essa classe será responsável pelo posicionamento da aplicação. O `absolute` será responsável por remover o elemento de fluxo. As propriedades `left` e `top` estarão com as medidas relativas, por isso o uso das porcentagens aqui! E enfim, para que possamos sobrepor, usaremos a propriedade `z-index`.

Agora, vamos definir as propriedades para a nossa famosa frase!! Retornem ao arquivo: `style.css` e incluem o bloco de código abaixo da classe: `.intro`:

```css
@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);

body {
    margin: 0;
    background: #000;
    overflow: hidden;
}

.intro {
    position: absolute;
    top: 40%;
    left: 20%;
    z-index: 1;    
}

.intro_texto {
    font-family: "News Cycle", sans-serif;
    color: #00BFFF;
    font-weight: 400;
    letter-spacing: .1em;
}
```

Como vocês podem ver, criamos a classe `.intro_texto` e com isso estamos usando a fonte que inicialmente importamos lá no início no arquivo css. Logo abaixo, claro, adicionamos a cor azul característico da famosa frase: **"A Log Time Ago, in a Galaxy far, far away…"** e atribuímos uma espessura de 400 e para concluir incluímos uma separação entre as letras usando a medida `em`.

Executem novamente a aplicação e vejam se não está aparecendo conforme a imagem abaixo:

[![Screen-Shot-12-20-19-at-09-58-PM.png](https://i.postimg.cc/ZRj5bDL8/Screen-Shot-12-20-19-at-09-58-PM.png)](https://postimg.cc/qhhTQwSq)

Lindo, não é mesmo! Mas, vamos começar a tratar a questão da lógica da nossa aplicação no lado do JavaScript! 😉

## Desenvolvendo a lógica da Aplicação no JavaScript

Agora vamos começar a desenvolver a parte da lógica dessa aplicação no JavaScript. Para isso, abrem o arquivo `script.js` e colocam o seguinte bloco de código:

```javascript
/**
 * Arquivo: intro.js
 * Data: 20/12/2019
 * Descrição: Lógica da Intro do filme Star Wars.
 * Author: Glaucia Lemos
 */

let width = window.innerWidth;
let height = window.innerHeight;

let intro = document.getElementsByClassName('intro')[0];

intro.style.fontSize = width / 30 + 'px';

window.addEventListener('resize', () => {
  width = canvas.width = window.innerWidth;
  height = canvas.height = window.innerHeight;
  intro.style.fontSize = width / 30 + 'px';
});
```

Vamos entender um pouco aqui o que fizemos aqui. O tamanho das letras serão de maneira responsiva. Para isso, estamos usando o JavaScript. E para isso aconteça precisamos obter a largura e comprimento da janela!

Depois, estamos selecionando o elemento da classe `intro` para que possamos armazenar numa variável com o mesmo nome.

E enfim, estamos definindo o tamanho da fonte de acordo com o tamanho proporcional da largura indicado. E com isso, caso venha a mudar os tamanhos das janelas em diferentes monitores, os valores serão atualizados.

Agora que a nossa frase inicial está pronta, vamos focar agora no texto resumo, em amarelo, que aparece no decorrer da intro! 😀

## A História Precisa ser Contada!

Agora vamos ao próximo passo, como já mencionado acima, é desenvolver a parte do resumo que aparece no decorrer da intro. Se vocês não se lembram, segue a imagem do que faremos agora:

[![star.jpg](https://i.postimg.cc/nrLNvdfG/star.jpg)](https://postimg.cc/nj6dxGzX)

Para isso, vamos ocultar o elemento anterior, adicionando na propriedade `opacity` em um valor de 0.

Já na parte do HTML, iremos adicionar uma nova tag `<section>`. E nessa tag ela receberá uma classe chamada `paragrafos`. Dentro dessa classe, haverá uma divisão com um resumo da ‘história’, que é justamente aí que incluiremos a história que aparecerá de amarelo na nossa aplicação. Com isso, incluiremos a tag `<div>` e dentro dela incluiremos a classe chamada: `historia_texto` para os estilos das letras. Dentro deste elemento adicionaremos nas tags `<p>` de cada elemento.

* **arquivo: index.html**

```html
<!DOCTYPE html>
<html lang="pt-br">

<head>
  <title>Intro - Star Wars</title>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport" />

  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

  <!-- Optional theme -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
    integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

  <link href="css/style.css" rel="stylesheet">
</head>

<body>

  <header></header>

  <section class="intro intro_texto">
    A Long Time Ago, in a galaxy far,<br> far away ...
  </section>
  
  <section class="paragrafos">
    <div class="historia historia_texto">
      <p class="text-center">Star Wars Episódio XI</p>
      <p class="text-center">Glaucia e a Busca do Sabre de Luz</p>
      <br>
      <p class="text-center">
        São tempos muito difícies!
        Por isso, Glaucia Lemos precisa encontrar o sabre de luz
        para que possa obter poderes de programar
        como nenhuma pessoa na galáxia.
        E com isso, ela inicia a sua busca por toda a galáxia.
      </p>

      <p class="text-center">
        Durante a sua busca,
        Glaucia se depara com um planeta chamado Tatooine.
        E é justamente ali que ela iniciará todo o seu treinamento
        para conseguir os seus poderes novamente.
      </p>
    </div>
  </section>

  <footer></footer>

  <script src="js/intro.js"></script>
</body>

</html>
```

O texto, pode ficar a critério e a criatividade de vocês! O importante é usar a imaginação de todos vocês! Bom, agora vamos voltar para o CSS e aplicar alguns estilos nesse texto.

Abrem novamente o arquivo `style.css` e inclua as seguintes classes:

- .historia
- .historia_texto
- .paragrafos

Conforme o bloco de código abaixo:

* **arquivo: style.css**

```css
@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);

body {
    margin: 0;
    background: #000;
    overflow: hidden;
}

.intro {
    position: absolute;
    top: 40%;
    left: 20%;
    z-index: 1;    
}

.intro_texto {
    font-family: "News Cycle", sans-serif;
    color: #00BFFF;
    font-weight: 400;
    letter-spacing: .1em;
}

.historia {
    position: absolute;
    top: 80%;
}

.historia_texto {
    font-family: "News Cycle", sans-serif;
    font-weight: 700;
    color: #FFD700;
    text-align: justify;
    letter-spacing: .1em;
    line-height: 1.1em;
}

.paragrafos {
    position: absolute;
    left: 15%;
    width: 70%;
    z-index: 1;
}
```

Vamos compreender o que foi feito aqui. Na classe `.historia` , colocamos uma `position` fixa e a localização dela será de maneira vertical sentido para o topo.

Já na classe `.paragrafos`, diferente da classe anterior, iremos adicionar a propriedade width e left para centralizar o elemento. E para sobrepor, usaremos a propriedade `z-index`.

Para a classe `.historia_texto` iremos utilizar a tipografia `Cycle News` com cor amarela e com espessura 700. E além disso, iremos justificar os parágrafos e dar um espaçamento entre as letras.

Procurem colocar um resumo mesmo. Não procurem colocar muita coisa…. lembre-se que o texto tem que acompanhar de acordo com o tema da música da intro. (sim…. vamos colocar áudio nessa intro!!) 😀

Só que na intro do filme as letras meio que ficam deitadas, não é mesmo? Bom, tem como resolver isso. Para isso, aplicaremos o efeito 3D dentro da classe: `.paragrafos` no arquivo `styles.css` 😀 

* **arquivo: styles.css**

```css
(...)

.paragrafos {
    position: absolute;
    left: 15%;
    width: 70%;
    z-index: 1;
    transform-origin: 50%;
    transform: perspective(300px) rotateX(20deg);
}
```

Vejam que para fazer o efeito das letras deitadas, utilizamos as propriedades: `perspective` e `rotate`. Assim, fará com que o texto fique ligeiramente inclinado. A primeira parte na propriedade `transform` indica a perspectiva de que um item será exibido em 3D e o segundo dá um certo eixo de rotação, uma série de ângulos em graus. Antes disso, iremos alterar a origem das alterações no centro do elemento. Vejam o resultado como fica:

[![Screen-Shot-12-20-19-at-10-22-PM.png](https://i.postimg.cc/k525Jypz/Screen-Shot-12-20-19-at-10-22-PM.png)](https://postimg.cc/wtdzFDHQ)

Agora vamos voltar ao arquivo `intro.js` e vamos a incluir lógica nesse texto. 

* **arquivo: intro.js**

```javascript
/**
 * Arquivo: intro.js
 * Data: 20/12/2019
 * Descrição: Lógica da Intro do filme Star Wars.
 * Author: Glaucia Lemos
 */

let width = window.innerWidth;
let height = window.innerHeight;

let intro = document.getElementsByClassName('intro')[0];
let historia = document.getElementsByClassName('historia')[0];
let paragrafos = document.getElementsByClassName('paragrafos')[0];

intro.style.fontSize = width / 30 + 'px';
historia.style.fontSize = width / 20 + 'px';
paragrafos.style.height = height + 'px';

window.addEventListener('resize', () => {
  width = canvas.width = window.innerWidth;
  height = canvas.height = window.innerHeight;
  intro.style.fontSize = width / 30 + 'px';
  historia.style.fontSize = width / 20 + 'px';
  paragrafos.style.height = height + 'px';
});
```

Agora, para que possamos ocultar os parágrafos, vamos alterar na classe `.historia` o valor da `position` de 0 para 80%: 

* **arquivo: styles.css**

```css
(...)

.historia {
    position: absolute;
    top: 80%;
}
```

Bom, agora vamos adicionar um botão que nos permitirá iniciar a nossa intro junto com áudio. Para isso, abre novamente o arquivo: `index.html`  e adicione o atributo `onclick` dentro da tag <div> com uma função chamada: `iniciar()`

* **arquivo: index.html**

```html
(...)

<body>
  <div class="botao" onclick="iniciar()">Iniciar</div>
  <header></header>

  <section class="intro intro_texto">
    A Long Time Ago, in a galaxy far,<br> far away ...
  </section>

(...)
```

Agora vamos aplicar alguns estilos nesse botão criado na página principal.

Crie no arquivo `style.css` a classe: `.botao`, conforme o bloco de código:

* **arquivo: style.css**

```css
(...)

.botao {
    color: white;
    display: inline-block;
    margin: 10px;
    padding: 5px;
    border: 3px solid;
    border-radius: 5px;
    cursor: pointer;
}
```

O resultado deverá estar assim:

[![Screen-Shot-12-20-19-at-10-33-PM.png](https://i.postimg.cc/wv9b5WYb/Screen-Shot-12-20-19-at-10-33-PM.png)](https://postimg.cc/zLPj8FBn)

Show de bola, não é mesmo?!! 😀

Estamos quase no final, mas precisamos incluir mais lógica nessa aplicação e com isso precisaremos mais do JavaScript!

## Um pouco mais de JavaScript para animar as coisas!!

No arquivo `script.js` vamos criar a função `iniciar`. Essa função será responsável em adicionar novas classes a um elemento intro e para a classe do elemento historia:

* **arquivo: intro.js**

```javascript
(...)

function iniciar() {
  intro.className = 'intro intro_texto intro_animacao';
  historia.className = 'historia historia_texto historia_animacao';
}
```

Definido a nossa função. Voltemos para o CSS. Vamos criar agora as classes que serão responsáveis por fazer a animação da nossa intro:

* **arquivo: style.css**

```css
(...)

.intro_animacao {
  animation: intro 2s ease-out 0s;
}

.historia_animacao {
  animation: paragrafos 80s linear 2s;
}

```

Vamos a explicação: Essa propriedade tem **4 valores**. Vamos a cada uma delas.

O primeiro é o nome da **animação**. O segundo é a **duração**. O terceiro é a **forma da função dos efeitos**, e finalmente, o tempo de espera para o **início da animação**. Controlando o tempo de início da nossa aplicação e criará uma sequencia para que a animação suceda logo de primeira! 😀

Agora vamos usar as famosas propriedades do CSS3: `keyframes`. Caso não saibam o que são keyframes, tem um excelente artigo no site Tableless escrito pelo Diego Eis, bem sucinto e com exemplos **[AQUI](https://tableless.com.br/css3-animation-keyframe/)**

Para a nossa primeira animação, faremos uma entrada e saída com desvanecimento das frases. Para fazermos isso, iremos modificar a propriedade: `opacity`. E para os `paragrafos` teremos o efeito de animação também!! Vamos acrescentar uma animação de desvanecimento e com a propriedade `top` vamos fazer com que as frases venham a sumir de baixo para cima:

* **arquivo: style.css**

```css
@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);

body {
    margin: 0;
    background: #000;
    overflow: hidden;
}

.intro {
    position: absolute;
    top: 40%;
    left: 20%;
    z-index: 1;    
}

.intro_texto {
    font-family: "News Cycle", sans-serif;
    color: #00BFFF;
    font-weight: 400;
    letter-spacing: .1em;
}

.historia {
    position: absolute;
    top: 80%;
}

.historia_texto {
    font-family: "News Cycle", sans-serif;
    font-weight: 700;
    color: #FFD700;
    text-align: justify;
    letter-spacing: .1em;
    line-height: 1.1em;
}

.paragrafos {
    position: absolute;
    left: 15%;
    width: 70%;
    z-index: 1;
    transform-origin: 50%;
    transform: perspective(300px) rotateX(20deg);
}

.botao {
    color: white;
    display: inline-block;
    margin: 10px;
    padding: 5px;
    border: 3px solid;
    border-radius: 5px;
    cursor: pointer;
}

.intro_animacao {
   animation: intro 2s ease-out 0s;
}

.historia_animacao {
    animation: paragrafos 80s linear 2s;
}

@keyframes intro {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes paragrafos {
  0% {
    top: 75%;
    opacity: 1;
  }
  95% {
    opacity: 1;
  }
  100% {
    top: -200%;
    opacity: 0;
  }
}
```

## Toda Galáxia tem Estrelas!

Sim. É verdade! Toda galáxia é composto de estrelas e planetas! E na nossa aplicação não será diferente!! 😀

Vamos adicionar estrelas no fundo. Para isso, vamos adicionar a propriedade canvas – para que possamos utilizar o efeito `snow`. O resultado final do arquivo `style.css` ficará da seguinte maneira:

* **arquivo: style.css**

```css
@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);

body {
    margin: 0;
    background: #000;
    overflow: hidden;
}

.intro {
    position: absolute;
    top: 40%;
    left: 20%;
    z-index: 1;    
    opacity: 0;
}

.intro_texto {
    font-family: "News Cycle", sans-serif;
    color: #00BFFF;
    font-weight: 400;
    letter-spacing: .1em;
}

.historia {
    position: absolute;
    top: 80%;
}

.historia_texto {
    font-family: "News Cycle", sans-serif;
    font-weight: 700;
    color: #FFD700;
    text-align: justify;
    letter-spacing: .1em;
    line-height: 1.1em;
}

.paragrafos {
    position: absolute;
    left: 15%;
    width: 70%;
    z-index: 1;
    transform-origin: 50%;
    transform: perspective(300px) rotateX(20deg);
}

.botao {
    color: white;
    display: inline-block;
    margin: 10px;
    padding: 5px;
    border: 3px solid;
    border-radius: 5px;
    cursor: pointer;
}

.intro_animacao {
   animation: intro 2s ease-out 0s;
}

.historia_animacao {
    animation: paragrafos 80s linear 2s;
}

@keyframes intro {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  90% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@keyframes paragrafos {
  0% {
    top: 75%;
    opacity: 1;
  }
  95% {
    opacity: 1;
  }
  100% {
    top: -200%;
    opacity: 0;
  }
}

/*Fundo com as estrelas*/
canvas {
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
}
```

E para incluirmos o som – o tema da intro do filme Star Wars, vamos criar uma variável no arquivo `intro.js` chamado: som. E incluir essa variável dentro da função `iniciar`:

* **arquivo: intro.js**

```javascript
/**
 * Arquivo: intro.js
 * Data: 20/12/2019
 * Descrição: Lógica da Intro do filme Star Wars.
 * Author: Glaucia Lemos
 */

let width = window.innerWidth;
let height = window.innerHeight;

let intro = document.getElementsByClassName('intro')[0];
let historia = document.getElementsByClassName('historia')[0];
let paragrafos = document.getElementsByClassName('paragrafos')[0];
let som = document.getElementById('som');

intro.style.fontSize = width / 30 + 'px';
historia.style.fontSize = width / 20 + 'px';
paragrafos.style.height = height + 'px';

window.addEventListener('resize', () => {
  width = canvas.width = window.innerWidth;
  height = canvas.height = window.innerHeight;
  intro.style.fontSize = width / 30 + 'px';
  historia.style.fontSize = width / 20 + 'px';
  paragrafos.style.height = height + 'px';
});

function iniciar() {
  intro.className = 'intro intro_texto intro_animacao';
  historia.className = 'historia historia_texto historia_animacao';
  som.play();
}
```

Vamos voltar a nossa atenção em criar um efeito `snow`! Vejam o bloco de código abaixo:

Note que já estão inclusas as alterações relacionadas as funções criadas: **inicio()** e **nevar()** no escopo do código!! 😀

* **arquivo: intro.js**

```javascript
/**
 * Arquivo: intro.js
 * Data: 20/12/2019
 * Descrição: Lógica da Intro do filme Star Wars.
 * Author: Glaucia Lemos
 */

let width = window.innerWidth;
let height = window.innerHeight;

const intro = document.getElementsByClassName('intro')[0];
const historia = document.getElementsByClassName('historia')[0];
const paragrafos = document.getElementsByClassName('paragrafos')[0];
const som = document.getElementById('som');

intro.style.fontSize = width / 30 + 'px';
historia.style.fontSize = width / 20 + 'px';
paragrafos.style.height = height + 'px';

window.addEventListener('resize', () => {
  width = canvas.width = window.innerWidth;
  height = canvas.height = window.innerHeight;
  intro.style.fontSize = width / 30 + 'px';
  historia.style.fontSize = width / 20 + 'px';
  paragrafos.style.height = height + 'px';
});

function iniciar() {
  intro.className = 'intro intro_texto intro_animacao';
  historia.className = 'historia historia_texto historia_animacao';
  som.play();
}

/* Fundo de estrelas */

let canvas = document.getElementById('snow');
const ctx = canvas.getContext('2d');

canvas.width = width;
canvas.height = height;

const num = 100;
const size = 2;
const elements = [];

function inicio() {
  for (let i = 0; i < num; i++) {
    elements[i] = {
      x: Math.ceil(Math.random() * width),
      y: Math.ceil(Math.random() * height),
      size: Math.random() * size,
    };
  }
}

function nevar() {
  ctx.clearRect(0, 0, width, height);
  for (let i = 0; i < num; i++) {
    const e = elements[i];
    ctx.beginPath();
    ctx.fillStyle = '#FFFFFF';
    ctx.arc(e.x, e.y, e.size, 0, 2 * Math.PI);
    ctx.fill();
  }
}

inicio();
nevar();

```

Agora voltando para a página principal… vamos incluir todas essas mudanças:

* **arquivo: index.html**

```html
<!DOCTYPE html>
<html lang="pt-br">

<head>
  <title>Intro - Star Wars</title>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport" />

  <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

  <!-- Optional theme -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"
    integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

  <link href="css/style.css" rel="stylesheet">
</head>

<body>
  <div class="botao" onclick="iniciar()">Iniciar</div>
  <canvas id="snow"></canvas>

  <section class="intro intro_texto">
    A Long Time Ago, in a galaxy far,<br> far away ...
  </section>
  
  <section class="paragrafos">
    <div class="historia historia_texto">
      <p class="text-center">Star Wars Episódio XI</p>
      <p class="text-center">Glaucia e a Busca do Sabre de Luz</p>
      <br>
      <p class="text-center">
        São tempos muito difícies!
        Por isso, Glaucia Lemos precisa encontrar o sabre de luz
        para que possa obter poderes de programar
        como nenhuma pessoa na galáxia.
        E com isso, ela inicia a sua busca por toda a galáxia.
      </p>

      <p class="text-center">
        Durante a sua busca,
        Glaucia se depara com um planeta chamado Tatooine.
        E é justamente ali que ela iniciará todo o seu treinamento
        para conseguir os seus poderes novamente.
      </p>
    </div>
  </section>

  <audio src="https://raw.githubusercontent.com/glaucia86/sounds/master/starwars.mp3" id="som"></audio>
    
  <script src="js/intro.js"></script>
</body>

</html>
```

Observem que o próprio HTML5 te fornece uma tag `<audio>` que te permite adicionar audio para a sua página que está desenvolvendo. Essa é uma das vantagens que o HTML5 nos proporciona.

Vejam o gif da nossa aplicação funcionando:

[![star-wars-intro.gif](https://s7.gifyu.com/images/star-wars-intro.gif)](https://gifyu.com/image/SLgYG)

## Realizando o Deploy da Aplicação para o Azure Static Web Apps

Agora que estamos com a nossa aplicação funcionando localmente, nada melhor do que disponibilizar para o mundo até para que possamos mostrar a todos o que desenvolvemos. 

Nesse caso, estaremos usando a **[Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps/?WT.mc_id=javascript-63934-gllemos)**. 

[![image-aswa-workflow.png](https://docs.microsoft.com/en-us/azure/static-web-apps/media/overview/azure-static-web-apps-overview.png)](https://postimg.cc/TpNm6gtm)

E vamos fazer tudo isso no **[Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=javascript-63934-gllemos)** e usando a extensão:

* **[Visual Studio Code Extension - Azure Static Web Apps](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurestaticwebapps&WT.mc_id=javascript-63934-gllemos)**

Abram o VS Code e vamos entrar no Portal Azure ali mesmo! 

[![Screen-Shot-04-18-22-at-01-42-PM.png](https://i.postimg.cc/66f0XkXr/Screen-Shot-04-18-22-at-01-42-PM.png)](https://postimg.cc/Lhhfk0h5)

Agora clique com o botão direito em cima do Azure Static Web Apps e vai aparecer a seguinte caixa: `Create Static Web App`, clique aí!

[![Screen-Shot-04-18-22-at-01-57-PM.png](https://i.postimg.cc/SRM9s11p/Screen-Shot-04-18-22-at-01-57-PM.png)](https://postimg.cc/ZvJnsHhf)

Depois siga os passos:

1. Inclua o nome da aplicação. Ex.: intro-starwars-app
2. Selecione a região onde será hospedada a aplicação. 
3. Agora, escolha a o build preset. Nesse caso como não estamos usando nenhum Framework JavaScript, mas puramente o Javascript, HTML e CSS escolha a opção: `custom`
4. Agora precisamos incluir o local onde está armazenada as informações da nossa aplicação: nesse caso coloque: `/public`
5. E, finalmente, deixe em branco a última opção. 

Uma caixa abrirá, clique na opção: `Open Actions in GitHub`

[![Screen-Shot-04-18-22-at-04-44-PM.png](https://i.postimg.cc/28Hmgr7b/Screen-Shot-04-18-22-at-04-44-PM.png)](https://postimg.cc/3dDPvM6Y)

Uma vez que você clique nessa caixa, você será redirecionado para a página de fluxos do repositório do código da aplicação. Onde aparecerá todo o workflow ou fluxo de esteira em C.I e C.D.

[![Screen-Shot-04-18-22-at-04-52-PM.png](https://i.postimg.cc/zvZSJswT/Screen-Shot-04-18-22-at-04-52-PM.png)](https://postimg.cc/2bGBGXK5)

Agora, retorne a extensão do Azure Static Web Apps no Visual Studio Code e clique com o botão direito em: `Browser Site`.

[![Screen-Shot-04-18-22-at-04-54-PM.png](https://i.postimg.cc/k49gqw6B/Screen-Shot-04-18-22-at-04-54-PM.png)](https://postimg.cc/p9GHBfBH)

E, vòilá! Sua aplicação está online e disponível ao mundo!

[![star-wars-intro.gif](https://s7.gifyu.com/images/star-wars-intro.gif)](https://gifyu.com/image/SLgYG)

Se você deseja ver a aplicação hospedada, basta acessar o link: **[AQUI - Star Wars Intro App](https://calm-cliff-0923da21e.1.azurestaticapps.net/)**

## Palavras Finais

Com HTML, CSS, JavaScript/Node.js, podemos fazer qualquer coisa. Mas, qualquer coisa mesmo! E aprender de uma maneira divertida e diferente.
E também aprendemos de uma maneira muito simples como implantar uma aplicação Node.js no Azure em poucos minutos, sem muitas dificuldades.

Abaixo segue alguns recursos necessários caso desejam aprender um pouco mais de Node.js + Azure:

* ✅ **[Curso Grátis Microsoft Learn - Node.js ](https://docs.microsoft.com/learn/modules/intro-to-nodejs/?WT.mc_id=javascript-63934-gllemos)**

* ✅ **[Azure Static Web Apps Official Documentation](https://docs.microsoft.com/azure/static-web-apps/?WT.mc_id=javascript-63934-gllemos)**

* ✅ **[Microsoft Learn Free Course - Publish an Angular, React, Svelte, or Vue JavaScript app with Azure Static Web Apps](https://docs.microsoft.com/en-us/learn/modules/publish-app-service-static-web-app-api/?WT.mc_id=javascript-63934-gllemos)**

* ✅ **[Microsoft Learn - Crie e Publique um site estático com Gatsby](https://docs.microsoft.com/en-us/learn/modules/create-deploy-static-webapp-gatsby-app-service/?WT.mc_id=javascript-63934-gllemos)**

* ✅ **[Implementando Azure Static Web Apps no Hugo](https://docs.microsoft.com/azure/static-web-apps/publish-hugo/?WT.mc_id=javascript-63934-gllemos)**

Se são conteúdos que você curte, então não deixa de se inscrever e ative o sininho para ficar sabendo quando teremos vídeo novo! Essa semana já teremos uma série nova incrível lá no Canal do Youtube.

[![Screen-Shot-12-31-20-at-01-06-AM.png](https://i.postimg.cc/pr3TL4Pd/Screen-Shot-12-31-20-at-01-06-AM.png)](https://bit.ly/youtube-canal-glaucialemos)

E para ficarem por dentro de várias outras novidades, não deixem de me seguir lá no twitter!

[![Twitter](https://code4coders.files.wordpress.com/2019/05/image-12.png)](https://twitter.com/glaucia_lemos86)

Nos vemos! Até a próxima pessoal! 😍