Criar visuais interactivos com JavaScript e HTML5 Canvas

, Author

Projecto 1: Linhas Icy

Para melhores resultados, abrir em ecrã inteiro

Primeiro, as nossas linhas são brancas, por isso vamos ao nosso CSS e dar à tela um fundo escuro:

canvas {
background: linear-gradient(45deg, #0d1011 0% 20%, #163486);
}

Construtor de Linhas

Agora de volta a canvas.js . Vamos criar um novo Line classe:

class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
}

Parte da determinação de cada linha:x e y posição, temos algumas outras propriedades para tornar nossos visuais mais interessantes:

  • Podemos usar a propriedade offset para renderizar as linhas a distâncias variáveis umas das outras.
  • Também vamos usar movimento circular no nosso exemplo. Podemos usar a propriedade radians para definir o ângulo de movimento e a propriedade velocity para determinar a velocidade do movimento.

Método de desenho de linhas

Próximo, vamos querer desenhar as nossas linhas. Há um pequeno círculo na parte inferior de cada linha, que podemos definir usando a função arc, e então a linha dispara para o topo da tela:

class Line {
constructor(x, y, offset) {
this.x = x;
this.y = y;
this.offset = offset;
this.radians = 0;
this.velocity = 0.01;
} draw = () => {
c.strokeStyle = 'rgba(255, 255, 255, 0.5)';
c.fillStyle = 'rgba(255, 255, 255, 0.3)'; c.beginPath();
c.arc(this.x, this.y, 1, 0, Math.PI * 2, false);
c.fill();
c.moveTo(this.x, this.y);
c.lineTo(this.x + 300, this.y - 1000);
c.stroke();
c.closePath(); this.update();
} update = () => {
// this is where we control movement and interactivity
}
}

Para testar se está funcionando, você pode criar uma linha de amostra:

const line = new Line(250, 800, 0);
line.draw();

Gerar 100 linhas

Mas queremos linhas para preencher a tela, então vamos precisar de uma maneira de criar um array de 100 linhas. Aqui está uma versão simples:

const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const unit = 25; lineArray.push(
new Line(
start.x + unit * i,
start.y + i * -3,
0.1 + (1 * i)
)
);
};

Para ver estas linhas, vamos precisar de activar os seus métodos de draw. Como em breve iremos animá-los, o melhor lugar para fazer isso é na função animate function:

function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
lineArray.forEach(line => {
line.draw();
});
};animate();

Agora temos 100 linhas! Mas podemos tornar a nossa posição inicial mais interessante: no código abaixo, a variável random ajuda a fornecer uma variação sutil que dá ao efeito geral um aspecto mais natural. (Eu também estou usando Math.sin(i) para adicionar alguma ondulação nas posições iniciais. Isto não é necessário, mas é um toque agradável.)

const lineArray = ;for (let i = 0; i < 100; i++) { const start = { x: -250, y: 800 };
const random = Math.random() - 0.5;
const unit = 25; lineArray.push(
new Line(
start.x + ((unit + random) * i),
start.y + (i + random) * -3 + Math.sin(i) * unit,
0.1 + (1 * i)
)
);
};

Jogue com os números até ter um padrão inicial que você gosta!

Animação

Daqui, é muito simples adicionar a animação que queremos. Volte à nossa classe Line, e depois adicione o seguinte no método update:

this.radians += this.velocity;
this.y = this.y + Math.cos(this.radians + this.offset);

Com cada frame de animação, this.radians irá aumentar em this.velocity . Usaremos então this.radians para criar movimento circular, via Math.cos .

Se você não encontrou Math.sin ou Math.cos antes (ou sua trigonometria está um pouco enferrujada!), isso não deve impedi-lo de seguir adiante. Basta saber que Math.cos nos permite criar um movimento de vaivém, num padrão idêntico à linha roxa do gráfico abaixo:

Onda cósmica

Por último, adicionando this.offset , as linhas começarão a fazer looping em ângulos diferentes.

Eu acho que este é um efeito bastante agradável. Mas para um toque final, vamos adicionar alguma interatividade. Quando o usuário passar o mouse sobre as linhas, vamos fazê-las mudar de cor.

Interatividade

A maneira mais simples de ver se o mouse do usuário está sobre uma das linhas é usar o canvas embutido do método.isPointInPath

Mas, sem mais ajustes, isto não vai ser muito útil. As linhas têm apenas 1 pixel de largura, então a chance de acionar qualquer mudança será muito baixa para ser interessante!

Uma grande solução para este problema é criar linhas invisíveis atrás de cada uma de nossas linhas. As linhas invisíveis devem ser mais largas, e podemos usá-las para disparar isPointInPath.

isPointInPath

No nosso método draw , vamos criar uma função chamada drawLinePath . Deve ser necessário um width para nossas linhas invisíveis, e um color (que nossas linhas visíveis se tornarão, quando as linhas invisíveis estiverem em contato):

const drawLinePath = (width = 0, color) => {
c.beginPath();
c.moveTo(this.x - (width / 2), this.y + (width / 2));
c.lineTo(this.x - (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2) + 300, this.y - (width / 2) - 1000);
c.lineTo(this.x + (width / 2), this.y - (width / 2));
c.closePath();
if (c.isPointInPath(mouse.x, mouse.y) && color) {
c.strokeStyle = color;
};
};

(Note que o uso de funções de seta acima implicitamente vincula o contexto correto para this ).

Podemos então facilmente adicionar diferentes larguras de linhas invisíveis para disparar diferentes mudanças de cor. O seguinte código deve deixar claro o que está acontecendo:

drawLinePath(150, 'red');
drawLinePath(50, 'yellow');

But, para um efeito mais sutil, tente:

drawLinePath(150, '#baf2ef');
drawLinePath(50, '#dcf3ff');

E isso é um wrap!

Para o código JavaScript completo, confira este gist.

Deixe uma resposta

O seu endereço de email não será publicado.