iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0

玩紙牌接龍最重要的就是卡牌會移來移去,之前都是用點的移動定點,
今天來試試看如何撰寫拖曳紙牌的功能。

安裝依賴

因為重頭學習理解拖曳,對我來說太麻煩也太無聊,
乾脆就使用現成的套件Vue.Draggable吧!

因為使用的是Vue3專案,所以必須安裝有標註next的版本。

npm i -S vuedraggable@next

單一列表的拖曳使用

我也還在理解該套件中,接下來的過程會盡可能去蕪存菁,但不失細節。
首先一定要先引入vuedraggable,如下所示:

<script setup>
import draggable from 'vuedraggable'
// ...other template
</script>

樣板的部分則如下:

<template>
    <draggable :list="firstCardStack" itemKey="value"
        @change="console.log"
        style="display: grid; grid-template-columns: repeat(13, 3rem);">
        <template #item="{ element, index }">
            <Card :value="element.value" :isOpen="element.isOpen" />
        </template>
    </draggable>
</template>

這樣的寫法在通常就已可運用,接下來讓我們來逐一理解<draggable>每個欄位的意義和預設行為...

:list

首先:list內設定的是一個參考到陣列的refreactive變數,只要裡面參考到的是Array即可,
這可以讓<draggable>明白當列表項目被拖曳移動時自動修改的對象。

// 此處genearateDeck(20, true)會回傳20個物件的Array物件
const firstCardStack = ref(geneateDeck(20, true));
// 為求簡單也能寫成底下這樣
// const firstCardStack = ref([]);

itemKey屬性

第二個重要的屬性是itemKey,代表前面陣列中每一個元素的唯一值,基本上就跟v-for內用到的:key有相同作用,可讓元件從itemKey明白內部元素的差異進而去做列表更新。

此處會設定itemKey="value",是因為參考的陣列firstCardStack每一個元素的構造如下:

{ 
    value: number,  // 撲克牌值,Ex: 0 對應 ♣A
    isOpen: boolean // 開牌狀態,Ex: false 對應 蓋牌樣式
}

嘗試過不添加itemKey仍可拖曳且參考的陣列有更新,但會發生UI不會刷新的窘境🤣

@change屬性

目前先使用console.log,可印出包含欄位moved的物件,moved內的構造如下:

{
    newIndex: 13 // 拖曳後項目的新索引
    oldIndex: 0 // 拖曳項目的原索引
}

<draggable>內部

傳進draggable內部的slot區塊,這部分我在重寫一次如下:

<template #item="{ element, index }">
    <Card :value="element.value" :isOpen="element.isOpen" />
</template>

可以方便理解成只是從下方v-for寫法換成上方的兩層式寫法:

<Card v-for="(element, index) in firstCardStack" :value="element.value" :isOpen="element.isOpen" />

外層的<template>的屬性#item只是省略了要迭代哪個陣列的v-for寫法而已,至於為什麼要這樣設計就要問原作者了哈哈ˊWˋ

小結

目前的卡牌列表是可以任意切換順序,但真實的接龍是不能這樣隨意拖曳,
明日再來研究如何限制列表的拖曳、兩個列表的拖曳。

程式碼: https://github.com/kabuto412rock/ithelp-pokergame/tree/day09
Yes
參考資料


上一篇
Day 08 牌堆的卡牌移動動畫
下一篇
Day 10 拖曳紙牌的效果(二)限制內部拖曳
系列文
毫無自信的開發Web遊戲接龍-成為創造龍的英雄之路!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言