この記事は ドワンゴ 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 なので、先人の肩に乗っかりまくって、ネットに転がっているテンプレから作りました。(ありがとうございます)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 は使えると思うので、いろんな振り返りサービスを見てみたいものです。