🕰️

JavaScript30 DAY2:CSS + JS Clock実装を通して気になる技術をまとめる

2023/10/20に公開

1.記事の目的

初めてzennで記事を書きます。
プログラミングの学び始めがJavascriptで、現在もJavascriptに関わりながら仕事をしているので、書くならJavascriptかな?と思いました。
そこで、Javascript30の中からいくつか実装しながら、「こんなことできるんだ!」というところをまとめようかなと思いました。
https://javascript30.com/

2.Javascript30について

30 Day Vanilla JS Coding Challenge
Build 30 things in 30 days with 30 tutorials
No Frameworks×No Compilers×No Libraries×No Boilerplate

こちらのサイトは30本の動画(1本10-30分程度です)から構成されており、フレームワークやライブラリなしのJavascriptで色々なものを作ってみよう!というコンセプトです。

Sign up to get immediate access to the course dashboard
You'll get all 30 days at once so you can binge watch Netflix style.

メールアドレスで無料で登録できて、登録したらすぐに30本の動画が見られます。
ちなみに動画は英語です😇
私は英語のリスニングが終わっているので、字幕をつけて再生速度を落としてなんとか解読しています。

https://github.com/wesbos/JavaScript30

コードも全て公開されています。

動画は、というかコンテンツ全て英語ですが、Javascriptの基礎がまとめられたページがあったり、有料のコースにはなりますがビギナー向けのJavascriptコースがあったりNode.jsのコースがあったり(Javascipt30はWesBosというサイトの1コース)、面白いサイトだと思います。

3.なんでいきなりDay2なの?

基礎的なものから取り組みたいな、と思いFUNDAMENTALSタグ(画像のピンク色タグ)のついているものからやっていこうと思います。
とりあえず目指せFUNDAMENTALS全投稿。

4.HTML&CSS&JS

早速コードです。
動画で出ているものと違いは、

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JS + CSS Clock</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
  <div class="clock">
    <div class="clock-face">
      <div class="hand hour-hand"></div>
      <div class="hand min-hand"></div>
      <div class="hand second-hand"></div>
    </div>
  </div>
  <script src="script.js"></script>
</body>
</html>
styles.CSS

  html {
    font-family: 'helvetica neue';
    text-align: center;
    font-size: 10px;
  }
  
  body {
    margin: 0;
    font-size: 2rem;
    display: flex;
    flex: 1;
    min-height: 100vh;
    align-items: center;
  }
  
  .clock {
    width: 30rem;
    height: 30rem;
    border: 20px solid white;
    border-radius: 50%;
    margin: 50px auto;
    position: relative;
    padding: 2rem;
    box-shadow:
      0 0 0 4px rgba(0,0,0,0.1),
      inset 0 0 0 3px #EFEFEF,
      inset 0 0 10px black,
      0 0 10px rgba(0,0,0,0.2);
  }
  
  .clock-face {
    position: relative;
    width: 100%;
    height: 100%;
    transform: translateY(-3px);
  }
  
  .hand {
    width: 50%;
    height: 6px;
    background: black;
    position: absolute;
    top: 50%;
    transform-origin: 100%;
    transform: rotate(90deg);
    transition: all 0.05s;
    transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
  }
script.js

const secondHand = document.querySelector('.second-hand');
const minsHand = document.querySelector('.min-hand');
const hourHand = document.querySelector('.hour-hand');

function setDate() {
  const now = new Date();
  const jpTime = new Date(now.toLocaleString({ timeZone: 'Asia/Tokyo' }));

  const seconds = jpTime.getSeconds();
  const secondsDegrees = ((seconds / 60) * 360) + 90;
  secondHand.style.transform = `rotate(${secondsDegrees}deg`;

  const mins = jpTime.getMinutes();
  const minsDegrees = ((mins / 60) * 360) + ((seconds / 60) * 6) + 90;
  minsHand.style.transform = `rotate(${minsDegrees}deg)`;

  const hour = jpTime.getHours();
  const hourDegrees = ((hour / 12) * 360) + ((mins / 60) * 30) + 90;
  hourHand.style.transform = `rotate(${hourDegrees}deg)`;
}

setInterval(setDate, 1000);

setDate();

5.気になったポイント

1.CSS

JSでなく、CSSで気になったポイントがありました。先にそちらから。
.handで針の形とアニメーションを実装しています。

transform-origin: 100%;
transform: rotate(90deg);

transform-originでtransformの原点を定義(100%だと右端になるそうです)
.handのCSS部分からtransform: rotate(90deg);を除くと、針の形をしたものが時計の真ん中に3本9時の方向を向いて揃います。
それにtransform: rotate(90deg);を適用すると、12時の方向を向いたものになります。
これが針の初期状態ということになるのかな。
https://developer.mozilla.org/ja/docs/Web/CSS/transform-origin
https://developer.mozilla.org/ja/docs/Web/CSS/transform

transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);

これはなんだ?と思ったのですが、アニメーションの加速曲線を定義しているようです。
https://developer.mozilla.org/ja/docs/Web/CSS/transition-timing-function
動画内での解説では微妙に後ろに戻るような加速曲線にすることで、より時計的な動きになるようにしているということだと思う。

transformやtransitionが使いこなせるとCSSの幅が広がりますね。

2.document.querySelector()

getElementById()やgetElemetnsByClassName()のようにHTML要素を検出・取得するメソッド。

指定されたセレクターまたはセレクター群に一致する、文書内の最初の Element を返します。

https://developer.mozilla.org/ja/docs/Web/API/Document/querySelector

とのことで、該当する要素が複数個あっても最初の一つしか返してくれません。
https://zenn.dev/harryduck/articles/e3e6c9d37e0169c05096

3.new Data()

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/Date
new DATAに引数をつけなければ世界標準時間(グリニッジ天文台の時刻)が表示されるようです。

上記した通り、これを日本時間に変更しています。

4.getSeconds() & getMinutes() & getHours()

これらでjpTimeの秒、分、時間を取得しています。

ここはそんなに難しいこともなく…参考にgetSeconds()のMDNです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/getSeconds

5.style.transform

transformしたい要素に対して要素.style.transform = transform内容と記載します。
https://mebee.info/2020/08/13/post-16557/

ここでは、秒ごとに針の角度を算出してrotate(${secondsDegrees}degのように、針の角度が変わるようにしています。

6.最後に

初めて書いたので、至らない点もあるかと思います。
書いてみた感想としては、慣れないことして疲れたというのが率直なところですが、できれば続けていきたいです。

明らかな技術的間違いなどに気づかれた方はぜひご指摘いただけるとありがたいです。

Discussion