76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
const PROJECT_PIXEL_STYLE_REFERENCE_SOURCES = [
|
|
'/character/Sword Princess/Original/Hero/idle/Idle01.png',
|
|
'/character/Archer Hero/Original/Hero/idle/idle01.png',
|
|
'/character/Girl Hero 1/Original/Hero/Idle/Idle01.png',
|
|
'/character/Punch Hero 3/Original/Hero/Idle/Idle01.png',
|
|
'/character/Fighter 4/original/Hero/idle/idle01.png',
|
|
] as const;
|
|
|
|
function loadImageFromSource(source: string) {
|
|
return new Promise<HTMLImageElement>((resolve, reject) => {
|
|
const image = new Image();
|
|
image.crossOrigin = 'anonymous';
|
|
image.onload = () => resolve(image);
|
|
image.onerror = () => reject(new Error(`加载图片失败:${source}`));
|
|
image.src = source;
|
|
});
|
|
}
|
|
|
|
function drawContainedImage(
|
|
context: CanvasRenderingContext2D,
|
|
image: HTMLImageElement,
|
|
options: {
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
},
|
|
) {
|
|
const fitScale = Math.min(
|
|
options.width / image.width,
|
|
options.height / image.height,
|
|
);
|
|
const drawWidth = image.width * fitScale;
|
|
const drawHeight = image.height * fitScale;
|
|
const drawX = options.x + (options.width - drawWidth) / 2;
|
|
const drawY = options.y + (options.height - drawHeight) / 2;
|
|
|
|
context.drawImage(image, drawX, drawY, drawWidth, drawHeight);
|
|
}
|
|
|
|
export async function buildProjectPixelStyleReferenceBoard(
|
|
sources = PROJECT_PIXEL_STYLE_REFERENCE_SOURCES,
|
|
) {
|
|
const images = await Promise.all(
|
|
sources.map((source) => loadImageFromSource(source)),
|
|
);
|
|
const cols = 3;
|
|
const rows = 2;
|
|
const cellSize = 320;
|
|
const padding = 24;
|
|
const canvas = document.createElement('canvas');
|
|
const context = canvas.getContext('2d');
|
|
if (!context) {
|
|
throw new Error('无法创建画布上下文');
|
|
}
|
|
|
|
canvas.width = cols * cellSize + padding * 2;
|
|
canvas.height = rows * cellSize + padding * 2;
|
|
context.fillStyle = '#f6f0dd';
|
|
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
context.imageSmoothingEnabled = false;
|
|
|
|
images.forEach((image, index) => {
|
|
const colIndex = index % cols;
|
|
const rowIndex = Math.floor(index / cols);
|
|
drawContainedImage(context, image, {
|
|
x: padding + colIndex * cellSize,
|
|
y: padding + rowIndex * cellSize,
|
|
width: cellSize,
|
|
height: cellSize,
|
|
});
|
|
});
|
|
|
|
return canvas.toDataURL('image/png');
|
|
}
|