1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ドワンゴAdvent Calendar 2019

Day 7

PDCAを物理的に回すサービスを Vue.js + typescript で作ってみた(RTA)

Last updated at Posted at 2019-12-07

この記事は ドワンゴ Advent calender 2019 の7日目です。(日にち変わってしまった...)

おばんです。ドワンゴジェイピーという音楽配信サイトのバックエンドを保守している者です。
今回は仕事のネタではなく、趣味で作ろうかなと思っていたサービスを、この機会を借りて作ってみた話をします。
作り始めるのがギリギリになってしまったので、RTAだと開き直ります!

何を作ったの

弊社の Slack には「経済が回る絵文字」があります。社内オークションチャンネルや、お金の話題をするチャンネルで頻用されます。
シュールさが大好きで HTML で再現してみたいなあと常日頃思っていました。

私は「PDCAが回る」ものを作りました。せっかく PDCA なので、入力できる機能もつけようかなと。
ついでに TypeScript の肩慣らし。

動くものはこちらです: https://irimo.github.io/rolling-pdca/dist/

  • 右横の PDCA がスクロールすると動きます。
  • PDCA を入力すると、localStorage に保存されて、自分だけ見返せます。

本当はリアル「PDCAを回す」ために、クリックでコンポーネントを増殖させる機能もつけたかったのですが、またの機会に。

HTML でイメージをつかんだ

PDCA がスクロールで回るものを、まずは JavaScript で作ってみました。

<!DOCTYPE html>
<html lang="en">
<head>
    <script>
        window.onscroll = function()
{
    var scrollTop =
        document.documentElement.scrollTop || // IE、Firefox、Opera
        document.body.scrollTop;              // Chrome、Safari
    var absdiv = document.getElementById("absdiv");
    absdiv.style = "transform: rotate("+scrollTop+"deg)";
}
    </script>
    <style type="text/css">
    #absdiv {
      display: inline-block;
      font-size: 3em;
      position:fixed;
      bottom:20px;
      right:20px;
    }
     
</style>
</head>
<body>
    <div id="absdiv">
    <div class="pdca-wrap">PDCA<br> </div>
</div>
</body>
</html>

素の JS は、懐かしい感じがしますね。

いよいよ Vue + TypeScript を導入

本当は vue コマンドで作った方がいいのですが、今回は RTA なので、先人の肩に乗っかりまくって、ネットに転がっているテンプレから作りました。(ありがとうございます:pray:1

Vue も TypeScript も初ですが、 React を 0.X の時に少し触ったので、コンポーネントの作り方は知っています。そういう方は理解も早いと思います。

PDCA を回すコンポーネント

こちらできたものです。


@Component({
  template: `
  <div class="pdca-wrap" v-bind:style="{transform: styleObject}">PDCA<br> </div>
`,
})

export default class PdcaComponent extends Vue {
  scrollTop: number = 0;
  styleObject: String = "rotate(0deg)"
  mounted(): void {
    window.addEventListener('scroll', this.scrollSpy);
  }
  destroyed(): void {
    window.removeEventListener('scroll', this.scrollSpy);
  }
  scrollSpy() {
      this.scrollTop =
          document.documentElement.scrollTop || // IE、Firefox、Opera
          document.body.scrollTop;              // Chrome、Safari
      this.styleObject = "rotate(" + this.scrollTop + "deg)";
    }
  }

本当は、しかるべきタイミングで PDCA が激しく回るようなパラメタを作りたかったのですが、まだその挙動はイメージが沸かないので保留。

scroll の取り方が、 JavaScript よりスマートですね。
window が取れなかったらググってください2

transform: rotate(scrollTop + deg)という文字列を div の style に渡すとスクロールに合わせてくるくる回るのですが、指定の方法が他の CSS 記法と違うので、手こずりました。

PDCA を入力するコンポーネント

できたものはこちらです。


@Component({
  template: `
  <div class="inputform">
  <form id="myform">
  <span>Plan: </span><input type="text" id="form-plan" v-model:value="t_plan" placeholder="計画を書こう" /><br />
  <span>Do: </span><input type="text" id="form-do" v-model:value="t_do" placeholder="やることに落としこもう" /><br />
  <span>Check: </span><input type="text" id="form-check" v-model:value="t_check" placeholder="やったこと確認しよう" /><br />
  <span>Action: </span><input type="text" id="form-action" v-model:value="t_action" placeholder="次になにする" /><br />
  </form>
  </div>
`,
})

export default class InputForm extends Vue {
        t_plan: string =  "";
        t_do: string =  "";
        t_check: string =  "";
        t_action: string =  "";
constructor() {
        super();
        var plan: string = localStorage.getItem('plan1');
        this.t_plan = plan ? plan : "";
        var val_do: string = localStorage.getItem('do1');
        this.t_do = val_do ? val_do : "";
        var check: string = localStorage.getItem('check1');
        this.t_check = check ? check : "";
        var action: string = localStorage.getItem('action1');
        this.t_action = action ? action : "";
    }
  mounted(): void {
    this.$el.querySelector("#form-plan").addEventListener('keyup', this.blurSpy);
    this.$el.querySelector("#form-do").addEventListener('keyup', this.blurSpy);
    this.$el.querySelector("#form-check").addEventListener('keyup', this.blurSpy);
    this.$el.querySelector("#form-action").addEventListener('keyup', this.blurSpy);
  }
  destroyed(): void {
  }

      blurSpy() {
        localStorage.setItem('plan1', this.t_plan);
        localStorage.setItem('do1', this.t_do);
        localStorage.setItem('check1', this.t_check);
        localStorage.setItem('action1', this.t_action);
    }
  }

本当は配列にした方が利便性がよさそうですが、RTA なので...

ググってもわからなかったのですが、input の値を取ったり差し込んだりしたいときは、v-model:valueとするとよいです。

作成時は仕上げに EventListener を keyup にしたので blur だったものがメソッド名に残っていますが、blur だと入力中にリロードした際、入力内容が消えてしまうのでよくないです。
keyup のレイテンシが気になったのですが、今時大丈夫でした。

localStorage はいきなり localStorage で見られると知ってちょっとびびりました。なんか変なストリーム読み込んだりして頑張るイメージがあったのですが、良かったです。いろいろ気軽に使いたいところ。

まとめ

  • 素の JS より分かりやすく作れた
  • コンポーネントへ style の適用方法、form へ localStorage のデータを差し込む方法がわかった
  • 何にせよ実質5時間ちょっとで作れちゃったのは時代の進化か、ネットの恩恵、デバッグも楽だった

おわりに

今回のメインは PDCA が物理的に回るコンポーネントなので何なんですが、PDCA という振り返りは古いという話を聞きました。振り返りのベストプラクティスとは。どのみち localStorage は使えると思うので、いろんな振り返りサービスを見てみたいものです。

  1. https://ics.media/entry/16329/#webpack-ts-vue

  2. https://sansaisoba.qrunch.io/entries/NrmnZGUHE3xZhO3a

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?