mirror of
https://github.com/AndrioCelos/TableturfBattleApp.git
synced 2026-03-21 17:34:28 -05:00
209 lines
8.2 KiB
TypeScript
209 lines
8.2 KiB
TypeScript
class CardDisplay implements ICardElement {
|
|
readonly card: Card;
|
|
level: number;
|
|
readonly element: HTMLElement;
|
|
readonly svg: SVGSVGElement;
|
|
private readonly sizeElement: SVGTextElement;
|
|
private readonly specialCostGroup: SVGGElement;
|
|
private idNumber: number;
|
|
|
|
private static nextIdNumber = 0;
|
|
|
|
private static getGradientId(baseId: string, scale: number) {
|
|
if (scale >= 20) return baseId;
|
|
|
|
const roundedScale = Math.round(scale * 20);
|
|
if (roundedScale >= 20) return baseId;
|
|
|
|
const id = `${baseId}${roundedScale}`;
|
|
if (document.getElementById(id)) return id;
|
|
|
|
const baseElement = document.getElementById(baseId);
|
|
if (!baseElement)
|
|
throw new Error(`Base gradient element '${baseId}' not found.`);
|
|
const el = <Element> baseElement!.cloneNode(true);
|
|
baseElement.insertAdjacentElement('afterend', el);
|
|
el.setAttribute('id', id);
|
|
el.setAttribute('gradientTransform', `translate(${-6350 / roundedScale + 317.5} 0) scale(${20 / roundedScale} 1)`);
|
|
return id;
|
|
}
|
|
|
|
constructor(card: Card, level: number, elementType: string = 'div') {
|
|
this.idNumber = CardDisplay.nextIdNumber++;
|
|
this.card = card;
|
|
this.level = level;
|
|
|
|
const element = document.createElement(elementType);
|
|
element.classList.add('card');
|
|
element.classList.add([ 'common', 'rare', 'fresh' ][card.rarity]);
|
|
this.element = element;
|
|
|
|
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
svg.setAttribute('viewBox', '0 0 442 616');
|
|
svg.setAttribute('alt', card.name);
|
|
this.svg = svg;
|
|
element.appendChild(svg);
|
|
|
|
if (card.isCustom) svg.classList.add('custom');
|
|
else if (card.isUpcoming) svg.classList.add('upcoming');
|
|
svg.dataset.cardNumber = card.number.toString();
|
|
svg.style.setProperty("--number", card.number.toString());
|
|
|
|
// Background
|
|
const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
|
|
image.setAttribute('class', 'cardDisplayBackground');
|
|
image.setAttribute('href', `assets/external/CardBackground${card.isCustom ? '-custom' : ''}-${card.rarity}-${level > 0 ? '1' : '0'}.webp`);
|
|
image.setAttribute('width', '100%');
|
|
image.setAttribute('height', '100%');
|
|
svg.appendChild(image);
|
|
|
|
if (level > 0) {
|
|
const r1 = card.inkColour1.r / 255;
|
|
const g1 = card.inkColour1.g / 255;
|
|
const b1 = card.inkColour1.b / 255;
|
|
const dr = (card.inkColour2.r - card.inkColour1.r) / 255;
|
|
const dg = (card.inkColour2.g - card.inkColour1.g) / 255;
|
|
const db = (card.inkColour2.b - card.inkColour1.b) / 255;
|
|
svg.insertAdjacentHTML('beforeend', `
|
|
<filter id="ink-${this.idNumber}" class="inkFilter" color-interpolation-filters="sRGB"><feColorMatrix type="matrix" values="${dr} 0 0 0 ${r1} 0 ${dg} 0 0 ${g1} 0 0 ${db} 0 ${b1} 0 0 0 0.88 0"/></filter>
|
|
<image href="assets/external/CardInk_00.webp" width="100%" height="100%" clip-path="url(#cardBorder)" filter="url(#ink-${this.idNumber})"/>
|
|
<image href="assets/external/CardFrame_01.webp" width="100%" height="100%" clip-path="url(#cardBorder)"/>
|
|
`);
|
|
}
|
|
|
|
// Art
|
|
if (card.imageUrl) {
|
|
const image2 = document.createElementNS('http://www.w3.org/2000/svg', 'image');
|
|
image2.setAttribute('class', 'cardArt');
|
|
image2.setAttribute('href', card.imageUrl);
|
|
image2.setAttribute('width', '100%');
|
|
image2.setAttribute('height', '100%');
|
|
svg.appendChild(image2);
|
|
}
|
|
|
|
// Grid
|
|
const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
|
g.setAttribute('class', 'cardGrid');
|
|
g.setAttribute('transform', 'translate(264 420) rotate(6.5) scale(0.197)');
|
|
svg.appendChild(g);
|
|
|
|
CardDisplay.CreateSvgCardGrid(card, g);
|
|
|
|
// Name
|
|
const text1 = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
|
text1.setAttribute('class', 'cardDisplayName');
|
|
text1.setAttribute('x', '50%');
|
|
text1.setAttribute('y', '19%');
|
|
text1.setAttribute('text-anchor', 'middle');
|
|
text1.setAttribute('font-size', '53');
|
|
text1.setAttribute('font-weight', 'bold');
|
|
text1.setAttribute('stroke', 'black');
|
|
text1.setAttribute('stroke-width', '10.5');
|
|
text1.setAttribute('stroke-linejoin', 'round');
|
|
text1.setAttribute('paint-order', 'stroke');
|
|
text1.setAttribute('word-spacing', '-10');
|
|
text1.setAttribute('transform-origin', 'center');
|
|
text1.setAttribute('transform', `scale(${card.textScale} 1)`);
|
|
switch (card.rarity) {
|
|
case Rarity.Common:
|
|
text1.setAttribute('fill', '#6038FF');
|
|
break;
|
|
case Rarity.Rare:
|
|
text1.setAttribute('fill', `url("#${CardDisplay.getGradientId('rareGradient', card.textScale)}")`);
|
|
break;
|
|
case Rarity.Fresh:
|
|
text1.setAttribute('fill', `url("#${CardDisplay.getGradientId('freshGradient', card.textScale)}")`);
|
|
break;
|
|
}
|
|
if (card.line1 != null && card.line2 != null) {
|
|
const tspan1 = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
|
tspan1.setAttribute('y', '13.8%');
|
|
tspan1.appendChild(document.createTextNode(card.line1));
|
|
text1.appendChild(tspan1);
|
|
|
|
if (!card.line1.endsWith('-') && !card.line2.startsWith('-')) {
|
|
// Add a space in the middle, to be included when copying the card name.
|
|
const tspanBr = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
|
tspanBr.setAttribute('x', '50%');
|
|
tspanBr.setAttribute('y', '19%');
|
|
tspanBr.appendChild(document.createTextNode(' '));
|
|
text1.appendChild(tspanBr);
|
|
}
|
|
|
|
const tspan2 = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
|
tspan2.setAttribute('x', '50%');
|
|
tspan2.setAttribute('y', '24.4%');
|
|
tspan2.appendChild(document.createTextNode(card.line2));
|
|
text1.appendChild(tspan2);
|
|
} else
|
|
text1.innerHTML = card.name;
|
|
|
|
svg.appendChild(text1);
|
|
|
|
// Size
|
|
svg.insertAdjacentHTML('beforeend', `<image class='cardSizeBackground' href='assets/external/CardCost_0${card.rarity}.webp' width='74.1' height='74.1' transform='translate(8.4 555) rotate(-45)'/>`);
|
|
svg.insertAdjacentHTML('beforeend', `<text fill='white' stroke='${card.rarity == Rarity.Common ? '#482BB4' : card.rarity == Rarity.Rare ? '#8B7E25' : '#481EF9'}' paint-order='stroke' stroke-width='5' font-size='33.4' x='13.7%' y='92.2%' text-anchor='middle'>${card.size}</text>`);
|
|
this.sizeElement = svg.lastElementChild as SVGTextElement;
|
|
|
|
// Special cost
|
|
const g2 = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
|
this.specialCostGroup = g2;
|
|
g2.setAttribute('class', 'specialCost');
|
|
g2.setAttribute('transform', 'translate(118 561) scale(0.222)');
|
|
svg.appendChild(g2);
|
|
|
|
this.setSpecialCost(card.specialCost);
|
|
}
|
|
|
|
static CreateSvgCardGrid(card: Card, parent: SVGElement) {
|
|
for (var y = 0; y < 8; y++) {
|
|
for (var x = 0; x < 8; x++) {
|
|
if (card.grid[x][y] == Space.Empty) {
|
|
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
|
rect.classList.add('empty');
|
|
rect.setAttribute('x', (100 * x + 3).toString());
|
|
rect.setAttribute('y', (100 * y + 3).toString());
|
|
rect.setAttribute('width', '94');
|
|
rect.setAttribute('height', '94');
|
|
parent.appendChild(rect);
|
|
} else {
|
|
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
|
rect.classList.add(card.grid[x][y] == Space.SpecialInactive1 ? 'special' : 'ink');
|
|
const elements: Element[] = [rect];
|
|
const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
|
|
image.setAttribute('href', card.grid[x][y] == Space.SpecialInactive1 ? 'assets/SpecialOverlay.webp' : 'assets/InkOverlay.webp');
|
|
elements.push(image);
|
|
|
|
for (const el of elements) {
|
|
el.setAttribute('x', (100 * x).toString());
|
|
el.setAttribute('y', (100 * y).toString());
|
|
el.setAttribute('width', '100');
|
|
el.setAttribute('height', '100');
|
|
parent.appendChild(el);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
setSpecialCost(value: number) {
|
|
clearChildren(this.specialCostGroup);
|
|
for (let i = 0; i < value; i++) {
|
|
let rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
|
const image = document.createElementNS('http://www.w3.org/2000/svg', 'image');
|
|
image.setAttribute('href', 'assets/SpecialOverlay.webp');
|
|
for (const el of [ rect, image ]) {
|
|
el.setAttribute('x', (110 * (i % 5)).toString());
|
|
el.setAttribute('y', (-125 * Math.floor(i / 5)).toString());
|
|
el.setAttribute('width', '95');
|
|
el.setAttribute('height', '95');
|
|
this.specialCostGroup.appendChild(el);
|
|
}
|
|
}
|
|
}
|
|
|
|
setSize(value: number) {
|
|
this.sizeElement.innerHTML = value.toString();
|
|
}
|
|
}
|