🕒

Youtubeの動画とかでよくみる左上に表示される日付とかを表示するためのツールを Svelte で作った

2022/10/08に公開約5,700字

つくったもの

こんな感じに時刻が表示される Web ページをつくりました。

https://mclock.vercel.app/
https://github.com/mirko-san/mclock

これがあると何が嬉しいか

OBS Studio (動画配信などで使うソフト)を使うと、動画や配信画面に現在の日時を表示させることが出来ます。

OBS はブラウザを入力ソースとして用いることが出来るのですが、ソース指定時にカスタムCSSを設定することが出来ます。

ここで font-family を指定することでフォントのカスタマイズも出来ます。

たとえば、URLに https://mclock.vercel.app/ を指定したうえで以下のカスタムCSSを指定すると、すべてのフォントを変えることができます。

@import url('https://fonts.googleapis.com/css2?family=Lexend+Tera:wght@900&display=swap');
* {
  font-family: 'Lexend Tera', sans-serif;
}

補足

やったこととしては全然新しい試みではなくて、既に以下のようなものが世の中に公開されています。

https://booth.pm/ja/items/2912843
https://www.ruri.info/?p=200
https://liveclock.pocopota.com/

技術者目線で Web Component や Svelte と戯れてみたかったというのが動機としては大きいです。
見た目や操作性はかなり先人のツールを参考にさせてもらいました。先人の方々ありがとうございます🙏

技術的なところ

本当は Web Components にして配布したかったので以下を選定しました。

  • Vite
  • Svelte

最近使って体感がすごく良かったので twind も使うことにしました。

  • twind

ですが、 Vite の設定で compilerOptions.customElementtrue にすると twind の CSS が利かなくなってしまいました😢
そのため、いったん Web Component としての配布はいったん断念しています😢
もし Vite + Svelte + twind の構成で Web Components の作成が出来た方はコメントください🙏

最終的にはすごく単純な Web 画面なので何で作ってもよかったなと思っています。

やったこととしては、 vite に svelte のテンプレート生成コマンドがあるので、それで生成されたコード群に src/lib/MClock.svelte を追加しました。

https://svelte.jp/

npm create vite@latest myapp -- --template svelte
src/lib/MClock.svelte
<script lang="ts">
  import { onMount, onDestroy } from "svelte";
  import { tw } from 'twind'
  import { formatISO, format, parseISO } from 'date-fns'

  const timeFormat = $$props['time-format'];
  const zoneString = $$props['zone-string'];
  const dateFormat = $$props['date-format'];

  const dateColor = $$props['date-color'];
  const zoneColor = $$props['zone-color'];
  const timeColor = $$props['time-color'];

  let dateISO = formatISO(new Date());
  let timeString = format(parseISO(dateISO), timeFormat);
  let dateString = format(parseISO(dateISO), dateFormat);
  let interval;

  onMount(() => {
    interval = setInterval(() => {
      dateISO = formatISO(new Date());
      timeString = format(parseISO(dateISO), timeFormat);
      dateString = format(parseISO(dateISO), dateFormat);
    }, 1000);
  });

  onDestroy(() => {
    clearInterval(interval);
  });
</script>

<div class="m-container">
  <div class={tw`inline-block m-8 px-6 pt-4 pb-6 rounded tracking-widest`}>
    <div class={tw`flex items-center mb-1`}>
      <div class={tw`text-xl text-[${dateColor}]`}>
        <span class="m-date">{dateString}</span>
      </div>
      <div class={tw`ml-4 text-sm text-[${zoneColor}]`}>
        <span class="m-zone">( {zoneString} )</span>
      </div>
    </div>

    <div class={tw`text-[${timeColor}] text-6xl align-middle`}>
      <span class="m-time">{timeString}</span>
    </div >
  </div>
</div>

このコンポーネントを以下のように読み込みます。

src/App.svelte
<script lang="ts">
  import MClock from './lib/MClock.svelte'
</script>

<main>
  <div>
    <MClock
      time-format="HH:mm:ss"
      zone-string="Asia/Tokyo"
      date-format="MM/dd E"
      date-color="#111827"
      zone-color="#111827"
      time-color="#111827"
    />
  </div>
</main>

src/lib/MClock.svelte を見ていきます。

以下のように props から各種パラメータを受け取るように作ることで、コンポーネント利用側で柔軟にフォーマットや色などを指定することが出来るようにしました。

  const timeFormat = $$props['time-format'];
  const zoneString = $$props['zone-string'];
  const dateFormat = $$props['date-format'];

  const dateColor = $$props['date-color'];
  const zoneColor = $$props['zone-color'];
  const timeColor = $$props['time-color'];

たとえば、 App.svelteMClock エレメントを以下のように書き換えると見た目を簡単に変えることが出来ます。

    <MClock
      time-format="HH:mm"
      zone-string="Asia/Tokyo"
      date-format="EEEE MMMM d"
      date-color="#7f1d1d"
      zone-color="#7f1d1d"
      time-color="#7f1d1d"
    />

日付のフォーマットは https://date-fns.org/v2.29.3/docs/format のフォーマットに従って指定することが出来ます。

テンプレート部分のコードはかなり twind で楽をしました。

<div class="m-container">
  <div class={tw`inline-block m-8 px-6 pt-4 pb-6 rounded tracking-widest`}>
    <div class={tw`flex items-center mb-1`}>
      <div class={tw`text-xl text-[${dateColor}]`}>
        <span class="m-date">{dateString}</span>
      </div>
      <div class={tw`ml-4 text-sm text-[${zoneColor}]`}>
        <span class="m-zone">( {zoneString} )</span>
      </div>
    </div>

    <div class={tw`text-[${timeColor}] text-6xl align-middle`}>
      <span class="m-time">{timeString}</span>
    </div >
  </div>
</div>

twind というか tailwind css の Arbitrary values を使うことで、色指定のテキストをそのまま渡すことでテキストの色を変えることが出来ています。

<div class={tw`text-[${timeColor}] text-6xl align-middle`}>

ちなみに、 tailwind ではない CSS には m- プレフィックスをつけることで名前空間を切ってあげています。
この m- CSS は OBS でのカスタムCSSでの画面操作を柔軟にする意図でつけており、たとえば以下の CSS でタイムゾーンを非表示にしたり、

.m-zone {
  display: none;
}

時刻のフォントのみ変えることが出来るようにするために付与しています。

@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@900&display=swap');
.m-time {
  font-family: 'Orbitron', sans-serif;
}

細かくCSS Class をつけるとカスタムCSSでの変更自由度が上がるのでイイカンジですね。

さいごに

三連休初日で元気があったので一日で考案 + 実装 + 記事作成までやりましたが、今後は以下のアプデを予定しています。

  • 以下の指定を画面ポチポチで出来るようにする
    • 文字の色
    • 日付・タイムゾーンの表示/非表示
    • 日付や日時のフォーマット
  • 背景を指定できるようにする
    • 単色やグラデ、任意の画像指定など
  • 日付や曜日の日本語化に対応する
  • タイムゾーンのテキストを変更できるようにする

アプデしたら知りたいよ!とかこんな機能がほしいよ!とかあればお気軽に https://twitter.com/mirko_960 までご連絡ください。
可能な人は https://github.com/mirko-san/mclock/issues に issue 立てちゃったもいいです👍

GitHubで編集を提案

Discussion

ログインするとコメントできます