Ensure correct card overlap on mobile by using actual rendered dimensions
This commit is contained in:
parent
5c8357f47b
commit
542b131cd8
75
pyramid.js
75
pyramid.js
@ -141,51 +141,47 @@
|
||||
function renderBoard() {
|
||||
if (!isActive) return;
|
||||
|
||||
const boardRect = gameBoard.getBoundingClientRect();
|
||||
const layoutRect = pyramidLayout.getBoundingClientRect();
|
||||
|
||||
// If the board isn't visible yet or dimensions aren't ready, wait for the next frame
|
||||
if (boardRect.width === 0 || layoutRect.width === 0) {
|
||||
// If the board isn't visible yet or dimensions aren't ready, wait
|
||||
if (layoutRect.width === 0) {
|
||||
requestAnimationFrame(renderBoard);
|
||||
return;
|
||||
}
|
||||
|
||||
const rootStyle = getComputedStyle(document.documentElement);
|
||||
let cardWidth = parseFloat(rootStyle.getPropertyValue('--card-width'));
|
||||
let horizontalGap = parseFloat(rootStyle.getPropertyValue('--gap'));
|
||||
// Use the first available card to get the REAL pixel width/height calculated by CSS
|
||||
const firstCardId = Object.keys(cardElements)[0];
|
||||
if (!firstCardId) return;
|
||||
const sampleCard = cardElements[firstCardId];
|
||||
const cardRect = sampleCard.getBoundingClientRect();
|
||||
const cardWidth = cardRect.width;
|
||||
const cardHeight = cardRect.height;
|
||||
|
||||
if (isNaN(cardWidth) || cardWidth === 0) cardWidth = 80;
|
||||
if (isNaN(horizontalGap)) horizontalGap = 10;
|
||||
|
||||
const cardHeight = cardWidth * 1.4;
|
||||
const rowOverlap = 0.45;
|
||||
|
||||
const boardTop = boardRect.top;
|
||||
const boardLeft = boardRect.left;
|
||||
// Calculate gap based on 1.5vw or fallback (matching style.css)
|
||||
let horizontalGap = (window.innerWidth * 1.5) / 100;
|
||||
if (window.innerWidth > 600) horizontalGap = (window.innerWidth * 1.2) / 100; // Desktop gap
|
||||
|
||||
const verticalStep = cardHeight * 0.45; // Row overlap ratio
|
||||
|
||||
// Position Pyramid Cards
|
||||
let index = 0;
|
||||
for (let row = 0; row < 7; row++) {
|
||||
// Calculate total width of this row to center it
|
||||
const numCards = row + 1;
|
||||
const totalRowWidth = numCards * cardWidth + (numCards - 1) * horizontalGap;
|
||||
const startX = (layoutRect.width - totalRowWidth) / 2;
|
||||
const y = row * (cardHeight * rowOverlap);
|
||||
const y = row * verticalStep;
|
||||
|
||||
for (let i = 0; i <= row; i++) {
|
||||
const card = pyramid[index];
|
||||
if (card) {
|
||||
const el = cardElements[card.id];
|
||||
// Absolute position relative to the gameBoard
|
||||
const finalTop = y + (layoutRect.top - boardTop);
|
||||
const finalLeft = startX + i * (cardWidth + horizontalGap) + (layoutRect.left - boardLeft);
|
||||
|
||||
el.style.top = `${finalTop}px`;
|
||||
el.style.left = `${finalLeft}px`;
|
||||
// Position relative to the pyramid-layout container
|
||||
// Note: pyramid-layout has position: relative in pyramid.css
|
||||
el.style.top = `${y}px`;
|
||||
el.style.left = `${startX + i * (cardWidth + horizontalGap)}px`;
|
||||
el.style.zIndex = 100 + index;
|
||||
el.classList.add('is-flipped');
|
||||
|
||||
// Mark if it's currently playable for visual feedback
|
||||
const exposed = isExposed(card.id);
|
||||
el.classList.toggle('is-exposed', exposed);
|
||||
}
|
||||
@ -193,41 +189,38 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Position Stock
|
||||
// Position Stock, Waste, Discard (these are in a separate container at the bottom)
|
||||
// We'll use a slightly different approach for these to ensure they stay in their piles
|
||||
const sRect = stockEl.getBoundingClientRect();
|
||||
const wRect = wasteEl.getBoundingClientRect();
|
||||
const dRect = discardEl.getBoundingClientRect();
|
||||
const bRect = gameBoard.getBoundingClientRect();
|
||||
|
||||
stock.forEach((card, i) => {
|
||||
const el = cardElements[card.id];
|
||||
el.style.top = `${sRect.top - boardTop + PILE_BORDER_WIDTH}px`;
|
||||
el.style.left = `${sRect.left - boardLeft + PILE_BORDER_WIDTH}px`;
|
||||
el.style.top = `${sRect.top - bRect.top + PILE_BORDER_WIDTH}px`;
|
||||
el.style.left = `${sRect.left - bRect.left + PILE_BORDER_WIDTH}px`;
|
||||
el.style.zIndex = 10 + i;
|
||||
el.classList.remove('is-flipped');
|
||||
el.classList.remove('is-selected');
|
||||
el.classList.remove('is-exposed');
|
||||
el.classList.remove('is-flipped', 'is-selected', 'is-exposed');
|
||||
});
|
||||
|
||||
// Position Waste
|
||||
const wRect = wasteEl.getBoundingClientRect();
|
||||
waste.forEach((card, i) => {
|
||||
const el = cardElements[card.id];
|
||||
const isTop = (i === waste.length - 1);
|
||||
el.style.top = `${wRect.top - boardTop + PILE_BORDER_WIDTH}px`;
|
||||
el.style.left = `${wRect.left - boardLeft + PILE_BORDER_WIDTH}px`;
|
||||
// Base z-index for waste is 500, +i to stack correctly
|
||||
el.style.zIndex = 500 + i;
|
||||
el.style.top = `${wRect.top - bRect.top + PILE_BORDER_WIDTH}px`;
|
||||
el.style.left = `${wRect.left - bRect.left + PILE_BORDER_WIDTH}px`;
|
||||
el.style.zIndex = 500 + i;
|
||||
el.classList.add('is-flipped');
|
||||
el.classList.toggle('is-exposed', isTop);
|
||||
});
|
||||
|
||||
// Position Discard
|
||||
const dRect = discardEl.getBoundingClientRect();
|
||||
discard.forEach((card, i) => {
|
||||
const el = cardElements[card.id];
|
||||
el.style.top = `${dRect.top - boardTop + PILE_BORDER_WIDTH}px`;
|
||||
el.style.left = `${dRect.left - boardLeft + PILE_BORDER_WIDTH}px`;
|
||||
el.style.top = `${dRect.top - bRect.top + PILE_BORDER_WIDTH}px`;
|
||||
el.style.left = `${dRect.left - bRect.left + PILE_BORDER_WIDTH}px`;
|
||||
el.style.zIndex = 10 + i;
|
||||
el.classList.add('is-flipped');
|
||||
el.classList.remove('is-selected');
|
||||
el.classList.remove('is-exposed');
|
||||
el.classList.remove('is-selected', 'is-exposed');
|
||||
});
|
||||
|
||||
checkWin();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user