mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 12:06:42 +02:00
Add new @manacore/wallpaper-generator package for creating device wallpapers from QR codes and images. Features: - 30 device presets (phones, tablets, desktops) - 3 layout types (center, corner, pattern) - 5 gradient presets + solid color backgrounds - Browser (Canvas) and Node.js (Sharp) renderers - Svelte WallpaperModal UI component Integrations: - @manacore/qr-export: toWallpaper() function - @manacore/spiral-db: toWallpaper() function - QRExportModal: "Als Wallpaper" button Also includes the full @manacore/qr-export package which was previously untracked. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
88 lines
2.1 KiB
TypeScript
88 lines
2.1 KiB
TypeScript
/**
|
|
* Pattern Layout
|
|
*
|
|
* Tiles image across the wallpaper as a repeating pattern.
|
|
*/
|
|
|
|
import type { PatternLayout } from '../types.js';
|
|
|
|
export interface PatternTile {
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
}
|
|
|
|
/**
|
|
* Calculate tile positions for pattern
|
|
*/
|
|
export function calculatePatternTiles(
|
|
canvasWidth: number,
|
|
canvasHeight: number,
|
|
imageWidth: number,
|
|
imageHeight: number,
|
|
layout: PatternLayout
|
|
): PatternTile[] {
|
|
const scale = layout.scale ?? 0.5;
|
|
const gap = layout.gap ?? 20;
|
|
|
|
const tileWidth = imageWidth * scale;
|
|
const tileHeight = imageHeight * scale;
|
|
|
|
const tiles: PatternTile[] = [];
|
|
|
|
// Calculate how many tiles fit (with overlap to cover edges)
|
|
const cols = Math.ceil(canvasWidth / (tileWidth + gap)) + 1;
|
|
const rows = Math.ceil(canvasHeight / (tileHeight + gap)) + 1;
|
|
|
|
// Center the pattern grid
|
|
const totalPatternWidth = cols * tileWidth + (cols - 1) * gap;
|
|
const totalPatternHeight = rows * tileHeight + (rows - 1) * gap;
|
|
|
|
const startX = (canvasWidth - totalPatternWidth) / 2;
|
|
const startY = (canvasHeight - totalPatternHeight) / 2;
|
|
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col = 0; col < cols; col++) {
|
|
tiles.push({
|
|
x: Math.round(startX + col * (tileWidth + gap)),
|
|
y: Math.round(startY + row * (tileHeight + gap)),
|
|
width: Math.round(tileWidth),
|
|
height: Math.round(tileHeight),
|
|
});
|
|
}
|
|
}
|
|
|
|
return tiles;
|
|
}
|
|
|
|
/**
|
|
* Draw pattern on canvas (browser)
|
|
*/
|
|
export function drawPattern(
|
|
ctx: CanvasRenderingContext2D,
|
|
image: HTMLImageElement | HTMLCanvasElement,
|
|
canvasWidth: number,
|
|
canvasHeight: number,
|
|
layout: PatternLayout
|
|
): void {
|
|
const opacity = layout.opacity ?? 0.15;
|
|
const tiles = calculatePatternTiles(canvasWidth, canvasHeight, image.width, image.height, layout);
|
|
|
|
// Save current state
|
|
ctx.save();
|
|
|
|
// Set opacity for pattern
|
|
ctx.globalAlpha = opacity;
|
|
|
|
// Use crisp rendering for pixel art / QR codes
|
|
ctx.imageSmoothingEnabled = false;
|
|
|
|
// Draw all tiles
|
|
for (const tile of tiles) {
|
|
ctx.drawImage(image, tile.x, tile.y, tile.width, tile.height);
|
|
}
|
|
|
|
// Restore state
|
|
ctx.restore();
|
|
}
|