app area resizes, cards dynamically fan and lift on hover

This commit is contained in:
2025-10-31 18:57:34 -07:00
parent 413be0c055
commit f9c95993c4
3 changed files with 109 additions and 49 deletions

View File

@ -1,39 +1,75 @@
import { Assets, Container, Size, Sprite } from "pixi.js";
import { Assets, Container, Size, PointData, Sprite } from "pixi.js";
import { Card } from "./Card";
const CARD_WIDTH = 144;
const CARD_HEIGHT = 224;
import { CARD_HEIGHT, CARD_WIDTH } from "./constants";
const spritesheet = await Assets.load("/public/assets/cards.json");
export class Hand {
cards: Container;
#containerSize: Size;
#offset: number;
#roomRemaining: number;
#cards: Sprite[];
#container: Container;
#maxWidth: number;
#parent: Size & PointData;
constructor(maxWidth: number, cards: Card[] = []) {
if (maxWidth < CARD_WIDTH) {
throw new Error("hand cannot be narrower than a single card");
}
this.#roomRemaining = maxWidth;
this.#containerSize = { width: maxWidth, height: CARD_HEIGHT };
this.#offset = CARD_WIDTH;
this.#maxWidth = maxWidth;
this.#container = new Container();
this.#parent = { x: 0, y: 0, width: 0, height: 0 };
const sprites: Container = new Container();
sprites.position.set(0, 0);
let x = 0;
if (cards.length > 0) {
const sprites: Sprite[] = [];
for (const card of cards) {
this.add(card);
}
this.#cards = sprites;
this.#container.addChild(...sprites);
this.fanCards();
} else {
this.#cards = [];
}
}
add(card: Card) {
const sprite = new Sprite(spritesheet.textures[card]);
sprite.x = x;
x += this.#offset;
sprites.addChild(sprite);
sprite.eventMode = "dynamic";
sprite.onmouseenter = () => {
sprite.y -= 50;
};
sprite.onmouseleave = () => {
sprite.y += 50;
};
this.#cards.push(sprite);
this.#container.addChild(sprite);
this.fanCards();
this.repositionContainer();
}
this.cards = sprites;
parentArea(x: number, y: number, width: number, height: number) {
this.#parent = { x, y, width, height };
this.repositionContainer();
}
repositionContainer() {
this.#container.pivot.set(this.#container.width / 2, CARD_HEIGHT);
this.#container.position.set(this.#parent.width / 2, this.#parent.height);
}
fanCards() {
const count = this.#cards.length;
const max = this.#maxWidth;
const offset = count * CARD_WIDTH > max ? max / count : CARD_WIDTH;
let x = 0;
for (const card of this.#cards) {
card.x = x;
x += offset;
}
}
getContainer(): Container {
return this.#container;
}
}

2
client/src/constants.ts Normal file
View File

@ -0,0 +1,2 @@
export const CARD_WIDTH = 144;
export const CARD_HEIGHT = 224;

View File

@ -1,37 +1,59 @@
import { Application, Assets, Sprite } from "pixi.js";
import { Application } from "pixi.js";
import { Hand } from "./Hand";
import { Card } from "./Card";
const cards: Card[] = [
"threeOfClubs",
"twoOfDiamonds",
"aceOfClubs",
"eightOfDiamonds",
"nineOfSpades",
"sixOfClubs",
];
(async () => {
// Create a new application
try {
// Create and initialize a new application
const app = new Application();
// Initialize the application
await app.init({ background: "#1099bb", resizeTo: window });
await app.init({
background: "#338140",
width: window.innerWidth,
height: window.innerHeight,
});
// Append the application canvas to the document body
document.getElementById("pixi-container")!.appendChild(app.canvas);
try {
const hand = new Hand(1000, [
"fourOfDiamonds",
"eightOfDiamonds",
"threeOfClubs",
"kingOfSpades",
]);
const hand = new Hand(350, []);
app.stage.addChild(hand.cards);
hand.parentArea(0, 0, app.screen.width, app.screen.height);
hand.cards.position.set(app.screen.width / 2, 0);
hand.cards.pivot.set(hand.cards.width / 2, 0);
app.stage.addChild(hand.getContainer());
// Listen for animate update
// app.ticker.add((time) => {
// // Just for fun, let's rotate mr rabbit a little.
// // * Delta is 1 if running at 100% performance *
// // * Creates frame-independent transformation *
// bunny.rotation += 0.1 * time.deltaTime;
// });
// When the user resizes the window, resize the app. There is a plugin
// for doing this automatically, but it doesn't reposition stage's
// children. Since I need those repositioned, I am handling all the
// resizing myself. Does handling it myself create some kind of strange
// issues? I sure hope not!
//
// If strange issues are encountered, check out how coordinates work in
// PixiJS:
// https://pixijs.com/8.x/guides/concepts/scene-graph#local-vs-global-coordinates
window.addEventListener?.("resize", () => {
app.renderer.resize(window.innerWidth, window.innerHeight);
hand.parentArea(0, 0, app.screen.width, app.screen.height);
});
let ms = 0;
let elapsed = 0;
app.ticker.add((time) => {
elapsed += time.elapsedMS;
if (cards.length && elapsed >= ms) {
ms += 300;
hand.add(cards.pop()!);
}
});
} catch (err) {
console.log(err);
console.error(err);
}
})();