Vueに触れ始めて少し経ったある日、
「Vueも少しずつ慣れてきたし、何か一つ自分で作ってみようかな。
でもそんなに難しいのはまだ無理だし…。
とりあえず時計作るか!!」
というわけでこんな感じのものができました。
少々ネタではありますが、学んだことを織り交ぜながら紹介していこうと思います。
構成図
図のようにコンポーネントを作って組み合わせていきます。
LightStick
オンで光ってオフで消える**「光る棒!!」**を作ります。
縦棒と横棒を選べるようにしておきます。
<template>
<div class="stick" :class="[type, {light: light}]" />
</template>
<script>
export default {
props: {
type: {
typs: String,
default: 'vertical'
}
},
data() {
return {
light: false
}
},
methods: {
on() {
this.light = true
},
off() {
this.light = false
}
}
}
</script>
<style scoped>
.stick {
background-color: rgba(200,255,200,0.2);
border-radius: 10px;
}
.vertical {
height: 50px;
width: 10px;
}
.horizontal {
height: 10px;
width: 50px;
}
.light {
background-color: yellowgreen;
}
</style>
NumberPanel
光る棒を組み合わせて数字の形を作ります。
あとは数字に合わせて「光棒何号」を光らせるかを決めるだけです。
「1」なら「いけ!!3号!!6号!!」といった具合です。
<template>
<div class="number-panel">
<light-stick type="horizontal" class="stick stick1" ref="stick1" />
<light-stick type="vertical" class="stick stick2" ref="stick2" />
<light-stick type="vertical" class="stick stick3" ref="stick3" />
<light-stick type="horizontal" class="stick stick4" ref="stick4" />
<light-stick type="vertical" class="stick stick5" ref="stick5" />
<light-stick type="vertical" class="stick stick6" ref="stick6" />
<light-stick type="horizontal" class="stick stick7" ref="stick7" />
</div>
</template>
<script>
import LightStick from "./LightStick"
export default {
components: {
LightStick
},
props: {
number: 0
},
watch: {
number() { //numberの変更とともに表示
this.display()
}
},
mounted() { //初期表示設定
this.display()
},
methods: {
display() {
switch(this.number) {
case 0:
this.zero()
break
case 1:
this.one()
break
case 2:
this.two()
break
case 3:
this.three()
break
case 4:
this.four()
break
case 5:
this.five()
break
case 6:
this.six()
break
case 7:
this.seven()
break
case 8:
this.eight()
break
case 9:
this.nine()
break
}
},
clear() {
this.$refs.stick1.off() //子コンポーネントのメソッド呼び出しにはref属性を使用
this.$refs.stick2.off()
this.$refs.stick3.off()
this.$refs.stick4.off()
this.$refs.stick5.off()
this.$refs.stick6.off()
this.$refs.stick7.off()
},
one() {
this.clear()
this.$refs.stick3.on()
this.$refs.stick6.on()
},
two() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick3.on()
this.$refs.stick4.on()
this.$refs.stick5.on()
this.$refs.stick7.on()
},
three() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick3.on()
this.$refs.stick4.on()
this.$refs.stick6.on()
this.$refs.stick7.on()
},
four() {
this.clear()
this.$refs.stick2.on()
this.$refs.stick3.on()
this.$refs.stick4.on()
this.$refs.stick6.on()
},
five() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick2.on()
this.$refs.stick4.on()
this.$refs.stick6.on()
this.$refs.stick7.on()
},
six() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick2.on()
this.$refs.stick4.on()
this.$refs.stick5.on()
this.$refs.stick6.on()
this.$refs.stick7.on()
},
seven() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick3.on()
this.$refs.stick6.on()
},
eight() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick2.on()
this.$refs.stick3.on()
this.$refs.stick4.on()
this.$refs.stick5.on()
this.$refs.stick6.on()
this.$refs.stick7.on()
},
nine() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick2.on()
this.$refs.stick3.on()
this.$refs.stick4.on()
this.$refs.stick6.on()
this.$refs.stick7.on()
},
zero() {
this.clear()
this.$refs.stick1.on()
this.$refs.stick2.on()
this.$refs.stick3.on()
this.$refs.stick5.on()
this.$refs.stick6.on()
this.$refs.stick7.on()
}
}
}
</script>
<style scoped>
.number-panel {
background-color: #222;
position: relative;
height: 130px;
width: 70px;
}
.stick {
position: absolute;
}
.stick1 {
top: 0;
left: 10px;
}
.stick2 {
top: 10px;
left: 0;
}
.stick3 {
top: 10px;
left: 60px;
}
.stick4 {
top: 60px;
left: 10px;
}
.stick5 {
top: 70px;
left: 0;
}
.stick6 {
top: 70px;
left: 60px;
}
.stick7 {
top: 120px;
left: 10px;
}
</style>
Separation
ただの区切りです。ハイ。
<template>
<div class="colon">
<div class="circle" />
<div class="circle" />
</div>
</template>
<style scoped>
.circle {
background-color: yellowgreen;
border-radius: 5px;
width: 10px;
height: 10px;
}
.colon {
height: 130px;
display: flex;
flex-direction: column;
justify-content: space-around;
}
</style>
DigitalClock
NumberPanelとSeparationを並べて時計の形を作ります。
あとは時刻の各値をNumberPanelに割り当てればOKです。
時刻の取得については別途解説します。
<template>
<div class="clock">
<div class="display">
<number-panel :number="hours2" />
<number-panel :number="hours1" />
<separation />
<number-panel :number="minutes2" />
<number-panel :number="minutes1" />
<separation />
<number-panel :number="seconds2" />
<number-panel :number="seconds1" />
</div>
</div>
</template>
<script>
import NumberPanel from "./NumberPanel"
import Separation from "./Separation"
import moment from "moment"
export default {
components: {
NumberPanel,
Separation
},
data() {
return {
time: undefined,
intervalId: undefined
}
},
methods: {
setTime() {
this.intervalId = setInterval(() => {
this.time = new Date()
}, 100)
}
},
mounted() {
this.setTime()
},
beforeDestroy() {
clearInterval(this.intervalId)
},
computed: {
hours1() {
return moment(this.time).format("HH") % 10
},
hours2() {
return Math.floor(moment(this.time).format("HH") / 10)
},
minutes1() {
return moment(this.time).format("mm") % 10
},
minutes2() {
return Math.floor(moment(this.time).format("mm") / 10)
},
seconds1() {
return moment(this.time).format("ss") % 10
},
seconds2() {
return Math.floor(moment(this.time).format("ss") / 10)
}
}
}
</script>
<style scoped>
.clock {
background-color: #111;
filter: drop-shadow(10px 10px 10px rgba(0,0,0,0.6));
padding: 50px;
}
.display {
background-color: #222;
display: flex;
justify-content: space-between;
padding: 10px;
width: 600px;
}
</style>
setInterval
時計を実装するために一定間隔で時刻を取得する必要があります。
その時に使用するのがsetIntervalです。
data() {
return {
intervalId: undefined //1. clearIntervalのためのIDを保持します
}
},
methods: {
do() { //2. 一定間隔で処理を実行するためメソッドを用意します
this.intervalId = setInterval(() => {
//処理内容
}, 1000) //1秒間隔で処理
}
},
mounted() { //3. 上記で用意したメソッドをマウントのタイミングで呼び出します。
// これによりこのコンポーネントは一定間隔で処理を実行することになります。
this.do()
},
beforeDestroy() { //4. 使用後はしっかりとクリアする必要があります
clearInterval(this.intervalId)
}
Moment.js
$npm install moment
javascriptで日付処理を容易にするためのライブラリです。
今回はフォーマットで使用しています。
これ以上はすみませんが割愛します。
vue-momentというのもあるみたいです。
詳しくは見ていません。ハイ。
おわりに
フロント学び始めたばかりだけど自由度が高くて楽しい!!でも難しい!!
今回のももっといい方法があるかもしれませんが、**棒を光らせたい!!**という思いでこんな感じになってしまいました。
次はもっといいものを作りたいですね。