🎨
This commit is contained in:
parent
ee6e022b2a
commit
527fe9046e
7 changed files with 80 additions and 10 deletions
|
@ -81,7 +81,7 @@ import { ref, computed, watch, onMounted } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import XSection from '@/components/MkEmojiPicker.section.vue';
|
import XSection from '@/components/MkEmojiPicker.section.vue';
|
||||||
import { emojilist, UnicodeEmojiDef, unicodeEmojiCategories as categories } from '@/scripts/emojilist';
|
import { emojilist, UnicodeEmojiDef, unicodeEmojiCategories as categories } from '@/scripts/emojilist';
|
||||||
import Ripple from '@/components/MkRipple.vue';
|
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { isTouchUsing } from '@/scripts/touch';
|
import { isTouchUsing } from '@/scripts/touch';
|
||||||
import { deviceKind } from '@/scripts/device-kind';
|
import { deviceKind } from '@/scripts/device-kind';
|
||||||
|
@ -288,7 +288,7 @@ function chosen(emoji: any, ev?: MouseEvent) {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(Ripple, { x, y }, {}, 'end');
|
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = getKey(emoji);
|
const key = getKey(emoji);
|
||||||
|
|
66
packages/frontend/src/components/MkPlusOneEffect.vue
Normal file
66
packages/frontend/src/components/MkPlusOneEffect.vue
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<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('high');
|
||||||
|
|
||||||
|
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: var(--accent);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
transform: translateY(-30px);
|
||||||
|
transition: transform 1s cubic-bezier(0,.5,0,1), opacity 1s cubic-bezier(.5,0,1,.5);
|
||||||
|
|
||||||
|
&.up {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-50px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -97,7 +97,7 @@ import { instance } from '@/instance';
|
||||||
import { $i, getAccounts, openAccountMenu as openAccountMenu_ } from '@/account';
|
import { $i, getAccounts, openAccountMenu as openAccountMenu_ } from '@/account';
|
||||||
import { uploadFile } from '@/scripts/upload';
|
import { uploadFile } from '@/scripts/upload';
|
||||||
import { deepClone } from '@/scripts/clone';
|
import { deepClone } from '@/scripts/clone';
|
||||||
import Ripple from '@/components/MkRipple.vue';
|
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||||
|
|
||||||
const modal = inject('modal');
|
const modal = inject('modal');
|
||||||
|
|
||||||
|
@ -575,7 +575,7 @@ async function post(ev?: MouseEvent) {
|
||||||
const rect = el.getBoundingClientRect();
|
const rect = el.getBoundingClientRect();
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
os.popup(Ripple, { x, y }, {}, 'end');
|
os.popup(MkRippleEffect, { x, y }, {}, 'end');
|
||||||
}
|
}
|
||||||
|
|
||||||
let postData = {
|
let postData = {
|
||||||
|
|
|
@ -19,6 +19,7 @@ import XReactionIcon from '@/components/MkReactionIcon.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { useTooltip } from '@/scripts/use-tooltip';
|
import { useTooltip } from '@/scripts/use-tooltip';
|
||||||
import { $i } from '@/account';
|
import { $i } from '@/account';
|
||||||
|
import MkPlusOneEffect from '@/components/MkPlusOneEffect.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
reaction: string;
|
reaction: string;
|
||||||
|
@ -57,7 +58,10 @@ const toggleReaction = () => {
|
||||||
const anime = () => {
|
const anime = () => {
|
||||||
if (document.hidden) return;
|
if (document.hidden) return;
|
||||||
|
|
||||||
// TODO: 新しくリアクションが付いたことが視覚的に分かりやすいアニメーション
|
const rect = buttonRef.value.getBoundingClientRect();
|
||||||
|
const x = rect.left + (buttonRef.value.offsetWidth / 2);
|
||||||
|
const y = rect.top + (buttonRef.value.offsetHeight / 2);
|
||||||
|
os.popup(MkPlusOneEffect, { x, y }, {}, 'end');
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(() => props.count, (newCount, oldCount) => {
|
watch(() => props.count, (newCount, oldCount) => {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { toRefs, Ref } from 'vue';
|
import { toRefs, Ref } from 'vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import Ripple from '@/components/MkRipple.vue';
|
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -45,7 +45,7 @@ const toggle = () => {
|
||||||
const rect = button.getBoundingClientRect();
|
const rect = button.getBoundingClientRect();
|
||||||
const x = rect.left + (button.offsetWidth / 2);
|
const x = rect.left + (button.offsetWidth / 2);
|
||||||
const y = rect.top + (button.offsetHeight / 2);
|
const y = rect.top + (button.offsetHeight / 2);
|
||||||
os.popup(Ripple, { x, y, particle: false }, {}, 'end');
|
os.popup(MkRippleEffect, { x, y, particle: false }, {}, 'end');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Ripple from '@/components/MkRipple.vue';
|
import MkRippleEffect from '@/components/MkRippleEffect.vue';
|
||||||
import { popup } from '@/os';
|
import { popup } from '@/os';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -12,7 +12,7 @@ export default {
|
||||||
const x = rect.left + (el.offsetWidth / 2);
|
const x = rect.left + (el.offsetWidth / 2);
|
||||||
const y = rect.top + (el.offsetHeight / 2);
|
const y = rect.top + (el.offsetHeight / 2);
|
||||||
|
|
||||||
popup(Ripple, { x, y }, {}, 'end');
|
popup(MkRippleEffect, { x, y }, {}, 'end');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue