Os gradientes fazem parte do espectro do CSS há algum tempo. Vemos muitos gradientes radiais e lineares em muitos projetos, mas há um tipo de gradiente que parece um pouco solitário: o gradiente cônico. Vamos fazer um mostrador de relógio usando esse tipo de gradiente.
Trabalhando com gradientes cônicos
O que estamos fazendo consiste em um gradiente com transições de cores giradas em torno de um ponto central e pode ter vários valores de cores. Para que este relógio funcione, também usaremos o valor do ângulo de um gradiente cônico que define a rotação ou ponto de partida. O ângulo é definido usando um from
valor.
background-image: conic-gradient(from 45deg, #6e7dab, #5762d5);
O interessante disso é que um ângulo inicial pode ter um valor negativo em CSS, o que será útil mais tarde.
Um exemplo simples e elegante de um gradiente cônico:
Construindo nosso relógio básico
Vamos começar adicionando um pouco de HTML para o relógio e os ponteiros:
Vamos criar um estilo padrão para o nosso relógio. Para que isso funcione corretamente, atualizaremos as variáveis CSS com JavaScript mais tarde, então vamos definir o escopo dessas variáveis dentro do nosso .clock
seletor. Para ajustes fáceis, vamos adicionar as cores das mãos também.
.clock {
/* general clock vars */
--hour-hand-color: #000;
--hour-hand-degrees: 0deg;
--minute-hand-color: #000;
--minute-hand-degrees: 0deg;
--second-hand-color: hotpink;
--second-hand-degrees: 0deg;
position: relative;
min-width: 320px;
width: 25vw;
height: 25vw;
min-height: 320px;
border-radius: 50%;
margin: 0 auto;
border: 7px solid #000;
}
/* clock hands */
.hand {
position: absolute;
left: 50%;
bottom: 50%;
height: 45%;
width: 4px;
margin-left: -2px;
background: var(--second-hand-color);
border-radius: 6px;
transform-origin: bottom center;
transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}
.second-hand {
transform: rotate(var(--second-hand-degrees));
}
.hour-hand {
height: 35%;
border-radius: 40px;
background-color: var(--hour-hand-color);
transform: rotate(var(--hour-hand-degrees));
}
.minute-hand {
height: 50%;
background: var(--minute-hand-color);
transform: rotate(var(--minute-hand-degrees));
}
Isso nos define com o estilo geral que precisamos para o relógio. Nós configuramos transform-origin
nos ponteiros para que eles girem corretamente ao redor do mostrador do relógio. Há também algumas propriedades personalizadas para definir ângulos nos ponteiros que atualizaremos com JavaScript para obter o tempo certo para que cada ponteiro seja mapeado para segundos, minutos e horas de acordo.
Aqui está o que temos até agora:
Tudo bem, vamos continuar atualizando essas propriedades personalizadas!
Adicionando o JavaScript para nosso relógio básico
Primeiro, vamos direcionar nosso relógio e criar uma função:
const clock = document.getElementById("clock");
function setDate() {
// Code to set the current time and hand angles.
}
setDate();
Dentro de nossa função vamos buscar a hora atual usando o Date()
função para calcular o ângulo correto das mãos:
const now = new Date();
const secondsAngle = now.getSeconds() * 6;
const minsAngle = now.getMinutes() * 6 + secondsAngle / 60;
const hourAngle = ((now.getHours() % 12) / 12) * 360 + minsAngle / 12;
Veja como funciona esse cálculo:
- Segundos: Pegamos 60 segundos e multiplicamos por
6
, que passa a ser360
, o número perfeito de ângulos em um círculo completo. - Minutos: O mesmo que segundos, mas agora adicionamos o ângulo dos segundos e dividimos por
60
para aumentar o ângulo um pouco dentro de um minuto para um resultado mais preciso. - Horas: Primeiro, calculamos o resto da hora e dividimos por
12
. Então dividimos esse resto por12
novamente para obter um valor decimal, podemos multiplicar por360
. Por exemplo, quando estamos na 23ª hora,23 / 12 =
remain
11
. Divida isso por 12 e teremos0.916
que então é multiplicado por360
para um total de330
. Aqui, faremos a mesma coisa que fizemos com os minutos e somaremos o ângulo dos minutos, dividido por12
, para um resultado mais preciso.
Agora que temos nossos ângulos, a única coisa que resta a fazer é atualizar as variáveis do nosso relógio adicionando o seguinte no final da nossa função:
clock.style.setProperty("--second-hand-degrees", secondsAngle + "deg");
clock.style.setProperty("--minute-hand-degrees", minsAngle + "deg");
clock.style.setProperty("--hour-hand-degrees", hourAngle + "deg");
Por último, mas não menos importante, acionaremos a função com um intervalo de um segundo para obter um relógio funcionando:
const clock = document.getElementById("clock");
function setDate() {
// etc.
}
// Tick tick tick
setInterval(setDate, 1000);
setDate();
Veja a demonstração de trabalho do nosso relógio básico:
Aplicando isso a um gradiente cônico
OK, então os ponteiros do nosso relógio estão funcionando. O que realmente queremos é mapeá-los para um gradiente cônico que se atualiza conforme o tempo muda. Você pode ter visto o mesmo efeito se tiver um Apple Watch com a face “Gradiente” ativa:
Para fazer isso, vamos começar atualizando nosso .clock
elemento com um gradiente cônico e duas propriedades personalizadas que controlam os ângulos inicial e final:
.clock {
/* same as before */
/* conic gradient vars */
--start: 0deg;
--end: 0deg;
/* same as before */
background:
conic-gradient(
from var(--start),
rgb(255 255 255) 2deg,
rgb(0 0 0 / 0.5) var(--end),
rgb(255 255 255) 2deg,
rgb(0 0 0 / 0.7)
);
}
Você pode brincar um pouco com isso para estilizá-lo do jeito que você gosta. Eu adicionei algumas cores extras no gradiente ao meu gosto, mas contanto que você tenha um ponto inicial e um ponto final, você está pronto para ir.
A seguir, atualizaremos nosso setDate()
função para que atualize as variáveis para nossos pontos inicial e final no gradiente cônico. O ponto de partida será o nosso ponteiro dos segundos, que é fácil de encontrar porque será o mesmo que o ângulo dos nossos minutos. Para fazer isso no ponteiro das horas, devemos fazer o nosso ponto final igual ao hourAngle
variável no script, mas subtraia nosso ponto de partida dela.
let startPosition = minsAngle;
let endPosition = hourAngle - minsAngle;
Agora podemos atualizar nossas variáveis com JavaScript novamente:
clock.style.setProperty("--start", startPosition + "deg");
clock.style.setProperty("--end", endPosition + "deg");
Parece que poderíamos terminar neste ponto, mas há um problema! Este cálculo funciona bem desde que o ponteiro dos minutos tenha um ângulo menor que o ponteiro das horas. Nosso gradiente cônico ficará confuso no momento em que o ponteiro dos minutos passar por ele. Para corrigir isso, usaremos um valor negativo como ponto de partida. Felizmente, é fácil identificar quando isso acontece. Antes de atualizar nossas variáveis, adicionaremos o seguinte:
if (minsAngle > hourAngle) {
startPosition = minsAngle - 360;
endPosition = hourAngle - startPosition;
}
Ao subtrair 360
do ângulo dos minutos, podemos definir um valor negativo para o nosso startposition
variável. Por causa desse ponto inicial negativo, nossa posição final deve ser atualizada pelo ângulo horário, subtraído da posição inicial.
Lá vamos nós - agora os ponteiros das horas e minutos estão definidos para ângulos de gradiente:
É isso! Mas não deixe que isso o impeça de levar isso ainda mais longe. Crie seus próprios estilos e compartilhe-os comigo nos comentários para que eu possa vê-los. Aqui está uma pequena inspiração para você seguir em frente: