時計をSVG化

This commit is contained in:
syuilo 2018-05-29 22:43:03 +09:00
parent d05aee19f2
commit 95d0d0047a

View file

@ -1,24 +1,103 @@
<template> <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> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { themeColor } from '../../../config'; import { themeColor } from '../../../config';
const Vec2 = function(this: any, x, y) {
this.x = x;
this.y = y;
};
export default Vue.extend({ export default Vue.extend({
data() { data() {
return { 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() { mounted() {
this.tick();
this.clock = setInterval(this.tick, 1000); this.clock = setInterval(this.tick, 1000);
}, },
beforeDestroy() { beforeDestroy() {
@ -26,75 +105,7 @@ export default Vue.extend({
}, },
methods: { methods: {
tick() { tick() {
const canv = this.$refs.canvas as any; this.now = new Date();
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();
}
} }
} }
}); });