Postado dia

E ae! Como primeiro tutorial, decidi ensinar a vocês como fazer o efeito de perspectiva que usei no meu portfólio online. Ele apresenta um efeito 3D e dá um toque legal ao seu site.

Se quiser, clique no botão abaixo para ver uma demonstração do que você aprenderá neste tutorial.

Ver demonstração

1. Definindo a base do tutorial

Primeiramente, em um arquivo HTML, precisamos criar os elementos que formarão a estrutura do que receberá o efeito. Para isso, o seu arquivo HTML deve estar assim:

<!DOCTYPE html>
<html lang="pt">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<title>Perspectiva</title>
</head>

<body>
<div id="perspectiva">
 <div id="distorcao">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nisl tortor, tempus vitae facilisis sed, tristique a quam.</div>
</div>
</body>
</html>

Note a presença de duas tags <div> com as ids “perspectiva” e “distorcao”. Esses serão os elementos que formam a estrutura que receberá o efeito.

2. A base da perspectiva

Agora vamos para o CSS. Para que o efeito funcione, o elemento que terá o efeito precisa estar dentro de um elemento com a propriedade CSS "perspective", que permite definir uma perspectiva aos elementos que usam propriedades de transformação 3D.

Para isso, abra uma tag <style> com o atributo “type” cujo valor seja “text/css”, para definir o uso do CSS, dentro da tag <head> e dentro escreva as linhas abaixo:

body{margin: 0; min-height: 100vh; background-color: #666;}
#perspectiva{width: 100%; height: 100vh; position: relative; -webkit-perspective: 100vw; perspective: 100vw;  overflow: hidden;}
#distorcao{width: 80%; position: absolute; top: 50%; left: 50%; font-size: 4vw; text-align: center; color: #FFF; transform-style: preserve-3d;}

Agora vamos por partes:

body{margin: 0; min-height: 100vh; background-color: #666;}

Primeiramente, definimos os estilo da tag <body> para que ela tenha uma altura mínima igual a 100% da altura da área do site todo, medido pela unidade “vh”, ou seja, altura do viewport. Uma cor de fundo também é definido usando a propriedade "background-color".

#perspectiva{width: 100%; height: 100vh; position: relative; -webkit-perspective: 100vw; perspective: 100vw;  overflow: hidden;}

Depois definimos as propriedades CSS para o elemento com id “perspectiva” para que ele pegue toda a largura do navegador e a altura igual ao definido na tag <body>. Como neste exemplo o texto fica centralizado na página, é definido a propriedade "position" com valor “relative”, para que seu canto superior esquerdo seja referência inicial para o texto.

Ainda neste mesmo elemento, definimos a propriedade "perspective", que permitirá que o efeito aconteça. Usaremos o valor de “100vw”, igual a 100% da largura da área do site todo. Pode ser usados outras unidades de medidas, sendo mais comum usar “px”. Para compatibilidade maior com navegadores webkit, aplicaremos a mesma propriedade com o prefixo vendor “-webkit-“, ficando assim: "-webkit-perspective: 100vw;". E por precaução, vamos definir a propriedade "overflow" com o valor “hidden”, para que caso o texto ultrapasse o limite do elemento “perspectiva”, o navegador não gere uma barra de rolagem.

#distorcao{width: 80%; position: absolute; top: 50%; left: 50%; font-size: 4vw; text-align: center; color: #FFF; transform-style: preserve-3d;}

Por fim, definimos as propriedades CSS para o elemento “distorcao”, que contém o texto que terá o efeito. A propriedade "position" com o valor “absolute” precisa ser aplicada caso deseja que o elemento se posicione no centro do elemento “perspectiva”, assim, ele irá se guiar baseado na posição do elemento acima na hierarquia que tenha posicionamento relativo, no caso, “perspectiva”.

Para centralizar, as propriedades "top" e "left" devem estar com o valor “50%”. Mas isso não deixará o elemento perfeitamente centralizado, pois ele usará o próprio canto superior esquerdo como ponto de referência. Mas isso será corrigido em breve. Para deixar o texto mais apresentável, definimos o "font-size", tamanho de fonte, em 4vw; "text-align", alinhamento de texto, como “center” (centralizado); e "color", cor do texto, como branco. Se quiser, pode definir uma fonte pra o texto, usando a propriedade "font-family".

E para encerrar, aplicamos a propriedade "transform-style" com o valor “preserve-3d”, que manterá a aparência 3D em qualquer transformação 3D que haja dentro do elemento “distorcao”.

Seu HTML deve estar assim agora:

<!DOCTYPE html>
<html lang="pt">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<title>Perspectiva</title>

<style type="text/css">
 body{margin: 0; min-height: 100vh; background-color: #666;}
 #perspectiva{width: 100%; height: 100vh; position: relative; -webkit-perspective: 100vw; perspective: 100vw; overflow: hidden;}
 #distorcao{width: 80%; position: absolute; top: 50%; left: 50%; font-size: 4vw; text-align: center; color: #FFF;}
</style>
</head>

<body>
<div id="perspectiva">
<div id="distorcao">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nisl tortor, tempus vitae facilisis sed, tristique a quam.</div>
</div>
</body>
</html>

E em funcionamento:

3. Hora da mágica

Só isso não vai fazer o elemento ganhar vida como queremos, então agora vamos para o Javascript.

Em seu arquivo HTML, abra uma tag <script> com o atributo “type” cujo valor seja “text/javascript”, para definir o uso do Javascript, dentro da tag <head> e dentro escreva as linhas abaixo:

window.onload = function(){
 document.getElementById("distorcao").style.transform =  "translate(-50%,-50%) rotateX(0deg) rotateY(0deg) translateZ(0)";
}

Esta primeira parte do código define a transformação inicial do elemento “distorcao”. Definimos uma função a ser rodada quando a página terminar de carregar (window.onload = function(){ ... }), incluindo qualquer elemento apontada nela.

Dentro desta função, apontamos para o elemento que contenha a id “distorcao” (document.getElementById("distorcao").style.transform) e aplicamos a propriedade CSS “transform” nela (style.transform). O valor da propriedade será “translate(-50%,-50%) rotateX(0deg) rotateY(0deg) translateZ(0)”.

A propriedade “transform” permite realizar transformações 2D e 3D no elemento, dependendo de quais propriedades forem aplicados ao elemento. No caso, o “transform” realizará 4 transformações:

  • translate(-50%,-50%) define um reposicionamento do elemento usando uma medida na horizontal e outra na vertical. No caso definimos -50% para os dois pois o elemento “distorcao” apresenta as propriedades “top” e “left” iguais a 50%, mas como dito antes, o elemento usará seu canto superior esquerdo como referência de posicionamento, mas na verdade queremos que ele use o seu centro. Definindo o translate com -50% nas duas direções fará o elemento se reposicionar horizontalmente subtraindo a posição atual com 50% da sua largura, e o mesmo acontecerá na vertical;
  • rotateX(0deg) define uma rotação do elemento em torno do eixo X. Mas aqui definimos o valor “0deg”, ou seja, 0 graus de rotação, então ele não terá um ângulo horizontal definido;
  • rotateY(0deg) funciona igual ao rotateX, mas usando o eixo Y;
  • translateZ(0) define um reposicionamento da coordenada 3D Z, ou seja, a profundidade. No caso, sua posição Z será 0, sem unidade mesmo. Quando algum valor é 0, não há necessidades de usar unidades de medidas, inclusive ângulos (“deg”).

Esse pedaço de código javascript faz o elemento ter uma posição inicial assim que a página carregar, ficando assim:

4. O Javascript

Agora vamos ao principal, fazer o elemento seguir o cursor. Aqui usaremos um pouco de matemática.

Ainda no seu código javascript, adicione o seguinte código:

document.onmousemove = function(e){
 x = e.pageX, y = e.pageY;
 limite = 25;

 var ww = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
 var wh = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

 rotx = y*100/wh;
 rotx = 180*rotx/100;
 rotx = rotx-90;
 rotx *= -1;

 roty = x*100/ww;
 roty = 180*roty/100;
 roty = roty-90;

 document.getElementById("distorcao").style.transform =  "translate(-50%,-50%) rotateX("+(rotx*limite/100)+"deg) rotateY("+(roty*limite/100)+"deg) translateZ(0)";
};

Definimos uma função a ser rodada quando o cursor se mover pela página (document.onmousemove = function(e){ ... }). Na função, precisaremos ler os eventos que acontece quando mexemos o cursor, então precisamos pegar o argumento “event” do evento “mousemove”, que é passado por padrão a sua função, mas só acessível se definirmos um parâmetro na função. No caso, vamos chamá-lo de “e”, para deixar o código menos sujo.

x = e.pageX, y = e.pageY;

Então primeiramente precisamos pegar a posição X e Y do cursor. Para isso, criamos duas variáveis e a nomeamos de “x” e “y”, sendo que cada uma deverá armazenar a posição do cursor passada para o parâmetro “e”. Para isso, definimos o valor “e.pageX” para a variável “x”, e “e.pageY” para a variável “y”. As informações pageX e pageY apresentam a posição do cursor na página e são alteradas a cada movimento do cursor em questão de milésimos de segundos.

limite = 25;

Depois vamos definir uma variável que funcione como um freio para a rotação, para que o elemento não exagere quando rotacionar. A ideia é que o seu valor vá de 0, parado, a 100, sem limitação. Então criamos a variável “limite” para que armazene esse valor numérico. Deixamos 25, mas você pode ajustar o valor dessa variável como quiser.

var ww = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var wh = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

Para calcularmos o movimento do elemento, também vamos precisar pegar as medidas da área do site no navegador. Para isso, criamos as variáveis “ww” para armazenar da área largura do site, e “wh” para armazenar a altura da área do site. Usamos três referências de medidas nessas variáveis pois cada navegador mede do seu jeito. Então mandamos ele ler de um jeito, e caso esse jeito não retorne um valor, pedidos para ele ler o próximo usando o operador lógico “||”, que significa “ou”.

5. “Matematicando”

Nas linhas seguintes, calculamos os ângulos para serem aplicados no elemento. Para isso, temos como base a posição do cursor na página em pixels e as medidas da área do site. Porém precisamos do valor convertido para algo equivalente em graus, sendo que vamos usar o máximo de 180 graus (explicarei o porquê em breve). A imagem abaixo ilustra isso:

Imagem 1 - A medida que o cursor se movimenta para a direita e/ou para baixo, o valores X e/ou Y da posição do cursor vão subindo. O máximo é igual ao valor das variáveis 'ww' e 'wh'. No caso, queremos que o máximo para cada quando convertido em graus seja igual a 180.

Imagem 1 – A medida que o cursor se movimenta para a direita e/ou para baixo, o valores X e/ou Y da posição do cursor vão subindo. O máximo é igual ao valor das variáveis “ww” e “wh”. No caso, queremos que o máximo para cada quando convertido em graus seja igual a 180.

Então vamos usar regra de três. Vamos definir a largura da área do site como o valor que seja igual a 100%. Vamos supor que essa largura seja de 1440px de largura. Agora vamos imaginar que o cursor está na posição X de 600px. A pergunta que devemos fazer é: se 1440px é equivalente a 100%, então 600px é equivalente a quantos %? Traduzindo para a regra de três, ficaria assim:

1440 - 100
600  - X

Agora ligamos o 1440 ao X e o 600 ao 100, formando um X entre os quatro valores. Cada ligação equivale a uma multiplicação, e depois dividimos uma multiplicação pela outra, sendo que aqui devemos dar preferência à multiplicação que tenha dois números, ficando assim:

1440X / 600 * 100
1440X / 60000
X = 60000 / 1440
X = 41,67

Descobrimos então que 600px é equivalente a 41,67% de 1440px. Mas ainda não temos isso em graus. Então vamos a outra regra de três. Ainda dentro deste exemplo, devemos nos fazer a próxima pergunta: se 100% é equivalente a 180 graus, então 41,67% é equivalente a quantos graus? Na regra de três, ficaria assim:

180 - 100
X   - 41,67

E montando a conta:

180 * 41,67 / 100X
7500,6 / 100X
X = 7500,6 / 100
X = 75,006

Descobrimos agora que quando o cursor estiver na posição X de 600px, seu valor em graus retornado será de 75,006 graus de rotação. Legal, hein?

Mas para que o elemento aja como se estivesse olhando para o cursor, não podemos usar esse valor ainda pois o elemento iria ficar de costas para o cursor, quase que de perfil para o usuário. Então vamos diminuir esse valor. A ideia é a seguinte: o ponto central do elemento que tem o texto tem que marcar 0 graus tanto na horizontal quanto na vertical, e as extremidades precisam marcar 90 graus, sendo este valor positivo ou negativo, dependendo de qual extremidade o cursor estiver. Ou seja, indo para uma direção a partir do centro, os valores X e Y podem subir ou descer, cada um atuando baseado na direção em que o cursor está indo.

O limite precisa ser 90 graus pois neste ângulo, tanto positivo quanto negativo, o texto irá olhar para os lados, ficando de perfil para o usuário, e não queremos que ele fique invertido, ou seja, de costas para o usuário. E se calcularmos a distância entre -90 e 90, temos um total de 180, ângulo máximo que citei anteriormente. Para entender melhor, abaixo está uma imagem ilustrando como a transformação deve ocorrer nos valores de rotateX() e rotateY(), respectivamente:

Imagem 2 - O funcionamento do rotateX() e rotateY() e os ângulos máximos finais que queremos em cada parte das extremidades do elemento 'perspectiva'

Imagem 2 – O funcionamento do rotateX() e rotateY() e os ângulos máximos finais que queremos em cada parte das extremidades do elemento “perspectiva”

Tendo essa ideia em mente, vamos ao código.

6. Definindo a direção do olhar do texto

As variáveis “rotx” e “roty” são as responsáveis por armazenar o valor em graus para ser usada no elemento “distorcao”. Olhando a imagem 1, podemos perceber que a direção em que o valor X tem seu valor aumentado é diferente da direção em que o rotateX() gira: um precisa ir para a horizontal, enquanto outro precisa ir para a vertical (ilustrado na imagem 2). E vice-versa para o Y. Por isso, pode ser notado algo diferente nas primeiras linhas das duas variáveis:

rotx = y*100/wh;
rotx = 180*rotx/100;
rotx = rotx-90;
rotx *= -1;

roty = x*100/ww;
roty = 180*roty/100;
roty = roty-90;

A variável “rotx” usa a posição Y do cursor e a altura da área do site ao invés de usar a posição X e a largura da área do site. O mesmo acontece no “roty”. Essas duas linhas pegam a porcentagem da posição do cursor conforme explicado acima, sobre o uso das regras de três.

As linhas seguintes de cada variável fazem a conversão de porcentagem para graus (rotx = 180*rotx/100; e roty = 180*roty/100;). Já depois dessas linhas, é feita a mudança dos valores de 0~180 para -90~90 simplesmente pegando o valor obtido até aqui e subtraindo com 90 (rotx = rotx-90; e roty = roty-90;).

Até este ponto, o texto estaria olhando corretamente para o cursor se movermos ele no sentido horizontal, mas na vertical, se movermos para baixo, o texto olhará para cima. Isso é facilmente corrigido invertendo o valor obtido em “rotx” de negativo para positivo, ou vice-versa dependendo do valor atual. Para isso, multiplicaremos a variável por -1 (rotx *= -1;). Vale lembrar que x *= -1 é a mesma coisa que x = x*-1;

Para finalizar, temos que aplicar os valores obtidos no elemento “distorcao”. A linha final faz isso:

document.getElementById("distorcao").style.transform = "translate(-50%,-50%) rotateX("+(rotx*limite/100)+"deg) rotateY("+(roty*limite/100)+"deg) translateZ(0)";

Perceba que os valores de “rotx” e “roty” são multiplicados pelo valor de “limite”, aquela variável que funcionaria como um freio para a rotação, lembra? Aqui, convertemos o valor de 0~100 para 0.0~1.0, já que queremos definir se permitimos a rotação até 90 graus ou diminuímos esse limite para o texto não girar de forma agressiva.

E é isso!

7. Final e versão jQuery

O código final fica assim:

<!DOCTYPE html>
<html lang="pt">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<title>Perspectiva</title>

<style type="text/css">
 body{margin: 0; min-height: 100vh; background-color: #666;}
 #perspectiva{width: 100%; height: 100vh; position: relative; -webkit-perspective: 100vw; perspective: 100vw; overflow: hidden;}
 #distorcao{width: 80%; position: absolute; top: 50%; left: 50%; font-size: 4vw; text-align: center; color: #FFF;}
</style>

<script type="text/javascript">
window.onload = function(){
 document.getElementById("distorcao").style.transform =  "translate(-50%,-50%) rotateX(0deg) rotateY(0deg) translateZ(0)";
}

document.onmousemove = function(e){
 x = e.pageX, y = e.pageY;
 limite = 25;

 var ww = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
 var wh = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

 rotx = y*100/wh;
 rotx = 180*rotx/100;
 rotx = rotx-90;
 rotx *= -1;

 roty = x*100/ww;
 roty = 180*roty/100;
 roty = roty-90;

 document.getElementById("distorcao").style.transform =  "translate(-50%,-50%) rotateX("+(rotx*limite/100)+"deg) rotateY("+(roty*limite/100)+"deg) translateZ(0)";
};
</script>
</head>

<body>
<div id="perspectiva">
 <div id="distorcao">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nisl tortor, tempus vitae facilisis sed, tristique a quam.</div>
</div>
</body>
</html>

E funcionando, ele fica assim:

Caso quiser jQuery, o código pode ser alterado para este:

<!DOCTYPE html>
<html lang="pt">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

<title>Perspectiva</title>

<style type="text/css">
 body{margin: 0; min-height: 100vh; background-color: #666;}
 #perspectiva{width: 100%; height: 100vh; position: relative; -webkit-perspective: 100vw; perspective: 100vw; overflow: hidden;}
 #distorcao{width: 80%; position: absolute; top: 50%; left: 50%; font-size: 4vw; text-align: center; color: #FFF;}
</style>

<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(window).load = function(){
 $("#distorcao").css({transform: "translate(-50%,-50%) rotateX(0deg) rotateY(0deg) translateZ(0)"});
}

$(document).on("mousemove",function(e){
 x = e.pageX, y = e.pageY;
 limite = 25;

 var ww = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
 var wh = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

 rotx = y*100/wh;
 rotx = 180*rotx/100;
 rotx = rotx-90;
 rotx *= -1;

 roty = x*100/ww;
 roty = 180*roty/100;
 roty = roty-90;

 $("#distorcao").css({transform: "translate(-50%,-50%) rotateX("+(roty*limite/100)+"deg) rotateY("+(rotx*limite/100)+"deg) translateZ(0)"});
};
</script>
</head>

<body>
<div id="perspectiva">
 <div id="distorcao">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum nisl tortor, tempus vitae facilisis sed, tristique a quam.</div>
</div>
</body>
</html>

Para ver este tutorial em ação em uma página separada, clique no botão abaixo para ver uma demonstração:

Ver demonstração

Até a próxima!

Manda sua palavra ae! Deixe um comentário: