File size: 3,874 Bytes
213c234 f444918 213c234 c6f0353 f444918 213c234 f444918 c6f0353 f444918 c6f0353 213c234 c6f0353 f444918 213c234 c6f0353 213c234 f444918 213c234 f444918 213c234 f444918 213c234 f444918 213c234 c6f0353 213c234 f444918 c6f0353 f444918 213c234 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
import type { PicletInstance } from '$lib/db/schema';
import { embedPicletMetadata } from './picletMetadata';
/**
* Generates a shareable image of a piclet with embedded metadata
*/
export async function generateShareableImage(piclet: PicletInstance): Promise<Blob> {
// Create canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (!ctx) throw new Error('Could not create canvas context');
// Set canvas size - narrower width to match content
const canvasWidth = 700;
const canvasHeight = 1536; // Taller to accommodate piclet at bottom
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// Fill background with solid sky blue
ctx.fillStyle = '#87CEEB';
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
// Load piclet image first
const picletImg = await loadImage(piclet.imageData || piclet.imageUrl);
const picletSize = 512;
const picletX = (canvasWidth - picletSize) / 2;
const picletY = canvasHeight - picletSize - 50; // Position near bottom with small margin
// Load and draw grass platform positioned under the piclet
const grassImg = await loadImage('/assets/grass.PNG');
const platformSize = picletSize + 100; // Slightly larger than piclet
const platformX = (canvasWidth - platformSize) / 2;
const platformY = picletY + picletSize - 180; // Position so piclet sits on platform
ctx.drawImage(grassImg, platformX, platformY, platformSize, platformSize);
// Draw piclet on top of platform
ctx.drawImage(picletImg, picletX, picletY, picletSize, picletSize);
// Add piclet name with video game font
ctx.fillStyle = 'white';
ctx.strokeStyle = '#1e3a8a'; // Dark blue outline
ctx.lineWidth = 8;
// Try to use a more gaming-style font, fallback to Impact
ctx.font = 'bold 72px "Press Start 2P", "Courier New", Impact, monospace';
ctx.textAlign = 'center';
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
const nameText = piclet.nickname || piclet.typeId;
// Draw name with outline and shadow
ctx.strokeText(nameText, canvasWidth / 2, 150);
ctx.fillText(nameText, canvasWidth / 2, 150);
// Reset shadow
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
// Load and draw translucent watermark
const logoImg = await loadImage('/assets/snap_logo.png');
const logoSize = 120;
ctx.globalAlpha = 0.3; // More translucent
ctx.drawImage(logoImg, canvasWidth - logoSize - 20, canvasHeight - logoSize - 20, logoSize, logoSize);
ctx.globalAlpha = 1.0;
// Get the image as blob
const blob = await canvasToBlob(canvas);
// Embed metadata in the blob
return embedPicletMetadata(blob, piclet);
}
/**
* Downloads a piclet card image
*/
export async function downloadPicletCard(piclet: PicletInstance, filename?: string): Promise<void> {
const blob = await generateShareableImage(piclet);
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename || `Piclet_${piclet.nickname || piclet.typeId}_Lv${piclet.level}.png`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
/**
* Helper to load an image
*/
function loadImage(src: string): Promise<HTMLImageElement> {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
}
/**
* Convert canvas to blob
*/
function canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob> {
return new Promise((resolve, reject) => {
canvas.toBlob((blob) => {
if (blob) resolve(blob);
else reject(new Error('Failed to create blob'));
}, 'image/png');
});
}
|