Sabe aquele efeito antes e depois interativo, bastante usado em sites como G1? Ele é bem simples e envolve alguns conceitos muito úteis, vamos fazer um?
Mas calma. Se você está aqui pelo #1postperday, sabe que não posso postar qualquer coisa. Tem que ser maneiro.
Nosso pequeno plugin, além de bonitinho, será reutilizável e carregará automaticamente, quantas instâncias do efeito na mesma página forem necessárias.
Além disso, vamos usar stylus e gulp em nosso workflow. Você pode fazer com css direto e sem livereload, mas aí eu te pergunto: Pra quê?
Analisando a demanda
Necessidade: Plugin reutilizável de efeito antes-e-depois interativo: usuário deve poder analisar e interagir com o efeito.
Requisitos: Mobile-ready e responsivo, leve e sem libraries externas (ex: jquery) em produção. Deve ser possível criar novas instâncias somente pelo markup. O markup deve ser mínimo.
Demo
A idéia é que fique assim ao final. Você pode incrementar, mas mantive o mais simples e básico possível, já que o objetivo é entender o processo, e não duplicar pra sair usando por aí sem saber. (Se fosse assim, usavamos JQuery hehe)
See the Pen Antes e Depois SEM Jquery by Romulo_Ctba (@romuloctba) on CodePen.
Curtiu? Vamos lá?
Ah, o resultado final está também (com gulp e stylus) neste repositório do github
Planejando o Workflow / Porque usar Stylus e Gulp
Se você não quiser usar GULP, pule direto para Criando os arquivos e pastas mais abaixo. Veja o conteúdo do CSS no codepen acima, clicando em ‘compile css’, mas eu recomendo que faça essa parte, pois é bem maneira.
Criaremos nosso código em um pasta chamada
/src
, dentro do diretório do nosso projeto.Escreveremos o Css usando Stylus, dentro da pasta
/src/stylus
O Javascript, na pasta
/src/javascript
Usaremos o Gulp para compilar o stylus em CSS e copiar tudo (css, html e imagens) para uma pasta chamda
/build
.
Nela, ficará o conteúdo final de nosso projeto.
Ela ficará no diretório de nosso projeto, ao lado da/src
.AH, os arquivos css compilados ficarão na pasta
/build/css
. A pasta/stylus
só existe em nosso source
A vantagem disso é que podemos criar tarefas de gulp para minificar o css e o javascript, bem como otimizar imagens e uma infinidade de outras coisas que podem ser muito úteis, de forma automática.
Preparando o Workflow
Vamos criar algumas tarefas do Gulp para nos ajudar com o Stylus, e também para o liveReload.
Se você ainda não tem, instale o NodeJS e, depois, abra seu terminal e rode:1
npm install -g gulp
Agora, crie uma pasta para seu projeto. Nela, um novo arquivo, chamado package.json
. Ele contém informações básicas sobre nosso projeto para o NodeJs.
1 | { |
Nele declaramos as devDependencies
, ou seja: dependências que não serão usadas em produção, apenas enquanto estamos desenvolvendo.
Elas são: Gulp (local, pois já instalamos o global), gulp-connect-multi
(será o servidor com liveReload) e gulp-stylus
que vai transformar Stylus em Css.
Com o terminal, acesse a pasta do projeto e rode:
1 | npm install |
Criando nossas tarefas para o Gulp
Precisaremos criar 3 tarefinhas: stylus, arquivos e servidor. Vamos lá:
Gulp task stylus
Crie um arquivo chamado gulpfile.js
na pasta do seu projeto. Nele, insira:
1 | var gulp = require('gulp') |
Nesta task, pegamos todos os arquivos .styl da pasta .src/stylus/
e aplicando, com o .pipe(), p método stylus
.
A opção compress:true
vai permitir que ele minifique o css enquanto copia, com o gulp.dest()
para a pasta /build/css.
Gulp task arquivos
´Tudo o que ela faz é copiar arquivos. Ela vai copiar tudo, menos o que estiver na pasta src/stylus
. Insira ao final do gulpfile:
1 | gulp.task('arquivos', function(){ |
Gulp task servidor
Vamos inciar o gulp-connect-multi
, com a opção liveReload
como true. A opção root
é a pasta principal. No caso, a pasta build
.
1 | gulp.task('servidor', connect.server({ |
Task padrão, para fazer tudo:
Faremos a task default
executar todas as outras, por isso, crie:
1 | gulp.task('default', ['stylus', 'arquivos', 'servidor']); |
Com as tasks prontas, podemos criar nosso código fonte.
Criando os arquivos e pastas
Vamos criar nossa estrutura. Dentro da pasta do seu projeto, crie uma pasta chamada src.
Dentro dela, 3 pastas: img
, js
e stylus
.
Agora sim! Vamos ‘começar’.
Arquivo src/index.html
Crie o arquivo index.html dentro da pasta src
com a seguinte estrutura básica:
1 |
|
Acima nada mais é do que o ‘esqueleto’ do nosso HTML, incluindo os arquivos css/main.css
e js/main.js
.
Um dos requisitos da nossa demanda era o markup mínimo.
Pois assim será, insira após o comentário:
1 | (...) |
Substitua img1.jpg
e img2.jpg
pelo nome das suas imagens.
Se quiser, pode usar as minhas imagens, salve elas na pasta src/img
. Pegue elas aqui: http://imgur.com/a/Hcc8R .
Olhem como o markup é mínimo! Um div com a classe .antesDepois
é o nosso container. Dentro dele, uma img
, que será o antes, e um div
com o atributo data-src
apontando uma outra imagem, que será o depois.
Com JS, pegaremos este atributo e adicionaremos como background
do div, fazendo a mágica acontecer.
Mas, pra isso, precisamos dum pouco de CSS:
Arquivo src/stylus/main.styl
Crie o arquivo main.styl
dentro da pasta src/stylus/
1 | .antesDepois |
Tudo bem simples: A classe do container é .antesDepois
. Estamos definindo posicionamento relativo e largura 100%. e !important
no max-width
, pois não queremos que ele passe de 100% de largura.
O cursor col-resize
é pra dar um charminho.
Também colocamos max-width: 100% !important
para o img DENTRO DO .antesDepois. Apenas as imgs de dentro dele terão essa regra.
A classe .depois
é quem faz a mágica.
Definimos um posicionamento absoluto, com 45% de largura e 99% de altura.
O Background-size vai ser cover, e uma bordinha branca pra ficar legal.
Note que o backgorund será incluído agora:
Arquivo src/js/main.js
O nosso Javascript não usa Jquery.
Criaremos uma função IIFE, ou seja: Uma função auto-executável, que vai pegar todos os elementos da classe .antesDepois
e executar um loop for
com eles, gerando cada uma das instâncias que houver no HTML.
A sintaxe de uma função IIFE é assim: (function(){})()
e seu conteúdo vai dentro dos {}.
1 |
|
Note a var containers
: O método getElementsByCLassName()
pega TODOS os elementos com a classe antesDepois
e coloca-os em um Array.
Com isso, podemos fazer um loop FOR
, que vai interagir, executando em cada um dos itens do array.
Em nosso for, colocamos o containers.length
em uma variável. Isso é tipo um ‘cache’ pra melhorar a performance ao iterar um array.
Em cada um dos loops, pegaremos o item da vez no array container
.
Daí as variáveis antes, depois e depoisImg
vêm com o mesmo método getElementsByClassName()
, só que dessa vez o método é executado dentro do container
, e não do document
.
Portanto, só os ementos que estiverem dentro de container
, que representa o item atual do FOR.
Por último, no trecho acima, temos o método .style()
, em que inserimos um background-image
, cuja url pegamos com getAttribute('data-src')
logo antes.
Daí, os 3 addEventListeners
que vão monitorar, respectivamente por um Mousemove, TouchStart e TouchMove, sempre dentro do container
.
Quando disparar o evento, vão chamar a função comparaPosicao()
, que criaremos agora:
Insira, ao final do main.js
:
1 | function comparaPosicao(e){ |
A função recebe um evento (e) como parâmetro. Aì usamos this.getBoundingClientRect()
que nos dá um retângulo do container. A palavra chave this
, no caso, refere-se à variavel container
, onde a função foi chamada pelo ´eventListener`.
A var posicao
é uma continha que pega o eixo X de dentro do retangulo (pageX - retangulo.left) e divide pelo offsetWidth
, ou seja: largura do container
. Isso dá um número decimal, fazemos ele * 100 e temos em quantos % da largura nosso mouse está.
Se a var posicao
for menor ou igual a 100, pegaremos o elemento com a classe .depois
de dentro do container atual (this) e definiremos sua largura (width) com a posição do mouse. Se ela for maior, significa que o mouse ou touch está fora do container.
Ufa, terminamos.
Testando e Rodando.
Com o seu terminal, acesse a pasta d oprojeto e rode o comendo:1
gulp
Se tudo der certo, seu navegador abrirá em http://localhost:1337 com tudo funcionando!! :)
Ah, o resultado final está também (com gulp e stylus) neste repositório do github
Conclusão
Apesar da preparação para o Workflow ter deixado o artigo um pouco longo, vimos que o código é bastante simples, sem precisar de JQuery.
Espero que possa passar à quem ainda tem medo, a coragem necessária pra largar mão - quando possível - desse framework tão bom, mas tão usado desnecessariamente.
É isso aí! Muito obrigado pela visita, volte sempre e fique a vontade :D
Comments