diff --git a/src/client/app/desktop/views/components/analog-clock.vue b/src/client/app/desktop/views/components/analog-clock.vue index 81eec81598..7b5caf9f27 100644 --- a/src/client/app/desktop/views/components/analog-clock.vue +++ b/src/client/app/desktop/views/components/analog-clock.vue @@ -1,24 +1,103 @@ <template> -<canvas class="mk-analog-clock" ref="canvas" width="256" height="256"></canvas> +<svg class="mk-analog-clock" viewBox="0 0 10 10" preserveAspectRatio="none"> + <line v-for="angle, i in graduations" + :x1="5 + (Math.sin(angle) * (5 - graduationsPadding))" + :y1="5 - (Math.cos(angle) * (5 - graduationsPadding))" + :x2="5 + (Math.sin(angle) * ((5 - graduationsPadding) - (i % 5 == 0 ? longGraduationLength : shortGraduationLength)))" + :y2="5 - (Math.cos(angle) * ((5 - graduationsPadding) - (i % 5 == 0 ? longGraduationLength : shortGraduationLength)))" + :stroke="i % 5 == 0 ? longGraduationColor : shortGraduationColor" + stroke-width="0.05"/> + + <line + x1="5" + y1="5" + :x2="5 + (Math.sin(sAngle) * ((sHandLengthRatio * 5) - handsPadding))" + :y2="5 - (Math.cos(sAngle) * ((sHandLengthRatio * 5) - handsPadding))" + :stroke="sHandColor" + stroke-width="0.05"/> + <line + x1="5" + y1="5" + :x2="5 + (Math.sin(mAngle) * ((mHandLengthRatio * 5) - handsPadding))" + :y2="5 - (Math.cos(mAngle) * ((mHandLengthRatio * 5) - handsPadding))" + :stroke="mHandColor" + stroke-width="0.1"/> + <line + x1="5" + y1="5" + :x2="5 + (Math.sin(hAngle) * ((hHandLengthRatio * 5) - handsPadding))" + :y2="5 - (Math.cos(hAngle) * ((hHandLengthRatio * 5) - handsPadding))" + :stroke="hHandColor" + stroke-width="0.1"/> +</svg> </template> <script lang="ts"> import Vue from 'vue'; import { themeColor } from '../../../config'; -const Vec2 = function(this: any, x, y) { - this.x = x; - this.y = y; -}; - export default Vue.extend({ data() { return { - clock: null + now: new Date(), + clock: null, + + graduationsPadding: 0.5, + longGraduationLength: 0.3, + shortGraduationLength: 0.15, + handsPadding: 1, + hHandLengthRatio: 0.75, + mHandLengthRatio: 1, + sHandLengthRatio: 1, }; }, + computed: { + longGraduationColor(): string { + return 'rgba(255, 255, 255, 0.3)'; + }, + shortGraduationColor(): string { + return 'rgba(255, 255, 255, 0.2)'; + }, + sHandColor(): string { + return 'rgba(255, 255, 255, 0.5)'; + }, + mHandColor(): string { + return '#fff'; + }, + hHandColor(): string { + return themeColor; + }, + + s(): number { + return this.now.getSeconds(); + }, + m(): number { + return this.now.getMinutes(); + }, + h(): number { + return this.now.getHours(); + }, + hAngle(): number { + return Math.PI * (this.h % 12 + this.m / 60) / 6; + }, + mAngle(): number { + return Math.PI * (this.m + this.s / 60) / 30; + }, + sAngle(): number { + return Math.PI * this.s / 30; + }, + + graduations(): any { + const angles = []; + for (let i = 0; i < 60; i++) { + const angle = Math.PI * i / 30; + angles.push(angle); + } + + return angles; + } + }, mounted() { - this.tick(); this.clock = setInterval(this.tick, 1000); }, beforeDestroy() { @@ -26,75 +105,7 @@ export default Vue.extend({ }, methods: { tick() { - const canv = this.$refs.canvas as any; - - const now = new Date(); - const s = now.getSeconds(); - const m = now.getMinutes(); - const h = now.getHours(); - - const ctx = canv.getContext('2d'); - const canvW = canv.width; - const canvH = canv.height; - ctx.clearRect(0, 0, canvW, canvH); - - { // 背景 - const center = Math.min((canvW / 2), (canvH / 2)); - const lineStart = center * 0.90; - const shortLineEnd = center * 0.87; - const longLineEnd = center * 0.84; - for (let i = 0; i < 60; i++) { - const angle = Math.PI * i / 30; - const uv = new Vec2(Math.sin(angle), -Math.cos(angle)); - ctx.beginPath(); - ctx.lineWidth = 1; - ctx.moveTo((canvW / 2) + uv.x * lineStart, (canvH / 2) + uv.y * lineStart); - if (i % 5 == 0) { - ctx.strokeStyle = 'rgba(255, 255, 255, 0.2)'; - ctx.lineTo((canvW / 2) + uv.x * longLineEnd, (canvH / 2) + uv.y * longLineEnd); - } else { - ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)'; - ctx.lineTo((canvW / 2) + uv.x * shortLineEnd, (canvH / 2) + uv.y * shortLineEnd); - } - ctx.stroke(); - } - } - - { // 分 - const angle = Math.PI * (m + s / 60) / 30; - const length = Math.min(canvW, canvH) / 2.6; - const uv = new Vec2(Math.sin(angle), -Math.cos(angle)); - ctx.beginPath(); - ctx.strokeStyle = '#ffffff'; - ctx.lineWidth = 2; - ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5); - ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length); - ctx.stroke(); - } - - { // 時 - const angle = Math.PI * (h % 12 + m / 60) / 6; - const length = Math.min(canvW, canvH) / 4; - const uv = new Vec2(Math.sin(angle), -Math.cos(angle)); - ctx.beginPath(); - ctx.strokeStyle = themeColor; - ctx.lineWidth = 2; - ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5); - ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length); - ctx.stroke(); - } - - { // 秒 - const angle = Math.PI * s / 30; - const length = Math.min(canvW, canvH) / 2.6; - const uv = new Vec2(Math.sin(angle), -Math.cos(angle)); - ctx.beginPath(); - ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)'; - ctx.lineWidth = 1; - ctx.moveTo(canvW / 2 - uv.x * length / 5, canvH / 2 - uv.y * length / 5); - ctx.lineTo(canvW / 2 + uv.x * length, canvH / 2 + uv.y * length); - ctx.stroke(); - } + this.now = new Date(); } } });