Feat : clickable effect icons
This commit is contained in:
+75
-21
@@ -3,7 +3,8 @@
|
||||
// import { useSettingsStore } from '~/stores/settingsStore';
|
||||
|
||||
export interface Props {
|
||||
card_id: number | undefined
|
||||
uuid?: string
|
||||
card_id?: number
|
||||
locked?: boolean
|
||||
wrapped?: boolean
|
||||
tilted?: boolean
|
||||
@@ -35,22 +36,31 @@ function cardClick() {
|
||||
emit("click")
|
||||
}
|
||||
|
||||
const rotation = ref(0)
|
||||
const isZooming = ref<boolean>(false)
|
||||
|
||||
function mouseenter(e: MouseEvent) {
|
||||
// User is Right Clicking
|
||||
if ((e.buttons & 2) == 2) {
|
||||
isZooming.value = true
|
||||
}
|
||||
|
||||
function mouseenter(e: Event) {
|
||||
// goStore.hoveredCard = props.card_id
|
||||
}
|
||||
function mouseleave(e: Event) {
|
||||
// goStore.hoveredCard = undefined
|
||||
function mouseleave(e: MouseEvent) {
|
||||
isZooming.value = false
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.card_id,
|
||||
() => {
|
||||
props.wrapped ? rotation.value = (Math.random() * 4) - 2 : rotation.value = Math.random() > .5 ? 2 : -2
|
||||
},
|
||||
{ immediate: true })
|
||||
function rightClickDown(e: MouseEvent) {
|
||||
isZooming.value = true
|
||||
}
|
||||
|
||||
function rightClickUp(e: MouseEvent) {
|
||||
isZooming.value = false
|
||||
}
|
||||
|
||||
function activateEffect(e: CustomEvent) {
|
||||
console.log(e.detail, props.uuid)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
card.value?.style.setProperty("--random-seed", -Math.random() * 10 + 's')
|
||||
@@ -58,17 +68,24 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="card" class="card" :class="{ active: childCount > 0, wrapped, unlocked: !props.locked }"
|
||||
@contextmenu.prevent="false" @click.left="cardClick" :style="tilted ? `rotate:${rotation}deg;` : ''"
|
||||
@mouseenter="mouseenter" @mouseleave="mouseleave">
|
||||
<div ref="card" class="card" :class="{ active: childCount > 0, wrapped, unlocked: !props.locked, zoom: isZooming }"
|
||||
@contextmenu.prevent="false" @click.left="cardClick" @mousedown.right="rightClickDown"
|
||||
@mouseup.right="rightClickUp" @mouseenter="mouseenter" @mouseleave="mouseleave">
|
||||
<div id="contextMenuButtons" :ref="(el) => { childCount = ((el as Element)?.childElementCount ?? 0) }">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<img :class="`card_image`" v-if="props.card_id"
|
||||
:src="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + extension"
|
||||
draggable="false">
|
||||
<template v-if="props.card_id">
|
||||
<svg width="180" height="250" v-if="settingsStore.cardStyle == CardStyles.SVG" viewBox="0 0 298 417">
|
||||
<use :xlink:href="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + extension + '#card' + props.card_id"
|
||||
@activate_effect="activateEffect($event)">
|
||||
</use>
|
||||
</svg>
|
||||
<img :class="`card_image`" v-else
|
||||
:src="`/cards/${settingsStore.cardStyle}/` + props.card_id.toString().padStart(3, '0') + extension"
|
||||
draggable="false">
|
||||
</template>
|
||||
|
||||
<img :class="`card_image`" v-if="!props.card_id" :src="'/cards/background.png'" draggable="false">
|
||||
<img :class="`card_image`" v-else :src="'/cards/background.png'" draggable="false">
|
||||
|
||||
</div>
|
||||
|
||||
@@ -82,13 +99,13 @@ onMounted(() => {
|
||||
.card {
|
||||
--max-height: 250px;
|
||||
--margin-bottom: calc(var(--max-height) * 0.05);
|
||||
max-width: 256px;
|
||||
/* max-width: 256px; */
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 0px;
|
||||
margin-top: var(--margin-bottom);
|
||||
transition: all 0.250s cubic-bezier(1, 1.81, .59, 1.42), filter .125s cubic-bezier(0.075, 0.82, 0.165, 1), rotate 0.075s cubic-bezier(1, 1.81, .59, 1.42);
|
||||
transition: all 0.075s cubic-bezier(1, 1.81, .59, 1.42);
|
||||
isolation: isolate;
|
||||
pointer-events: all;
|
||||
max-height: var(--max-height);
|
||||
@@ -146,7 +163,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.card.wrapped {
|
||||
max-height: 6px;
|
||||
height: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -154,6 +171,11 @@ onMounted(() => {
|
||||
filter: drop-shadow(.5px .5px .5px gray) drop-shadow(-.5px -.5px .5px gray);
|
||||
}
|
||||
|
||||
.card.zoom {
|
||||
transform: scale(200%);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#contextMenuButtons {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
@@ -177,4 +199,36 @@ onMounted(() => {
|
||||
border-radius: 12px;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
@keyframes gelatine {
|
||||
|
||||
from,
|
||||
to {}
|
||||
|
||||
25% {
|
||||
transform: scale(1, 1.5);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.5, 1);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: scale(1.1, 1.3);
|
||||
}
|
||||
}
|
||||
|
||||
.svg_resource_icon {
|
||||
cursor: pointer;
|
||||
animation: gelatine 0.3s normal;
|
||||
transition: transform .1s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
.svg_resource_icon:active {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.svg_resource_icon:hover {
|
||||
transform: scale(130%);
|
||||
}
|
||||
</style>
|
||||
@@ -77,7 +77,8 @@ onUnmounted(() => {
|
||||
<template>
|
||||
<div class="cards_container" :class="{ wrapped, rotate }">
|
||||
<TransitionGroup name="list" @enter="onEnter" @leave="onLeave" @before-enter="onBeforeEnter">
|
||||
<CardPreview :card_id="c.cardId" :wrapped="wrapped" v-for="c in cards" :key="c?._id">
|
||||
<CardPreview :card_id="c.cardId" :wrapped="wrapped" v-for="c in cards" :key="c._id"
|
||||
:uuid="c._id.toString()">
|
||||
<slot></slot>
|
||||
</CardPreview>
|
||||
</TransitionGroup>
|
||||
@@ -98,25 +99,29 @@ onUnmounted(() => {
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
.cards_container.wrapped:before {
|
||||
height: calc(250px - 10px);
|
||||
display: block;
|
||||
content: "";
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.rotate {
|
||||
rotate: 360deg;
|
||||
}
|
||||
|
||||
.cards_container {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
min-width: 200px;
|
||||
transition: rotate v-bind('shuffleAnimationSpeed') ease;
|
||||
}
|
||||
|
||||
.cards_container.wrapped {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.cards_container.wrapped:before {
|
||||
height: calc(250px - 10px);
|
||||
display: block;
|
||||
content: "";
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.empty {
|
||||
max-height: 10px;
|
||||
}
|
||||
|
||||
@@ -4,19 +4,20 @@ import type { Container } from '~/netcode/interfaces';
|
||||
|
||||
|
||||
export interface Props {
|
||||
container: Container
|
||||
market: Container
|
||||
fire_gems: Container
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const selfPlayer = computed(() => authStore.logged ? playerList.value?.find(p => p.user.userId == authStore.selfUser.userId) : undefined)
|
||||
// const selfPlayer = computed(() => authStore.logged ? playerList.value?.find(p => p.user.userId == authStore.selfUser.userId) : undefined)
|
||||
|
||||
const isTurn = computed(() => goStore.self && goStore.current_game?.started && (goStore.self.team == goStore.current_game.current_turn))
|
||||
const clientStore = useClientSideStore()
|
||||
// const isTurn = computed(() => goStore.self && goStore.current_game?.started && (goStore.self.team == goStore.current_game.current_turn))
|
||||
// const clientStore = useClientSideStore()
|
||||
|
||||
const buyableFiregem = computed(() => goStore?.current_game?.gem_stack.at(-1))
|
||||
// const buyableFiregem = computed(() => goStore?.current_game?.gem_stack.at(-1))
|
||||
|
||||
|
||||
function onBeforeEnter(el: Element) {
|
||||
@@ -43,63 +44,12 @@ function onEnter(el: any, done: () => unknown) {
|
||||
<div id="market">
|
||||
<CardPreview :tilted="false" :card_id="undefined"></CardPreview>
|
||||
<div class="separator"></div>
|
||||
<TransitionGroup name="market_card">
|
||||
<CardPreview :tilted="false" :card_id="c?.card_id" v-for="c in goStore.current_game?.market"
|
||||
:key="c?.card_id" @click="c && buy(c)">
|
||||
<template
|
||||
v-if="isTurn && goStore.self?.turn && c && c.cost && (goStore.self?.turn.gold_reserve ?? 0) >= c.cost">
|
||||
<button @click.stop="buy(c)">BUY</button>
|
||||
<button @click.stop="clientStore.findUseEffect(CardEffects.PLAY_NEXT_CARD_BOUGHT, c);"
|
||||
v-if="clientStore.activatedClientside.find((e: Effect) => (e.effect == CardEffects.PLAY_NEXT_CARD_BOUGHT) && e.usable)">
|
||||
BUY IN HAND</button>
|
||||
<button @click.stop="clientStore.findUseEffect(CardEffects.STACK_NEXT_CARD_BOUGHT, c)"
|
||||
v-if="clientStore.activatedClientside.find((e: Effect) => (e.effect == CardEffects.STACK_NEXT_CARD_BOUGHT) && e.usable)">
|
||||
BUY IN STACK (generic)</button>
|
||||
|
||||
<button @click.stop="clientStore.findUseEffect(CardEffects.STACK_NEXT_ACTION_BOUGHT, c)"
|
||||
v-if="c.card_type == CardType.ACTION && clientStore.activatedClientside.find((e: Effect) => (e.effect == CardEffects.STACK_NEXT_ACTION_BOUGHT) && e.usable)">
|
||||
BUY IN STACK (actions)</button>
|
||||
</template>
|
||||
</CardPreview>
|
||||
</TransitionGroup>
|
||||
<CardsGrouped :container="market"></CardsGrouped>
|
||||
<div class="separator"></div>
|
||||
<CardPreview :tilted="false" :card_id="goStore.current_game?.gem_stack.at(-1)?.card_id"
|
||||
@click="buy(goStore.current_game?.gem_stack.at(-1)!)">
|
||||
<template
|
||||
v-if="isTurn && goStore.self?.turn && goStore.current_game?.gem_stack.length && goStore.current_game?.gem_stack.length > 0 && (goStore.self?.turn.gold_reserve ?? 0) >= (goStore.current_game?.gem_stack.at(-1)?.cost ?? Infinity)">
|
||||
<button @click.stop="buy(goStore.current_game.gem_stack.at(-1)!)">
|
||||
BUY
|
||||
</button>
|
||||
<button @click.stop="clientStore.findUseEffect(CardEffects.PLAY_NEXT_CARD_BOUGHT, buyableFiregem)"
|
||||
v-if="buyableFiregem && clientStore.activatedClientside.find((e: Effect) => (e.effect == CardEffects.PLAY_NEXT_CARD_BOUGHT) && e.usable)">
|
||||
BUY IN HAND</button>
|
||||
<button @click.stop="clientStore.findUseEffect(CardEffects.STACK_NEXT_CARD_BOUGHT, buyableFiregem)"
|
||||
v-if="buyableFiregem && clientStore.activatedClientside.find((e: Effect) => (e.effect == CardEffects.STACK_NEXT_CARD_BOUGHT) && e.usable)">
|
||||
BUY IN STACK(generic)
|
||||
</button>
|
||||
</template>
|
||||
</CardPreview>
|
||||
<CardsGrouped :container="fire_gems" :wrapped="true"></CardsGrouped>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
/* .market_card-leave-active,
|
||||
.market_card-move {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.market_card-enter-from {
|
||||
transform: translate(-500px);
|
||||
}
|
||||
|
||||
|
||||
.market_card-enter-active,
|
||||
.market_card-leave-active {
|
||||
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
|
||||
} */
|
||||
</style>
|
||||
<style scoped>
|
||||
#market {
|
||||
width: min-content;
|
||||
@@ -118,7 +68,6 @@ function onEnter(el: any, done: () => unknown) {
|
||||
filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, .60));
|
||||
backdrop-filter: blur(5px) brightness(80%);
|
||||
background: rgba(155, 62, 62, 0.46);
|
||||
|
||||
}
|
||||
|
||||
.separator {
|
||||
|
||||
Reference in New Issue
Block a user