summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorfuyu <54523771+mfmfuyu@users.noreply.github.com>2020-02-14 23:31:24 +0900
committerGitHub <noreply@github.com>2020-02-14 23:31:24 +0900
commita2ce072ae7bd9249754f1151efcbbde3aafc3a27 (patch)
tree60998347bf572705493485f503a5f7a40edaa992 /src
parentサムネイルをJPEGで生成するように (#5941) (diff)
downloadsharkey-a2ce072ae7bd9249754f1151efcbbde3aafc3a27.tar.gz
sharkey-a2ce072ae7bd9249754f1151efcbbde3aafc3a27.tar.bz2
sharkey-a2ce072ae7bd9249754f1151efcbbde3aafc3a27.zip
アナログ時計ウィジェットを移植 (#5944)
* アナログ時計ウィジェットを移植 * analog-clock -> clock
Diffstat (limited to 'src')
-rw-r--r--src/client/app.vue3
-rw-r--r--src/client/components/analog-clock.vue143
-rw-r--r--src/client/widgets/clock.vue42
-rw-r--r--src/client/widgets/index.ts1
4 files changed, 188 insertions, 1 deletions
diff --git a/src/client/app.vue b/src/client/app.vue
index c2e60c9bbe..615f6b9cd3 100644
--- a/src/client/app.vue
+++ b/src/client/app.vue
@@ -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({
diff --git a/src/client/components/analog-clock.vue b/src/client/components/analog-clock.vue
new file mode 100644
index 0000000000..a107362240
--- /dev/null
+++ b/src/client/components/analog-clock.vue
@@ -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>
diff --git a/src/client/widgets/clock.vue b/src/client/widgets/clock.vue
new file mode 100644
index 0000000000..bd521813b7
--- /dev/null
+++ b/src/client/widgets/clock.vue
@@ -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>
diff --git a/src/client/widgets/index.ts b/src/client/widgets/index.ts
index 4743be0763..d6af41e2f8 100644
--- a/src/client/widgets/index.ts
+++ b/src/client/widgets/index.ts
@@ -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));