app area resizes, cards dynamically fan and lift on hover
This commit is contained in:
@ -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";
|
import { Card } from "./Card";
|
||||||
|
import { CARD_HEIGHT, CARD_WIDTH } from "./constants";
|
||||||
const CARD_WIDTH = 144;
|
|
||||||
const CARD_HEIGHT = 224;
|
|
||||||
|
|
||||||
const spritesheet = await Assets.load("/public/assets/cards.json");
|
const spritesheet = await Assets.load("/public/assets/cards.json");
|
||||||
|
|
||||||
export class Hand {
|
export class Hand {
|
||||||
cards: Container;
|
#cards: Sprite[];
|
||||||
#containerSize: Size;
|
#container: Container;
|
||||||
#offset: number;
|
#maxWidth: number;
|
||||||
#roomRemaining: number;
|
#parent: Size & PointData;
|
||||||
|
|
||||||
constructor(maxWidth: number, cards: Card[] = []) {
|
constructor(maxWidth: number, cards: Card[] = []) {
|
||||||
if (maxWidth < CARD_WIDTH) {
|
if (maxWidth < CARD_WIDTH) {
|
||||||
throw new Error("hand cannot be narrower than a single card");
|
throw new Error("hand cannot be narrower than a single card");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#roomRemaining = maxWidth;
|
this.#maxWidth = maxWidth;
|
||||||
this.#containerSize = { width: maxWidth, height: CARD_HEIGHT };
|
this.#container = new Container();
|
||||||
this.#offset = CARD_WIDTH;
|
this.#parent = { x: 0, y: 0, width: 0, height: 0 };
|
||||||
|
|
||||||
const sprites: Container = new Container();
|
if (cards.length > 0) {
|
||||||
sprites.position.set(0, 0);
|
const sprites: Sprite[] = [];
|
||||||
|
for (const card of cards) {
|
||||||
|
this.add(card);
|
||||||
|
}
|
||||||
|
|
||||||
let x = 0;
|
this.#cards = sprites;
|
||||||
for (const card of cards) {
|
this.#container.addChild(...sprites);
|
||||||
const sprite = new Sprite(spritesheet.textures[card]);
|
this.fanCards();
|
||||||
|
} else {
|
||||||
sprite.x = x;
|
this.#cards = [];
|
||||||
x += this.#offset;
|
|
||||||
|
|
||||||
sprites.addChild(sprite);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.cards = sprites;
|
add(card: Card) {
|
||||||
|
const sprite = new Sprite(spritesheet.textures[card]);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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
2
client/src/constants.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const CARD_WIDTH = 144;
|
||||||
|
export const CARD_HEIGHT = 224;
|
||||||
@ -1,37 +1,59 @@
|
|||||||
import { Application, Assets, Sprite } from "pixi.js";
|
import { Application } from "pixi.js";
|
||||||
import { Hand } from "./Hand";
|
import { Hand } from "./Hand";
|
||||||
|
import { Card } from "./Card";
|
||||||
|
|
||||||
|
const cards: Card[] = [
|
||||||
|
"threeOfClubs",
|
||||||
|
"twoOfDiamonds",
|
||||||
|
"aceOfClubs",
|
||||||
|
"eightOfDiamonds",
|
||||||
|
"nineOfSpades",
|
||||||
|
"sixOfClubs",
|
||||||
|
];
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
// Create a new application
|
|
||||||
const app = new Application();
|
|
||||||
|
|
||||||
// Initialize the application
|
|
||||||
await app.init({ background: "#1099bb", resizeTo: window });
|
|
||||||
|
|
||||||
// Append the application canvas to the document body
|
|
||||||
document.getElementById("pixi-container")!.appendChild(app.canvas);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hand = new Hand(1000, [
|
// Create and initialize a new application
|
||||||
"fourOfDiamonds",
|
const app = new Application();
|
||||||
"eightOfDiamonds",
|
await app.init({
|
||||||
"threeOfClubs",
|
background: "#338140",
|
||||||
"kingOfSpades",
|
width: window.innerWidth,
|
||||||
]);
|
height: window.innerHeight,
|
||||||
|
});
|
||||||
|
|
||||||
app.stage.addChild(hand.cards);
|
// Append the application canvas to the document body
|
||||||
|
document.getElementById("pixi-container")!.appendChild(app.canvas);
|
||||||
|
|
||||||
hand.cards.position.set(app.screen.width / 2, 0);
|
const hand = new Hand(350, []);
|
||||||
hand.cards.pivot.set(hand.cards.width / 2, 0);
|
|
||||||
|
|
||||||
// Listen for animate update
|
hand.parentArea(0, 0, app.screen.width, app.screen.height);
|
||||||
// app.ticker.add((time) => {
|
|
||||||
// // Just for fun, let's rotate mr rabbit a little.
|
app.stage.addChild(hand.getContainer());
|
||||||
// // * Delta is 1 if running at 100% performance *
|
|
||||||
// // * Creates frame-independent transformation *
|
// When the user resizes the window, resize the app. There is a plugin
|
||||||
// bunny.rotation += 0.1 * time.deltaTime;
|
// 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) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user