summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-01-08 17:41:09 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-01-08 17:41:09 +0900
commit27c2ca50488680595c114dfae6f8de2ec3c48b32 (patch)
tree913bad82798e39c40e14d1bbc7fa20683bdf3622 /packages/frontend/src/components
parent:art: (diff)
downloadmisskey-27c2ca50488680595c114dfae6f8de2ec3c48b32.tar.gz
misskey-27c2ca50488680595c114dfae6f8de2ec3c48b32.tar.bz2
misskey-27c2ca50488680595c114dfae6f8de2ec3c48b32.zip
feat(client): 🍪👈
Diffstat (limited to 'packages/frontend/src/components')
-rw-r--r--packages/frontend/src/components/MkClickerGame.vue70
-rw-r--r--packages/frontend/src/components/MkPlusOneEffect.vue69
2 files changed, 139 insertions, 0 deletions
diff --git a/packages/frontend/src/components/MkClickerGame.vue b/packages/frontend/src/components/MkClickerGame.vue
new file mode 100644
index 0000000000..6ae202cb63
--- /dev/null
+++ b/packages/frontend/src/components/MkClickerGame.vue
@@ -0,0 +1,70 @@
+<template>
+<div>
+ <div v-if="game.ready" :class="$style.game">
+ <div :class="$style.count" class=""><i class="ti ti-cookie" style="font-size: 70%;"></i> {{ number(cookies) }}</div>
+ <button v-click-anime class="_button" :class="$style.button" @click="onClick">
+ <img src="/client-assets/cookie.png" :class="$style.img">
+ </button>
+ </div>
+ <div v-else>
+ <MkLoading/>
+ </div>
+</div>
+</template>
+
+<script lang="ts" setup>
+import { computed, defineAsyncComponent, onMounted, onUnmounted } from 'vue';
+import MkPlusOneEffect from '@/components/MkPlusOneEffect.vue';
+import * as os from '@/os';
+import { useInterval } from '@/scripts/use-interval';
+import * as game from '@/scripts/clicker-game';
+import number from '@/filters/number';
+
+defineProps<{
+}>();
+
+const saveData = game.saveData;
+const cookies = computed(() => saveData.value?.cookies);
+
+function onClick(ev: MouseEvent) {
+ saveData.value!.cookies++;
+ saveData.value!.clicked++;
+
+ const x = ev.clientX;
+ const y = ev.clientY;
+ os.popup(MkPlusOneEffect, { x, y }, {}, 'end');
+}
+
+useInterval(game.save, 1000 * 5, {
+ immediate: false,
+ afterMounted: true,
+});
+
+onMounted(async () => {
+ await game.load();
+});
+
+onUnmounted(() => {
+ game.save();
+});
+</script>
+
+<style lang="scss" module>
+.game {
+ padding: 16px;
+ text-align: center;
+}
+
+.count {
+ font-size: 1.3em;
+ margin-bottom: 6px;
+}
+
+.button {
+
+}
+
+.img {
+ max-width: 90px;
+}
+</style>
diff --git a/packages/frontend/src/components/MkPlusOneEffect.vue b/packages/frontend/src/components/MkPlusOneEffect.vue
new file mode 100644
index 0000000000..6a09669a68
--- /dev/null
+++ b/packages/frontend/src/components/MkPlusOneEffect.vue
@@ -0,0 +1,69 @@
+<template>
+<div :class="$style.root" :style="{ zIndex, top: `${y - 64}px`, left: `${x - 64}px` }">
+ <span class="text" :class="{ up }">+1</span>
+</div>
+</template>
+
+<script lang="ts" setup>
+import { onMounted } from 'vue';
+import * as os from '@/os';
+
+const props = withDefaults(defineProps<{
+ x: number;
+ y: number;
+}>(), {
+});
+
+const emit = defineEmits<{
+ (ev: 'end'): void;
+}>();
+
+let up = $ref(false);
+const zIndex = os.claimZIndex('middle');
+const angle = (45 - (Math.random() * 90)) + 'deg';
+
+onMounted(() => {
+ window.setTimeout(() => {
+ up = true;
+ }, 10);
+
+ window.setTimeout(() => {
+ emit('end');
+ }, 1100);
+});
+</script>
+
+<style lang="scss" module>
+.root {
+ pointer-events: none;
+ position: fixed;
+ width: 128px;
+ height: 128px;
+
+ &:global {
+ > .text {
+ display: block;
+ height: 1em;
+ text-align: center;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ color: #fff;
+ text-shadow: 0 0 6px #000;
+ font-size: 18px;
+ font-weight: bold;
+ transform: translateY(0px);
+ transition: transform 1s cubic-bezier(0,.5,0,1), opacity 1s cubic-bezier(.5,0,1,.5);
+ will-change: opacity, transform;
+
+ &.up {
+ opacity: 0;
+ transform: translateY(-50px) rotateZ(v-bind(angle));
+ }
+ }
+ }
+}
+</style>