add stats
Browse files
src/lib/services/picletExport.ts
CHANGED
@@ -10,9 +10,26 @@ export async function generateShareableImage(piclet: PicletInstance): Promise<Bl
|
|
10 |
const ctx = canvas.getContext('2d');
|
11 |
if (!ctx) throw new Error('Could not create canvas context');
|
12 |
|
13 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
const canvasWidth = 1024;
|
15 |
-
const canvasHeight =
|
16 |
canvas.width = canvasWidth;
|
17 |
canvas.height = canvasHeight;
|
18 |
|
@@ -83,6 +100,77 @@ export async function generateShareableImage(piclet: PicletInstance): Promise<Bl
|
|
83 |
ctx.shadowOffsetX = 0;
|
84 |
ctx.shadowOffsetY = 0;
|
85 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
// Load and draw translucent watermark
|
87 |
const logoImg = await loadImage('/assets/snap_logo.png');
|
88 |
const logoSize = 150;
|
|
|
10 |
const ctx = canvas.getContext('2d');
|
11 |
if (!ctx) throw new Error('Could not create canvas context');
|
12 |
|
13 |
+
// Polyfill for roundRect if not available
|
14 |
+
if (!ctx.roundRect) {
|
15 |
+
ctx.roundRect = function(x: number, y: number, width: number, height: number, radius: number) {
|
16 |
+
ctx.beginPath();
|
17 |
+
ctx.moveTo(x + radius, y);
|
18 |
+
ctx.lineTo(x + width - radius, y);
|
19 |
+
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
|
20 |
+
ctx.lineTo(x + width, y + height - radius);
|
21 |
+
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
|
22 |
+
ctx.lineTo(x + radius, y + height);
|
23 |
+
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
|
24 |
+
ctx.lineTo(x, y + radius);
|
25 |
+
ctx.quadraticCurveTo(x, y, x + radius, y);
|
26 |
+
ctx.closePath();
|
27 |
+
};
|
28 |
+
}
|
29 |
+
|
30 |
+
// Set canvas size - full piclet size plus padding for name and stats
|
31 |
const canvasWidth = 1024;
|
32 |
+
const canvasHeight = 1400; // Extra height for name and stats
|
33 |
canvas.width = canvasWidth;
|
34 |
canvas.height = canvasHeight;
|
35 |
|
|
|
100 |
ctx.shadowOffsetX = 0;
|
101 |
ctx.shadowOffsetY = 0;
|
102 |
|
103 |
+
// Draw base stats in a sleek format
|
104 |
+
const statsY = picletY + picletSize + 50; // Position below piclet
|
105 |
+
const stats = [
|
106 |
+
{ label: 'HP', value: piclet.baseHp, color: '#4caf50' },
|
107 |
+
{ label: 'ATK', value: piclet.baseAttack, color: '#f44336' },
|
108 |
+
{ label: 'DEF', value: piclet.baseDefense, color: '#2196f3' },
|
109 |
+
{ label: 'S.ATK', value: piclet.baseFieldAttack, color: '#ff9800' },
|
110 |
+
{ label: 'S.DEF', value: piclet.baseFieldDefense, color: '#9c27b0' },
|
111 |
+
{ label: 'SPD', value: piclet.baseSpeed, color: '#00bcd4' }
|
112 |
+
];
|
113 |
+
|
114 |
+
// Stats container background
|
115 |
+
const containerX = 100;
|
116 |
+
const containerY = statsY - 20;
|
117 |
+
const containerWidth = canvasWidth - 200;
|
118 |
+
const containerHeight = 150;
|
119 |
+
|
120 |
+
// Draw semi-transparent background
|
121 |
+
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)';
|
122 |
+
ctx.roundRect(containerX, containerY, containerWidth, containerHeight, 20);
|
123 |
+
ctx.fill();
|
124 |
+
|
125 |
+
// Draw stats bars
|
126 |
+
const barHeight = 16;
|
127 |
+
const barSpacing = 20;
|
128 |
+
const maxStatValue = 255;
|
129 |
+
const barMaxWidth = containerWidth - 240; // Leave room for labels and values
|
130 |
+
|
131 |
+
stats.forEach((stat, index) => {
|
132 |
+
const y = statsY + (index * barSpacing);
|
133 |
+
|
134 |
+
// Draw stat label
|
135 |
+
ctx.font = 'bold 14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif';
|
136 |
+
ctx.fillStyle = '#ffffff';
|
137 |
+
ctx.textAlign = 'left';
|
138 |
+
ctx.fillText(stat.label, containerX + 20, y + 3);
|
139 |
+
|
140 |
+
// Draw stat value
|
141 |
+
ctx.textAlign = 'right';
|
142 |
+
ctx.fillText(stat.value.toString(), containerX + 100, y + 3);
|
143 |
+
|
144 |
+
// Draw background bar
|
145 |
+
const barX = containerX + 120;
|
146 |
+
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
|
147 |
+
ctx.roundRect(barX, y - 8, barMaxWidth, barHeight, 8);
|
148 |
+
ctx.fill();
|
149 |
+
|
150 |
+
// Draw filled bar
|
151 |
+
const fillWidth = (stat.value / maxStatValue) * barMaxWidth;
|
152 |
+
ctx.fillStyle = stat.color;
|
153 |
+
ctx.roundRect(barX, y - 8, fillWidth, barHeight, 8);
|
154 |
+
ctx.fill();
|
155 |
+
|
156 |
+
// Add shine effect
|
157 |
+
const shineGradient = ctx.createLinearGradient(barX, y - 8, barX, y - 8 + barHeight);
|
158 |
+
shineGradient.addColorStop(0, 'rgba(255, 255, 255, 0.3)');
|
159 |
+
shineGradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.1)');
|
160 |
+
shineGradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
|
161 |
+
ctx.fillStyle = shineGradient;
|
162 |
+
ctx.roundRect(barX, y - 8, fillWidth, barHeight / 2, 8);
|
163 |
+
ctx.fill();
|
164 |
+
});
|
165 |
+
|
166 |
+
// Draw BST (Base Stat Total)
|
167 |
+
const bst = piclet.bst || (piclet.baseHp + piclet.baseAttack + piclet.baseDefense +
|
168 |
+
piclet.baseFieldAttack + piclet.baseFieldDefense + piclet.baseSpeed);
|
169 |
+
ctx.font = 'bold 18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif';
|
170 |
+
ctx.fillStyle = '#ffd700'; // Gold color
|
171 |
+
ctx.textAlign = 'center';
|
172 |
+
ctx.fillText(`BST: ${bst}`, canvasWidth / 2, containerY + containerHeight - 10);
|
173 |
+
|
174 |
// Load and draw translucent watermark
|
175 |
const logoImg = await loadImage('/assets/snap_logo.png');
|
176 |
const logoSize = 150;
|