mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-04 07:24:13 +00:00 
			
		
		
		
	時計をSVG化
This commit is contained in:
		
							parent
							
								
									d05aee19f2
								
							
						
					
					
						commit
						95d0d0047a
					
				
					 1 changed files with 88 additions and 77 deletions
				
			
		| 
						 | 
					@ -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();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue