parent
							
								
									439563c5d6
								
							
						
					
					
						commit
						a2ce072ae7
					
				
					 4 changed files with 188 additions and 1 deletions
				
			
		|  | @ -293,7 +293,7 @@ export default Vue.extend({ | |||
| 		const ro = new ResizeObserver((entries, observer) => { | ||||
| 			adjustTitlePosition(); | ||||
| 		}); | ||||
| 		 | ||||
| 
 | ||||
| 		ro.observe(this.$refs.contents); | ||||
| 
 | ||||
| 		window.addEventListener('resize', adjustTitlePosition); | ||||
|  | @ -556,6 +556,7 @@ export default Vue.extend({ | |||
| 				'calendar', | ||||
| 				'rss', | ||||
| 				'trends', | ||||
| 				'clock' | ||||
| 			]; | ||||
| 
 | ||||
| 			this.$root.menu({ | ||||
|  |  | |||
							
								
								
									
										143
									
								
								src/client/components/analog-clock.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/client/components/analog-clock.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | |||
| <template> | ||||
| <svg class="mk-analog-clock" viewBox="0 0 10 10" preserveAspectRatio="none"> | ||||
| 	<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"/> | ||||
| 
 | ||||
| 	<line | ||||
| 		:x1="5 - (Math.sin(sAngle) * (sHandLengthRatio * handsTailLength))" | ||||
| 		:y1="5 + (Math.cos(sAngle) * (sHandLengthRatio * handsTailLength))" | ||||
| 		: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 - (Math.sin(mAngle) * (mHandLengthRatio * handsTailLength))" | ||||
| 		:y1="5 + (Math.cos(mAngle) * (mHandLengthRatio * handsTailLength))" | ||||
| 		: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 - (Math.sin(hAngle) * (hHandLengthRatio * handsTailLength))" | ||||
| 		:y1="5 + (Math.cos(hAngle) * (hHandLengthRatio * handsTailLength))" | ||||
| 		: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 * as tinycolor from 'tinycolor2'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	props: { | ||||
| 		dark: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		}, | ||||
| 		smooth: { | ||||
| 			type: Boolean, | ||||
| 			default: false | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			now: new Date(), | ||||
| 			enabled: true, | ||||
| 
 | ||||
| 			graduationsPadding: 0.5, | ||||
| 			handsPadding: 1, | ||||
| 			handsTailLength: 0.7, | ||||
| 			hHandLengthRatio: 0.75, | ||||
| 			mHandLengthRatio: 1, | ||||
| 			sHandLengthRatio: 1 | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	computed: { | ||||
| 		majorGraduationColor(): string { | ||||
| 			return this.dark ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.3)'; | ||||
| 		}, | ||||
| 		minorGraduationColor(): string { | ||||
| 			return this.dark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)'; | ||||
| 		}, | ||||
| 
 | ||||
| 		sHandColor(): string { | ||||
| 			return this.dark ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.3)'; | ||||
| 		}, | ||||
| 		mHandColor(): string { | ||||
| 			return this.dark ? '#fff' : '#777'; | ||||
| 		}, | ||||
| 		hHandColor(): string { | ||||
| 			return tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--primary')).toHexString(); | ||||
| 		}, | ||||
| 
 | ||||
| 		ms(): number { | ||||
| 			return this.now.getMilliseconds() * this.smooth; | ||||
| 		}, | ||||
| 		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 + (this.s + this.ms / 1000) / 60) / 60) / 6; | ||||
| 		}, | ||||
| 		mAngle(): number { | ||||
| 			return Math.PI * (this.m + (this.s + this.ms / 1000) / 60) / 30; | ||||
| 		}, | ||||
| 		sAngle(): number { | ||||
| 			return Math.PI * (this.s + this.ms / 1000) / 30; | ||||
| 		}, | ||||
| 
 | ||||
| 		graduations(): any { | ||||
| 			const angles = []; | ||||
| 			for (let i = 0; i < 60; i++) { | ||||
| 				const angle = Math.PI * i / 30; | ||||
| 				angles.push(angle); | ||||
| 			} | ||||
| 
 | ||||
| 			return angles; | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		const update = () => { | ||||
| 			if (this.enabled) { | ||||
| 				this.tick(); | ||||
| 				requestAnimationFrame(update); | ||||
| 			} | ||||
| 		}; | ||||
| 		update(); | ||||
| 	}, | ||||
| 
 | ||||
| 	beforeDestroy() { | ||||
| 		this.enabled = false; | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		tick() { | ||||
| 			this.now = new Date(); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .mk-analog-clock { | ||||
| 	display: block; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										42
									
								
								src/client/widgets/clock.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/client/widgets/clock.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| <template> | ||||
| <div class="mkw-clock"> | ||||
| 	<mk-container :naked="props.style % 2 === 0" :show-header="false"> | ||||
| 		<div class="mkw-analog-clock--body"> | ||||
| 			<mk-analog-clock :dark="$store.state.device.darkmode" :smooth="props.style < 2"/> | ||||
| 		</div> | ||||
| 	</mk-container> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import define from './define'; | ||||
| 
 | ||||
| import MkContainer from '../components/ui/container.vue'; | ||||
| import MkAnalogClock from '../components/analog-clock.vue'; | ||||
| 
 | ||||
| export default define({ | ||||
| 	name: 'clock', | ||||
| 	props: () => ({ | ||||
| 		style: 0 | ||||
| 	}) | ||||
| }).extend({ | ||||
| 	components: { | ||||
| 		MkContainer, | ||||
| 		MkAnalogClock | ||||
| 	}, | ||||
| 	methods: { | ||||
| 		func() { | ||||
| 			this.props.style = (this.props.style + 1) % 4; | ||||
| 			this.save(); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .mkw-analog-clock { | ||||
| 	.mkw-analog-clock--body { | ||||
| 		padding: 8px; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -6,3 +6,4 @@ Vue.component('mkw-timeline', () => import('./timeline.vue').then(m => m.default | |||
| Vue.component('mkw-calendar', () => import('./calendar.vue').then(m => m.default)); | ||||
| Vue.component('mkw-rss', () => import('./rss.vue').then(m => m.default)); | ||||
| Vue.component('mkw-trends', () => import('./trends.vue').then(m => m.default)); | ||||
| Vue.component('mkw-clock', () => import('./clock.vue').then(m => m.default)); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue