quarta-feira, 10 de dezembro de 2014

Criando um Relógio Analógico com jQuery e PHP

Saudações! Ainda pretendo gravar um vídeo para este post, então por enquanto, vou deixar só na escrita mesmo.
Vamos ver, hoje, como criar um relógio analógico usando PHP para pegar a hora certa do servidor e jQuery para fazer a rotação do relógio.
Exemplo

ATENÇÃO: A rotação do relógio será feita com transform: rotate(); das CSS. Portanto, é necessário que o navegador destino suporte isso. Os navegadores que devem rodar sao:
  • Internet Explorer 9(com prefixo -ms-) e 10+
  • Mozilla Firefox 31+
  • Google Chrome 31-35(com prefixo -webkit-) e 36+
  • Safari 5.1+ (com prefixo -webkit-)
  • Opera 26+
  • iOS Safari 7.1+ (com prefixo -webkit-)
  • Android Browser 4.1+ (com prefixo -webkit-)
  • Opera Mobile 24+
  • Blackberry Browser 10 (com prefixo -webkit-)
  • Chrome/Android 39+
  • Firefox/Android 33+
  • IE Mobile 11+
Insira o jQuery assim:
<script type="text/javascript" src="//code.jquery.com/jquery.min.js"></script>
Você pode fazer a verificação do jQuery, para saber se ele está corretamente inserido. Veja:
Como verificar se jQuery está corretamente inserido


Agora, com os navegadores em mente e o jQuery rodando, vamos preparar as imagens, que serão todas com 1000px de altura(height). isso é importante para que os ponteiros coincidam, um em cima do outro, e rodem bem no centro. Você pode montar seu relógio no Photoshop.
No meu caso, montei a base inteiramente no Photoshop, e os ponteiros foram adaptações de espadas do anime Sword Art Online. Observe as imagens:

Base do Relógio (height = 1000px; width = 1000px)
Ponteiro Hora (height = 1000px; width = 154px)
Ponteiro Minutos (height = 1000px; width = 154px)
Ponteiro Segundos (height = 1000px; width = 154px)
Note que todos os ponteiros tem 1000px de altura, apesar de que o conteúdo das imagens varia de tamanho. Todas as imagens são PNGs sem fundo.
Isso é importante para que possamos deixar todos com um height:100%; e definir apenas o tamanho do relógio.

Agora, para começar o posicionamento, crie uma div com id clock e, dentro dela, três imagens e um span de class="dig". Ou algo de sua preferência.
div#clock será a base do relógio. As três imagens, que terão classes = hour, min e sec, serão, respectivamente, os ponteiros de hora, minutos e segundos.
Estrutura do relógio:
<div id="clock">
<img src="img/hour.png" class="hour" />
<img src="img/min.png" class="min" />
<img src="img/sec.png" class="sec" />
<span class="dig">Héliton Martyns</span>
</div>

Agora nosso CSS:
#clock, .hour, .min, .sec {
 height:400px;
 width:auto;
 position:absolute;
}
#clock {
 top:50%;
 left:50%;
 margin-left:-200px;
 margin-top:-200px;
 background:url("img/clock.png");
}
.hour, .min, .sec {
 left:50%;
 height:100%;
 margin-left:-61.6px;
}
.dig {
 height:20px;
 border:1px solid #000;
 background:#FFF;
 background:rgba(255,255,255,0.6);
 position:absolute;
 top:50%;
 margin-top:-10px;
 left:50%;
 margin-left:20px;
 font-size:16px;
 line-height:20px;
 font-family:Verdana, Geneva, sans-serif;
}

.dig se refere ao campo onde ficarão a hora digital, ao lado direito do centro do relógio.
Com tudo posicionado, é hora de fazer o jQuery.

o primeiro passo será pegar a hora do servidor, lembrando que o código a seguir deve estar entre as tags <script> de um arquivo PHP:
index.php
<?php date_default_timezone_set("America/Sao_Paulo"); ?>
servh = "<?php echo date("h"); ?>"; // retorna 01-12 (horas)
servi = "<?php echo date("i"); ?>"; // retorna 00-59 (minutos)
servs = "<?php echo date("s"); ?>"; // retorna 00-59 (segundos)
servH = "<?php echo date("H"); ?>"; // retorna 00-23 (horas)
Essas variáveis globais, agora, guardam a hora do servidor, mas no horário de Londres. Então temos que colocar o comando date_default_timezone_set() ANTES da primeira função date(); do PHP.
Para ver a lista de timezones aceitos, acesse: PHP.net - Timezones Suportados.


Agora vamos estudar um pouco de matemática...

Como já sabemos, o relógio tem 360º, já que é um círculo.
Sendo assim, cada hora tem 30º de distância entre si.
Logo, cada minuto/segundo tem 6º de distância entre si.

O ponteiro segundo se moverá 6º por segundo, completando 360º em 60 segundos.
Se o ponteiro dos minutos devem se mover o tempo todo, ele se moverá 0.1º por segundo.
Mas se seguirmos o exemplo, e considerarmos que o ponteiro minuto deve se mover apenas quando o segundo passar por uma marcação de hora, ou seja, que o ponteiro minuto deve se mover a cada 5 segundos, notamos que ele deve se mover 0.5º nesse intervalo.
Seguindo a mesma lógica, decidi que o ponteiro de horas se moveria 0.1º por minuto.

Seria mais legal se eu deixasse você fazer esse cálculos...

Sendo assim, a função entrada(), que posicionará os ponteiros de acordo com a hora certa, deve fazer o seguinte:

Posicionar os segundos na posição resultante de segundos*6 (6º por segundo).
Posicionar os minutos na posição resultante de minutos*6+segundos*0.1, que significa 6º por minuto mais 0.5 pra cada 5 segundos que já passaram(seria segundo÷5*0.5, o que dá segundo*0.1).
Posicionar as horas na posição de horas*30+minutos*0.1, o que é a posição daquelas horas mais quantos minutos já se passaram.

No caso, nosso jQuery fica assim:
$(window).load(function(){
 //Elementos - Vamos deixar as Strings prontas para facilitar
 ph = "#clock img.hour";    //Ponteiro Horas
 pm = "#clock img.min";     //Ponteiro Minutos
 ps = "#clock img.sec";     //Ponteiro Segundos
 di = "#clock span.digital";//Digital
 
 
 
 //Hora Certa
 servh = <?php echo date("h"); ?> // 12 horas
 servi = <?php echo date("i"); ?> // minutos
 servs = <?php echo date("s"); ?> // segundos
 servH = <?php echo date("H"); ?> // 24 horas
 
 function entrada(){ // Posiciona os ponteiros antes de começar a rotação
  segrot = servs*6;             //rotação segundos
  minrot = servm*6+servs*0.1;   //rotação minutos
  hourot = servh*30+servm*0.5;  //rotação horas
  $(ps).css("transform","rotate("+segrot+"deg)");   //
  $(pm).css("transform","rotate("+minrot+"deg)");  // Rotações
  $(ph).css("transform","rotate("+hourot+"deg)"); //
  $(di).html(servH+":"+servi+":"+servs);         // Digital
 }
 entrada();
});
Ótimo. Agora precisamos da função que faz ele rodar o tempo todo. Não podemos simplesmente repetir isso, já que gastaríamos mais de um segundo pra pegar hora no servidos por AJAX, o que também ia acabar com a internet do sujeito. Sendo assim, com a hora certa, vamos acrescentando 1 segundo com o jQuery.

Então a função responsável pela rotação será rotacao(), que ficará assim:
function rotacao(){
 secrot += 6;
 if(secrot%30==0) minrot += 0.5;
 hourot += 0.0083;
 servs++;
 if(servs%60==0){
  servi++;
  servs=00;
  if(servi%60==0){
   servH++;
   servi=00;
  }
 }
 
 if(String(servs).length<2)servs = "0"+servs;
 if(String(servi).length<2)servi="0"+servi;
 if(String(servH).length<2)servH="0"+servH;
 var digital = servH+":"+servi+":"+servs;
 $(hp).css({"transform": "rotate("+hourot+"deg)"});
 $(mp).css({"transform": "rotate("+minrot+"deg)"});
 $(sp).css({"transform": "rotate("+secrot+"deg)"});
 $("#clock span.digital").html(digital);
}

E, claro, precisamos fazê-la repetir:
var rotationInterval = setInterval(function(){rotacao();},1000);
Agora a função deverá fazer a rotação até que a pessoa deixe a página.
Se você quiser permitir ao usuário parar o relógio (o que, se não forem feitos alguns ajustes, fará com que a atualização da página seja obrigatória para a retomada do relógio), use a ID deste setInterval, que é rotationInterval para pará-lo. Um exemplo:
$("#para_relogio").click(function(){
clearInterval(rotationInterval);
});
$("#retoma_relogio").click(function(){
location.refresh();
});
Estas funções devem parar o relógio ao clicar em alguma coisa com a id para_relogio, e recarregar a página ao clicar em alguma coisa com a ID retoma_relogio.


Enfim... É isso aí. Valeu!

Sistema inteiramente desenvolvido por mim.
    A primeira versão pode ser conferida em: *Relógio Analógico - Héliton Martyns*
Imagem da base do Relógio, desenvolvida por mim, com o Adobe Photoshop CS6.
Imagem dos ponteiros encontrada no Google e adaptada por mim, usando o Adobe Photoshop CS6.


<Héliton Martyns>
Contato: https://www.facebook.com/messages/notileh --ou-- https://www.facebook.com/notileh --ou-- Comentários aqui em baixo.

Nenhum comentário:

Postar um comentário