Vueで最初に作ったものがなぜかデジタル時計だったお話

Vueで最初に作ったものがなぜかデジタル時計だったお話:

Vueに触れ始めて少し経ったある日、

「Vueも少しずつ慣れてきたし、何か一つ自分で作ってみようかな。

でもそんなに難しいのはまだ無理だし…。

とりあえず時計作るか!!」

というわけでこんな感じのものができました。



digital_clock.gif


少々ネタではありますが、学んだことを織り交ぜながら紹介していこうと思います。


構成図



digital_clock_parts_discription.PNG


図のようにコンポーネントを作って組み合わせていきます。


LightStick

オンで光ってオフで消える「光る棒!!」を作ります。

縦棒と横棒を選べるようにしておきます。

LightStick.vue
<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

光る棒を組み合わせて数字の形を作ります。



NumberPanelDiscription.PNG


あとは数字に合わせて「光棒何号」を光らせるかを決めるだけです。

「1」なら「いけ!!3号!!6号!!」といった具合です。

NumberPanel.vue
<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

ただの区切りです。ハイ。

Separation.vue
<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です。

時刻の取得については別途解説します。

DigitalClock.vue
<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というのもあるみたいです。

詳しくは見ていません。ハイ。


おわりに

フロント学び始めたばかりだけど自由度が高くて楽しい!!でも難しい!!

今回のももっといい方法があるかもしれませんが、棒を光らせたい!!という思いでこんな感じになってしまいました。

次はもっといいものを作りたいですね。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)