|
import type { PicletInstance } from '$lib/db/schema'; |
|
import { embedPicletMetadata } from './picletMetadata'; |
|
|
|
|
|
|
|
|
|
export async function generateShareableImage(piclet: PicletInstance): Promise<Blob> { |
|
|
|
const canvas = document.createElement('canvas'); |
|
const ctx = canvas.getContext('2d'); |
|
if (!ctx) throw new Error('Could not create canvas context'); |
|
|
|
|
|
const canvasSize = 1024; |
|
canvas.width = canvasSize; |
|
canvas.height = canvasSize; |
|
|
|
|
|
ctx.fillStyle = '#87CEEB'; |
|
ctx.fillRect(0, 0, canvasSize, canvasSize); |
|
|
|
|
|
const picletImg = await loadImage(piclet.imageData || piclet.imageUrl); |
|
const picletSize = 512; |
|
const picletX = (canvasSize - picletSize) / 2; |
|
const picletY = canvasSize / 2 - picletSize / 2 + 50; |
|
|
|
|
|
const grassImg = await loadImage('/assets/grass.PNG'); |
|
const platformSize = picletSize + 100; |
|
const platformX = (canvasSize - platformSize) / 2; |
|
const platformY = picletY + picletSize - 150; |
|
ctx.drawImage(grassImg, platformX, platformY, platformSize, platformSize); |
|
|
|
|
|
ctx.drawImage(picletImg, picletX, picletY, picletSize, picletSize); |
|
|
|
|
|
ctx.fillStyle = 'white'; |
|
ctx.strokeStyle = 'black'; |
|
ctx.lineWidth = 6; |
|
ctx.font = 'bold 64px Arial'; |
|
ctx.textAlign = 'center'; |
|
|
|
const nameText = piclet.nickname || piclet.typeId; |
|
|
|
|
|
ctx.strokeText(nameText, canvasSize / 2, 120); |
|
ctx.fillText(nameText, canvasSize / 2, 120); |
|
|
|
|
|
const logoImg = await loadImage('/assets/snap_logo.png'); |
|
const logoSize = 150; |
|
ctx.globalAlpha = 0.3; |
|
ctx.drawImage(logoImg, canvasSize - logoSize - 30, canvasSize - logoSize - 30, logoSize, logoSize); |
|
ctx.globalAlpha = 1.0; |
|
|
|
|
|
const blob = await canvasToBlob(canvas); |
|
|
|
|
|
return embedPicletMetadata(blob, piclet); |
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
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'); |
|
}); |
|
} |
|
|
|
|