Animations
This commit is contained in:
		
							parent
							
								
									903bc35bd3
								
							
						
					
					
						commit
						ba01bba5dc
					
				| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
<script setup lang="ts"></script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <RouterView class="container mx-auto h-full" />
 | 
			
		||||
  <RouterView class="container mx-auto h-full px-2" />
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,61 +1,68 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <TransitionGroup name="slide_up">
 | 
			
		||||
    <div
 | 
			
		||||
      class="mb-2 text-center"
 | 
			
		||||
      v-for="(op, i) in operations"
 | 
			
		||||
      :style="{ transitionDelay: `${transDelay * (operations.length - i)}ms` }"
 | 
			
		||||
      :key="i">
 | 
			
		||||
      <div class="inline-block relative text-xl">
 | 
			
		||||
        <!-- OPERATION -->
 | 
			
		||||
        <div
 | 
			
		||||
          class="flex items-center"
 | 
			
		||||
          :class="{ 'text-red-600': isOperationInvalid(op) }">
 | 
			
		||||
          <!-- LEFT -->
 | 
			
		||||
          <div class="w-[2.5em] border-b border-stone-600 transition-all">
 | 
			
		||||
            {{ op.left?.value ?? ' ' }}
 | 
			
		||||
          </div>
 | 
			
		||||
          <!-- RIGHT -->
 | 
			
		||||
          <div class="w-[2.5em] border-b border-stone-600 transition-all">
 | 
			
		||||
            {{ op.operator ?? ' ' }}
 | 
			
		||||
          </div>
 | 
			
		||||
  <div>
 | 
			
		||||
    <TransitionGroup name="slide_up">
 | 
			
		||||
      <div
 | 
			
		||||
        class="mb-2 text-center"
 | 
			
		||||
        v-for="(op, i) in operations"
 | 
			
		||||
        :style="{
 | 
			
		||||
          transitionDelay: `${transDelay * (operations.length - i)}ms`,
 | 
			
		||||
        }"
 | 
			
		||||
        :key="i">
 | 
			
		||||
        <div class="inline-block relative text-xl">
 | 
			
		||||
          <!-- OPERATION -->
 | 
			
		||||
          <div
 | 
			
		||||
            class="flex items-center"
 | 
			
		||||
            :class="{ 'text-red-600': isOperationInvalid(op) }">
 | 
			
		||||
            <!-- LEFT -->
 | 
			
		||||
            <div class="w-[2.5em] border-b border-stone-600 transition-all">
 | 
			
		||||
              {{ op.left?.value ?? ' ' }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <!-- RIGHT -->
 | 
			
		||||
            <div class="w-[2.5em] border-b border-stone-600 transition-all">
 | 
			
		||||
              {{ op.operator ?? ' ' }}
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
          <div class="w-[2.5em] border-b border-stone-600 transition-all">
 | 
			
		||||
            {{ op.right?.value ?? ' ' }}
 | 
			
		||||
            <div class="w-[2.5em] border-b border-stone-600 transition-all">
 | 
			
		||||
              {{ op.right?.value ?? ' ' }}
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- EQUALS -->
 | 
			
		||||
            <div class="mx-4 border-none">
 | 
			
		||||
              =
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- RESULT -->
 | 
			
		||||
            <PlaquetteBox
 | 
			
		||||
              :dynamic-size="true"
 | 
			
		||||
              class="w-[3.2em] h-8 border-none">
 | 
			
		||||
              <IconSad v-if="isOperationInvalid(op)" />
 | 
			
		||||
              <span
 | 
			
		||||
                v-else-if="
 | 
			
		||||
                  op.operator &&
 | 
			
		||||
                    op.left &&
 | 
			
		||||
                    op.right &&
 | 
			
		||||
                    isOperationResultValid(op)
 | 
			
		||||
                ">
 | 
			
		||||
                {{ operate(op.operator, op.left.value, op.right.value) }}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span v-else>?</span>
 | 
			
		||||
            </PlaquetteBox>
 | 
			
		||||
 | 
			
		||||
            <!-- UNDO -->
 | 
			
		||||
            <button
 | 
			
		||||
              class="ml-8"
 | 
			
		||||
              @click="undoOperation(i)">
 | 
			
		||||
              <IconUndo
 | 
			
		||||
                class="text-stone-400"
 | 
			
		||||
                :class="{
 | 
			
		||||
                  invisible: !canOperationBeDeleted(op),
 | 
			
		||||
                }" />
 | 
			
		||||
            </button>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <!-- EQUALS -->
 | 
			
		||||
          <div class="mx-4 border-none">
 | 
			
		||||
            =
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <!-- RESULT -->
 | 
			
		||||
          <PlaquetteBox
 | 
			
		||||
            :dynamic-size="true"
 | 
			
		||||
            class="w-[3.2em] h-8 border-none">
 | 
			
		||||
            <IconSad v-if="isOperationInvalid(op)" />
 | 
			
		||||
            <span
 | 
			
		||||
              v-else-if="
 | 
			
		||||
                op.operator && op.left && op.right && isOperationResultValid(op)
 | 
			
		||||
              ">
 | 
			
		||||
              {{ operate(op.operator, op.left.value, op.right.value) }}
 | 
			
		||||
            </span>
 | 
			
		||||
            <span v-else>?</span>
 | 
			
		||||
          </PlaquetteBox>
 | 
			
		||||
 | 
			
		||||
          <!-- UNDO -->
 | 
			
		||||
          <button
 | 
			
		||||
            class="ml-8"
 | 
			
		||||
            @click="undoOperation(i)">
 | 
			
		||||
            <IconUndo
 | 
			
		||||
              class="text-stone-400"
 | 
			
		||||
              :class="{
 | 
			
		||||
                invisible: !canOperationBeDeleted(op),
 | 
			
		||||
              }" />
 | 
			
		||||
          </button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </TransitionGroup>
 | 
			
		||||
    </TransitionGroup>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,9 +8,8 @@ export const pool = [
 | 
			
		|||
export enum GameState {
 | 
			
		||||
  Undefined = 0,
 | 
			
		||||
  Waiting = 1,
 | 
			
		||||
  Playing = 2,
 | 
			
		||||
  Lost = 3,
 | 
			
		||||
  Won = 4,
 | 
			
		||||
  Loading = 2,
 | 
			
		||||
  Playing = 3,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const gameState = ref(GameState.Undefined)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,4 +65,14 @@
 | 
			
		|||
.slide_up-leave-to {
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
  transform: translateY(30px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.zero_height-enter-active,
 | 
			
		||||
.zero_height-leave-active {
 | 
			
		||||
  transition: all 0.5s ease;
 | 
			
		||||
}
 | 
			
		||||
.zero_height-enter-from,
 | 
			
		||||
.zero_height-leave-to {
 | 
			
		||||
  height: 0;
 | 
			
		||||
  opacity: 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +6,8 @@ import { Operation, Plaquette } from './types'
 | 
			
		|||
export const operations = reactive<Operation[]>([])
 | 
			
		||||
export const plaquettes = ref<Plaquette[]>([])
 | 
			
		||||
 | 
			
		||||
export const result = ref(0)
 | 
			
		||||
 | 
			
		||||
export const currentOperation = computed(
 | 
			
		||||
  () => operations[operations.length - 1],
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -13,3 +15,7 @@ export const currentOperation = computed(
 | 
			
		|||
export const isEndGame = computed(
 | 
			
		||||
  () => operations.length === 5 && isOperationReady(currentOperation.value),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
export const isResultPerfect = computed(
 | 
			
		||||
  () => currentOperation.value.result!.value === result.value,
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,13 +16,21 @@
 | 
			
		|||
    </NumberBox>
 | 
			
		||||
 | 
			
		||||
    <!-- Start button -->
 | 
			
		||||
    <Transition name="slide_up">
 | 
			
		||||
      <!-- TODO: fix animation -->
 | 
			
		||||
      <div class="text-center">
 | 
			
		||||
    <!-- TODO: fix animation -->
 | 
			
		||||
    <Transition name="zero_height">
 | 
			
		||||
      <div
 | 
			
		||||
        class="text-center"
 | 
			
		||||
        v-if="gameState === GameState.Waiting">
 | 
			
		||||
        <div>
 | 
			
		||||
          Combinez les nombres imposés afin de trouver le résultat ci-dessus, ou
 | 
			
		||||
          de vous en approcher le plus possible.<br>
 | 
			
		||||
          Le compteur démarre quand vous cliquez sur le bouton.<br>Partagez vos
 | 
			
		||||
          meilleurs temps !
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <button
 | 
			
		||||
          v-if="!gameIsRunning"
 | 
			
		||||
          @click="startGame"
 | 
			
		||||
          class="py-2 px-4 bg-stone-800 rounded border">
 | 
			
		||||
          class="py-2 px-4 mt-4 bg-stone-800 rounded border">
 | 
			
		||||
          {{ t('startGame') }}
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -71,9 +79,7 @@
 | 
			
		|||
      <div
 | 
			
		||||
        v-if="isEndGame"
 | 
			
		||||
        class="flex flex-row justify-evenly items-center mt-8">
 | 
			
		||||
        <span v-if="gameState === GameState.Won">{{
 | 
			
		||||
          t('endGame.victoryLabel')
 | 
			
		||||
        }}</span>
 | 
			
		||||
        <span v-if="isResultPerfect">{{ t('endGame.victoryLabel') }}</span>
 | 
			
		||||
        <span v-else>{{ t('endGame.failureLabel') }}</span>
 | 
			
		||||
        <button
 | 
			
		||||
          class="p-2 rounded border"
 | 
			
		||||
| 
						 | 
				
			
			@ -100,20 +106,26 @@ import NumberBox from '@/components/common/NumberBox.vue'
 | 
			
		|||
import PlaquetteBox from '@/components/common/PlaquetteBox.vue'
 | 
			
		||||
import OperationsList from '@/components/OperationsList.vue'
 | 
			
		||||
import { GameState, gameState, operators, pool } from '@/globals'
 | 
			
		||||
import { currentOperation, isEndGame, operations, plaquettes } from '@/store'
 | 
			
		||||
import {
 | 
			
		||||
  currentOperation,
 | 
			
		||||
  isEndGame,
 | 
			
		||||
  isResultPerfect,
 | 
			
		||||
  operations,
 | 
			
		||||
  plaquettes,
 | 
			
		||||
  result,
 | 
			
		||||
} from '@/store'
 | 
			
		||||
import { OperatorType, Plaquette } from '@/types'
 | 
			
		||||
import { randItem, randRange } from '@/utils'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // call `useI18n`, and spread `t` from  `useI18n` returning
 | 
			
		||||
 | 
			
		||||
const result = ref(0)
 | 
			
		||||
const initDelay = ref(100)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Computed
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
const gameIsRunning = computed(() => gameState.value > GameState.Waiting)
 | 
			
		||||
const gameIsRunning = computed(() => gameState.value > GameState.Loading)
 | 
			
		||||
const shownPlaquettes = computed(() =>
 | 
			
		||||
  gameIsRunning.value ? plaquettes.value : [],
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -130,11 +142,7 @@ watch(
 | 
			
		|||
        free: true,
 | 
			
		||||
        value: operate(op.operator!, op.left!.value, op.right!.value),
 | 
			
		||||
      }
 | 
			
		||||
      if (op.result.value === result.value) {
 | 
			
		||||
        // Winner
 | 
			
		||||
        gameState.value = GameState.Won
 | 
			
		||||
      }
 | 
			
		||||
      else if (operations.length < 5) {
 | 
			
		||||
      if (operations.length < 5) {
 | 
			
		||||
        plaquettes.value.push(op.result)
 | 
			
		||||
        operations.push(getEmptyOperation())
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +152,8 @@ watch(
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
function startGame(): void {
 | 
			
		||||
  gameState.value = GameState.Playing
 | 
			
		||||
  gameState.value = GameState.Loading
 | 
			
		||||
  setTimeout(() => (gameState.value = GameState.Playing), 500)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function selectNumber(p: Plaquette): void {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user