From 3a9da789014d3782aa8ac0e735b278744a8a766d Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Sat, 6 Aug 2022 16:39:09 +0900 Subject: [PATCH] enhance(client): improve clock widget --- .../client/src/components/analog-clock.vue | 61 ++++++------------- packages/client/src/widgets/clock.vue | 13 ++-- 2 files changed, 24 insertions(+), 50 deletions(-) diff --git a/packages/client/src/components/analog-clock.vue b/packages/client/src/components/analog-clock.vue index 438152e2dd..170dbb36fa 100644 --- a/packages/client/src/components/analog-clock.vue +++ b/packages/client/src/components/analog-clock.vue @@ -1,44 +1,16 @@ <template> <svg class="mbcofsoe" viewBox="0 0 10 10" preserveAspectRatio="none"> <template v-if="props.graduations === 'dots'"> - <circle - v-for="(angle, i) in graduationsMinor" - :cx="5 + (Math.sin(angle) * (5 - graduationsPadding))" - :cy="5 - (Math.cos(angle) * (5 - graduationsPadding))" - :r="i % 5 == 0 ? 0 : 0.05" - :fill="minorGraduationColor" - /> <circle v-for="(angle, i) in graduationsMajor" :cx="5 + (Math.sin(angle) * (5 - graduationsPadding))" :cy="5 - (Math.cos(angle) * (5 - graduationsPadding))" :r="0.125" - :fill="majorGraduationColor" - /> - </template> - <template v-else-if="props.graduations === 'dotsMajor'"> - <circle - v-for="(angle, i) in graduationsMajor" - :cx="5 + (Math.sin(angle) * (5 - graduationsPadding))" - :cy="5 - (Math.cos(angle) * (5 - graduationsPadding))" - :r="0.125" - :fill="majorGraduationColor" + :fill="(props.twentyfour ? h : h % 12) === i ? nowColor : majorGraduationColor" + :opacity="!props.fadeGraduations || (props.twentyfour ? h : h % 12) === i ? 1 : Math.max(0, 1 - (angleDiff(hAngle, angle) / Math.PI) - numbersOpacityFactor)" /> </template> <template v-else-if="props.graduations === 'numbers'"> - <text - v-for="(angle, i) in texts" - :x="5 + (Math.sin(angle) * (5 - textsPadding))" - :y="5 - (Math.cos(angle) * (5 - textsPadding))" - text-anchor="middle" - dominant-baseline="middle" - font-size="0.75" - fill="currentColor" - > - {{ i === 0 ? (props.twentyfour ? '24' : '12') : i }} - </text> - </template> - <template v-else-if="props.graduations === 'numbersCurrent'"> <text v-for="(angle, i) in texts" :x="5 + (Math.sin(angle) * (5 - textsPadding))" @@ -47,8 +19,8 @@ dominant-baseline="middle" :font-size="(props.twentyfour ? h : h % 12) === i ? 1 : 0.7" :font-weight="(props.twentyfour ? h : h % 12) === i ? 'bold' : 'normal'" - :fill="(props.twentyfour ? h : h % 12) === i ? currentHTextColor : 'currentColor'" - :opacity="(props.twentyfour ? h : h % 12) === i ? 1 : 0.5" + :fill="(props.twentyfour ? h : h % 12) === i ? nowColor : 'currentColor'" + :opacity="!props.fadeGraduations || (props.twentyfour ? h : h % 12) === i ? 1 : Math.max(0, 1 - (angleDiff(hAngle, angle) / Math.PI) - numbersOpacityFactor)" > {{ i === 0 ? (props.twentyfour ? '24' : '12') : i }} </text> @@ -91,33 +63,34 @@ import { ref, computed, onMounted, onBeforeUnmount } from 'vue'; import tinycolor from 'tinycolor2'; import { globalEvents } from '@/events.js'; +// https://stackoverflow.com/questions/1878907/how-can-i-find-the-difference-between-two-angles +const angleDiff = (a: number, b: number) => { + const x = Math.abs(a - b); + return Math.abs((x + Math.PI) % (Math.PI * 2) - Math.PI); +}; + const graduationsPadding = 0.5; -const textsPadding = 0.5; +const textsPadding = 0.6; const handsPadding = 1; const handsTailLength = 0.7; const hHandLengthRatio = 0.75; const mHandLengthRatio = 1; const sHandLengthRatio = 1; -const graduationsMinor = (() => { - const angles: number[] = []; - for (let i = 0; i < 60; i++) { - const angle = Math.PI * i / 30; - angles.push(angle); - } - return angles; -})(); +const numbersOpacityFactor = 0.35; const props = withDefaults(defineProps<{ thickness?: number; offset?: number; twentyfour?: boolean; - graduations?: 'none' | 'dots' | 'dotsMajor' | 'numbers' | 'numbersCurrent'; + graduations?: 'none' | 'dots' | 'numbers'; + fadeGraduations?: boolean; }>(), { numbers: false, thickness: 0.1, offset: 0 - new Date().getTimezoneOffset(), twentyfour: false, graduations: 'dots', + fadeGraduations: true, }); const graduationsMajor = computed(() => { @@ -148,7 +121,7 @@ const minorGraduationColor = ref<string>(); const sHandColor = ref<string>(); const mHandColor = ref<string>(); const hHandColor = ref<string>(); -const currentHTextColor = ref<string>(); +const nowColor = ref<string>(); const s = computed(() => now.value.getSeconds()); const m = computed(() => now.value.getMinutes()); const h = computed(() => now.value.getHours()); @@ -170,7 +143,7 @@ function calcColors() { sHandColor.value = dark ? 'rgba(255, 255, 255, 0.5)' : 'rgba(0, 0, 0, 0.3)'; mHandColor.value = tinycolor(computedStyle.getPropertyValue('--fg')).toHexString(); hHandColor.value = accent; - currentHTextColor.value = accent; + nowColor.value = accent; } calcColors(); diff --git a/packages/client/src/widgets/clock.vue b/packages/client/src/widgets/clock.vue index 905117ab07..c844bdd14e 100644 --- a/packages/client/src/widgets/clock.vue +++ b/packages/client/src/widgets/clock.vue @@ -7,6 +7,7 @@ :thickness="widgetProps.thickness" :offset="tzOffset" :graduations="widgetProps.graduations" + :fade-graduations="widgetProps.fadeGraduations" :twentyfour="widgetProps.twentyFour" /> <div v-if="widgetProps.showLabel" class="label offset">{{ tzOffsetLabel }}</div> @@ -43,7 +44,7 @@ const widgetPropsDef = { }, thickness: { type: 'radio' as const, - default: 0.1, + default: 0.2, options: [{ value: 0.1, label: 'thin', }, { @@ -54,19 +55,19 @@ const widgetPropsDef = { }, graduations: { type: 'radio' as const, - default: 'dots', + default: 'numbers', options: [{ value: 'none', label: 'None', }, { value: 'dots', label: 'Dots', - }, { - value: 'dotsMajor', label: 'Dots (major)', }, { value: 'numbers', label: 'Numbers', - }, { - value: 'numbersCurrent', label: 'Numbers (current)', }], }, + fadeGraduations: { + type: 'boolean' as const, + default: true, + }, twentyFour: { type: 'boolean' as const, default: false, -- GitLab