mizzkey/src/client/app/common/views/components/analog-clock.vue

141 lines
3.3 KiB
Vue
Raw Normal View History

2018-02-12 14:07:28 +01:00
<template>
2018-05-29 15:43:03 +02:00
<svg class="mk-analog-clock" viewBox="0 0 10 10" preserveAspectRatio="none">
2018-05-29 21:07:23 +02:00
<circle v-for="angle, i in graduations"
:cx="5 + (Math.sin(angle) * (5 - graduationsPadding))"
:cy="5 - (Math.cos(angle) * (5 - graduationsPadding))"
:r="i % 5 == 0 ? 0.125 : 0.05"
:fill="i % 5 == 0 ? majorGraduationColor : minorGraduationColor"/>
2018-05-29 15:43:03 +02:00
<line
2018-05-29 15:56:05 +02:00
:x1="5 - (Math.sin(sAngle) * (sHandLengthRatio * handsTailLength))"
:y1="5 + (Math.cos(sAngle) * (sHandLengthRatio * handsTailLength))"
2018-05-29 15:43:03 +02:00
:x2="5 + (Math.sin(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
:y2="5 - (Math.cos(sAngle) * ((sHandLengthRatio * 5) - handsPadding))"
:stroke="sHandColor"
stroke-width="0.05"/>
<line
2018-05-29 15:56:05 +02:00
:x1="5 - (Math.sin(mAngle) * (mHandLengthRatio * handsTailLength))"
:y1="5 + (Math.cos(mAngle) * (mHandLengthRatio * handsTailLength))"
2018-05-29 15:43:03 +02:00
:x2="5 + (Math.sin(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
:y2="5 - (Math.cos(mAngle) * ((mHandLengthRatio * 5) - handsPadding))"
:stroke="mHandColor"
stroke-width="0.1"/>
<line
2018-05-29 15:56:05 +02:00
:x1="5 - (Math.sin(hAngle) * (hHandLengthRatio * handsTailLength))"
:y1="5 + (Math.cos(hAngle) * (hHandLengthRatio * handsTailLength))"
2018-05-29 15:43:03 +02:00
:x2="5 + (Math.sin(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
:y2="5 - (Math.cos(hAngle) * ((hHandLengthRatio * 5) - handsPadding))"
:stroke="hHandColor"
stroke-width="0.1"/>
</svg>
2018-02-12 14:07:28 +01:00
</template>
<script lang="ts">
import Vue from 'vue';
import * as tinycolor from 'tinycolor2';
2017-02-20 12:13:42 +01:00
2018-02-12 14:07:28 +01:00
export default Vue.extend({
2018-05-29 16:13:39 +02:00
props: {
dark: {
type: Boolean,
default: false
2018-07-17 19:04:07 +02:00
},
smooth: {
type: Boolean,
default: false
2018-05-29 16:13:39 +02:00
}
},
2018-05-29 21:07:23 +02:00
2018-02-12 14:07:28 +01:00
data() {
return {
2018-05-29 15:43:03 +02:00
now: new Date(),
2018-07-17 11:43:04 +02:00
enabled: true,
2018-05-29 15:43:03 +02:00
graduationsPadding: 0.5,
handsPadding: 1,
2018-05-29 15:56:05 +02:00
handsTailLength: 0.7,
2018-05-29 15:43:03 +02:00
hHandLengthRatio: 0.75,
mHandLengthRatio: 1,
2018-05-29 15:56:05 +02:00
sHandLengthRatio: 1
2018-02-12 14:07:28 +01:00
};
},
2018-05-29 21:07:23 +02:00
2018-05-29 15:43:03 +02:00
computed: {
2018-05-29 21:07:23 +02:00
majorGraduationColor(): string {
2018-05-29 16:13:39 +02:00
return this.dark ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)';
2018-05-29 15:43:03 +02:00
},
2018-05-29 21:07:23 +02:00
minorGraduationColor(): string {
2018-05-29 16:13:39 +02:00
return this.dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)';
2018-05-29 15:43:03 +02:00
},
2018-05-29 16:13:39 +02:00
2018-05-29 15:43:03 +02:00
sHandColor(): string {
2018-05-29 16:13:39 +02:00
return this.dark ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.3)';
2018-05-29 15:43:03 +02:00
},
mHandColor(): string {
2018-05-29 16:13:39 +02:00
return this.dark ? '#fff' : '#777';
2018-05-29 15:43:03 +02:00
},
hHandColor(): string {
2018-12-18 16:45:00 +01:00
return tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--primary')).toHexString();
2018-05-29 15:43:03 +02:00
},
2018-07-17 11:43:04 +02:00
ms(): number {
2018-07-17 19:06:01 +02:00
return this.now.getMilliseconds() * this.smooth;
},
2018-05-29 15:43:03 +02:00
s(): number {
return this.now.getSeconds();
},
m(): number {
return this.now.getMinutes();
},
h(): number {
return this.now.getHours();
},
2018-05-29 16:13:39 +02:00
2018-05-29 15:43:03 +02:00
hAngle(): number {
2018-07-17 19:06:01 +02:00
return Math.PI * (this.h % 12 + (this.m + (this.s + this.ms / 1000) / 60) / 60) / 6;
2018-05-29 15:43:03 +02:00
},
mAngle(): number {
2018-07-17 19:06:01 +02:00
return Math.PI * (this.m + (this.s + this.ms / 1000) / 60) / 30;
2018-05-29 15:43:03 +02:00
},
sAngle(): number {
2018-07-17 19:06:01 +02:00
return Math.PI * (this.s + this.ms / 1000) / 30;
2018-05-29 15:43:03 +02:00
},
graduations(): any {
const angles = [];
for (let i = 0; i < 60; i++) {
const angle = Math.PI * i / 30;
angles.push(angle);
}
return angles;
}
},
2018-05-29 21:07:23 +02:00
2018-02-12 14:07:28 +01:00
mounted() {
2018-07-17 11:43:04 +02:00
const update = () => {
if (this.enabled) {
this.tick();
requestAnimationFrame(update);
}
2018-07-17 18:22:11 +02:00
};
2018-07-17 11:43:04 +02:00
update();
2018-02-12 14:07:28 +01:00
},
2018-05-29 21:07:23 +02:00
2018-02-12 14:07:28 +01:00
beforeDestroy() {
2018-07-17 11:50:13 +02:00
this.enabled = false;
2018-02-12 14:07:28 +01:00
},
2018-05-29 21:07:23 +02:00
2018-02-12 14:07:28 +01:00
methods: {
tick() {
2018-05-29 15:43:03 +02:00
this.now = new Date();
2018-02-12 14:07:28 +01:00
}
}
});
</script>
<style lang="stylus" scoped>
.mk-analog-clock
display block
</style>