★前回の記事
プログラミングをしていきます。まずは使うピースの選択です。
状態の追加
選択中のピースをstate
に追加します。
初期値はpieceIdが1, 2, 9, 5, 10ですので、これを追加します。
js/state.js
const state = { // One of "selectPiece", "solving", "solvedSuccess", "solvedFailed", "pause" solverState: "selectPiece", // 追加 targetPieces: [1, 2, 9, 5, 10], }
state.targetPieces
の初期値は、初期化処理でhtml要素から取得した方がよいのですが、今回は簡易的にstateに直接書き込みました。
actionの登録
ピースがドロップされたときの動作を実装します。各エリアにドロップされたときに使うピースを更新します。
ドロップされたときの動作はdroppable
関数のdrop
プロパティに記載します。使わないピースのエリア#unused-piece-droppable
にドロップされたときは、ドロップされたピースを使うピースから削除するaction.removeFromTargetPieces
(まだ定義していません)を呼び出します。同様に使うピースのエリア(#used-piece-droppable
)にドロップされたときは、ドロップされたピースを使うピースに追加するaction.addToTargetPieces
(まだ定義していません)を呼び出します。
ピースのIDは、
<span id="piece_0" class="draggable-piece m-2 p-0" data-piece-id="0">
のように書いたhtmlタグの、data-piece-id="0"
の部分から取得します。取得した際は文字列型なので、数値型に変換します。
js/main.js
// 前略 const initializer = { setEvent: () => { $(".draggable-piece").draggable({ revert: "invalid" }) $("#unused-piece-droppable").droppable({ hoverClass: "bg-light", accept: ".draggable-piece", // 追加ここから drop : ((e, ui) => { const pieceId = ui.draggable.data("piece-id") action.removeFromTargetPieces(parseInt(pieceId, 10)) }), // 追加ここまで }) $("#used-piece-droppable").droppable({ hoverClass: "hover", accept: ".draggable-piece", // 追加ここから drop : ((e, ui) => { const pieceId = ui.draggable.data("piece-id") action.addToTargetPieces(parseInt(pieceId, 10)) }), // 追加ここまで }) }, }
actionの実装
ドロップされたピースを使うピースから削除するaction.removeFromTargetPieces
とドロップされたピースを使うピースに追加するaction.addToTargetPieces
を実装します。
先にaction.removeFromTargetPieces
を実装します。受け取ったpieceId
が、使うピース(state.targetPieces
)に含まれているか判定します。ピースが含まれていれば、そのピースの番号を使うピースのリストから削除します。新しいリストをstateManagerに渡します。
受け取ったpieceIdが、使うピースに含まれているかはindexOfの値が0以上かどうかで判定します。選択したピースのリストからの削除にはfilterを使用しています。
stateManager.setTargetPieces
はまだ実装していません。
ja/action.js
// 追加ここから const action = { removeFromTargetPieces: (pieceId) => { if (state.targetPieces.indexOf(pieceId) >= 0) { const newPieces = state.targetPieces.filter(id => id !== pieceId) stateManager.setTargetPieces(newPieces) } }, } // 追加ここまで
次に、action.addToTargetPieces
を実装します。受け取ったpieceId
が、使うピース(state.targetPieces
)に含まれているか判定し、含まれいなければ、pieceId
を追加した配列をstateManager.setTargetPieces
に渡します。(この関数はまだ定義していません)
js/action.js
const action = { // 中略 // 追加ここから addToTargetPieces: (pieceId) => { if (state.targetPieces.indexOf(pieceId) < 0) { stateManager.setTargetPieces([...state.targetPieces, pieceId]) } }, // 追加ここまで }
stateManagerの実装
stateManager.setTargetPieces
を実装します。state
を書き換えます。(stateManager
のみがstate
を書き換えることができます。)
書き換えたあとは画面を更新するのですが、一旦ここでコンソールに表示してここまでの動作を確認しましょう。
js/stateManager.js
// 追加ここから const stateManager = { setTargetPieces: (targetPieces) => { state.targetPieces = targetPieces // TODO displayの呼び出し console.log("state.targetPieces", state.targetPieces) }, } // 追加ここまで
ここまでの実行結果
実行結果です。"使うピース"の中にあるピースがstate.targetPieces
と同期しているのが分かります。
使わないピースを使うピースのエリアにドロップする↓ 6番のピースをドロップすると、targetPieces
の末尾に番号が追加されました。
使うピースを使わないピースにのエリアにドロップする↓ 5番ののピースをドロップすると、targetPieces
から番号が削除されました。
ボタンの表示の切り替え
ボタンの表示を切り替えます。選択されたピースの個数が3未満の場合には"つかうピースをもっとおいてください"のボタンを表示します。3以上の場合はスタートボタンを表示します。ボタンの表示の切り替えはtoggle関数で行います。
js/display.js
const display = { // show プロパティは削除 // 追加ここから updateStartButtons: ({targetPieces}) => { $("#start-button").toggle( targetPieces.length >= 3 ) $("#more-piece-button").toggle( targetPieces.length < 3 ) }, // 追加ここまで }
使うピースが更新されたときに、ボタンの更新を呼び出すようにstateManager
を更新します。
js/stateManager.js
const stateManager = { setTargetPieces: (targetPieces) => { state.targetPieces = targetPieces // console.log("state.targetPieces", state.targetPieces) は削除してもよい // 追加 display.updateStartButtons(state) }, }
実行結果
実行結果です。
使うピースが3個以上の場合↓
使うピースが3個未満の場合↓
以上で使うピースの選択を実装ができました。
★次回の記事
★目次