File size: 3,844 Bytes
213c234 34f0868 f444918 34f0868 f444918 213c234 34f0868 213c234 f444918 c6f0353 f444918 34f0868 c6f0353 213c234 c6f0353 f444918 34f0868 213c234 c6f0353 213c234 f444918 213c234 f444918 34f0868 213c234 34f0868 f444918 213c234 f444918 34f0868 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 |
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, tighter height
const canvasWidth = 700;
const canvasHeight = 700; // Square format, tighter
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// Clear canvas for transparency (no background fill)
ctx.clearRect(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 = 120; // Position piclet closer to top, leaving room for name
// 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 - 200; // Platform overlaps bottom of piclet
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 64px "Press Start 2P", "Courier New", Impact, monospace';
ctx.textAlign = 'center';
ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
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, 80);
ctx.fillText(nameText, canvasWidth / 2, 80);
// 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');
});
}
|