feat(client_web): display checkers stacks
This commit is contained in:
parent
01fa837b84
commit
d3a20eb6b6
2 changed files with 104 additions and 74 deletions
|
|
@ -262,7 +262,7 @@ input[type="text"] {
|
||||||
/* ── Fields ─────────────────────────────────────────────────────────── */
|
/* ── Fields ─────────────────────────────────────────────────────────── */
|
||||||
.field {
|
.field {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 110px;
|
height: 180px;
|
||||||
background: #d4a843;
|
background: #d4a843;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -295,25 +295,34 @@ input[type="text"] {
|
||||||
.top-row .field-num { bottom: auto; top: 2px; }
|
.top-row .field-num { bottom: auto; top: 2px; }
|
||||||
|
|
||||||
/* ── Checkers ───────────────────────────────────────────────────────── */
|
/* ── Checkers ───────────────────────────────────────────────────────── */
|
||||||
.checkers {
|
.checker-stack {
|
||||||
width: 46px;
|
display: flex;
|
||||||
height: 46px;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checker {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 1rem;
|
font-size: 0.8rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border: 2px solid rgba(0,0,0,0.3);
|
border: 2px solid rgba(0,0,0,0.3);
|
||||||
box-shadow: inset 0 2px 4px rgba(255,255,255,0.3), 0 2px 4px rgba(0,0,0,0.3);
|
box-shadow: inset 0 2px 4px rgba(255,255,255,0.3), 0 1px 3px rgba(0,0,0,0.3);
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkers.white {
|
.checker + .checker { margin-top: 2px; }
|
||||||
|
|
||||||
|
.checker.white {
|
||||||
background: radial-gradient(circle at 35% 35%, #ffffff, #cccccc);
|
background: radial-gradient(circle at 35% 35%, #ffffff, #cccccc);
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkers.black {
|
.checker.black {
|
||||||
background: radial-gradient(circle at 35% 35%, #555555, #111111);
|
background: radial-gradient(circle at 35% 35%, #555555, #111111);
|
||||||
color: #eee;
|
color: #eee;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,12 @@ fn displayed_value(
|
||||||
let mut val = base_board[(field_num - 1) as usize];
|
let mut val = base_board[(field_num - 1) as usize];
|
||||||
let delta: i8 = if is_white { 1 } else { -1 };
|
let delta: i8 = if is_white { 1 } else { -1 };
|
||||||
for &(from, to) in staged_moves {
|
for &(from, to) in staged_moves {
|
||||||
if from == field_num { val -= delta; }
|
if from == field_num {
|
||||||
if to == field_num { val += delta; }
|
val -= delta;
|
||||||
|
}
|
||||||
|
if to == field_num {
|
||||||
|
val += delta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
@ -42,11 +46,15 @@ pub fn Board(
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let board = view_state.board;
|
let board = view_state.board;
|
||||||
let is_move_stage = view_state.active_mp_player == Some(player_id)
|
let is_move_stage = view_state.active_mp_player == Some(player_id)
|
||||||
&& matches!(view_state.turn_stage, SerTurnStage::Move | SerTurnStage::HoldOrGoChoice);
|
&& matches!(
|
||||||
|
view_state.turn_stage,
|
||||||
|
SerTurnStage::Move | SerTurnStage::HoldOrGoChoice
|
||||||
|
);
|
||||||
let is_white = player_id == 0;
|
let is_white = player_id == 0;
|
||||||
|
|
||||||
let fields_from = |nums: &[u8]| -> Vec<AnyView> {
|
let fields_from = |nums: &[u8], is_top_row: bool| -> Vec<AnyView> {
|
||||||
nums.iter().map(|&field_num| {
|
nums.iter()
|
||||||
|
.map(|&field_num| {
|
||||||
view! {
|
view! {
|
||||||
<div
|
<div
|
||||||
class=move || {
|
class=move || {
|
||||||
|
|
@ -94,7 +102,20 @@ pub fn Board(
|
||||||
let count = val.unsigned_abs();
|
let count = val.unsigned_abs();
|
||||||
(count > 0).then(|| {
|
(count > 0).then(|| {
|
||||||
let color = if val > 0 { "white" } else { "black" };
|
let color = if val > 0 { "white" } else { "black" };
|
||||||
view! { <span class=format!("checkers {color}")>{count}</span> }
|
let display_n = (count as usize).min(4);
|
||||||
|
// outermost index: last for top rows, first for bottom rows.
|
||||||
|
let outer_idx = if is_top_row { display_n - 1 } else { 0 };
|
||||||
|
let chips: Vec<AnyView> = (0..display_n).map(|i| {
|
||||||
|
let label = if i == outer_idx && count >= 5 {
|
||||||
|
count.to_string()
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
view! {
|
||||||
|
<div class=format!("checker {color}")>{label}</div>
|
||||||
|
}.into_any()
|
||||||
|
}).collect();
|
||||||
|
view! { <div class="checker-stack">{chips}</div> }
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -113,15 +134,15 @@ pub fn Board(
|
||||||
view! {
|
view! {
|
||||||
<div class="board">
|
<div class="board">
|
||||||
<div class="board-row top-row">
|
<div class="board-row top-row">
|
||||||
<div class="board-quarter">{fields_from(tl)}</div>
|
<div class="board-quarter">{fields_from(tl, true)}</div>
|
||||||
<div class="board-bar"></div>
|
<div class="board-bar"></div>
|
||||||
<div class="board-quarter">{fields_from(tr)}</div>
|
<div class="board-quarter">{fields_from(tr, true)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="board-center-bar"></div>
|
<div class="board-center-bar"></div>
|
||||||
<div class="board-row bot-row">
|
<div class="board-row bot-row">
|
||||||
<div class="board-quarter">{fields_from(bl)}</div>
|
<div class="board-quarter">{fields_from(bl, false)}</div>
|
||||||
<div class="board-bar"></div>
|
<div class="board-bar"></div>
|
||||||
<div class="board-quarter">{fields_from(br)}</div>
|
<div class="board-quarter">{fields_from(br, false)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue