初始化奇妙小屏幕控制器项目

This commit is contained in:
2026-09-08 22:56:52 +08:00
commit 8d368de3b5
491 changed files with 67678 additions and 0 deletions
@@ -0,0 +1,56 @@
const OUTPUT_PIXELS = 64;
function positiveNumber(value, field) {
const number = Number(value);
if (!Number.isFinite(number) || number <= 0) {
throw new TypeError(field + " must be a positive number");
}
return number;
}
export function cropGeometry({
viewportWidth, viewportHeight, sourceWidth, sourceHeight, zoom, centerX, centerY,
}) {
const viewWidth = positiveNumber(viewportWidth, "viewportWidth");
const viewHeight = positiveNumber(viewportHeight, "viewportHeight");
const imageWidth = positiveNumber(sourceWidth, "sourceWidth");
const imageHeight = positiveNumber(sourceHeight, "sourceHeight");
const scaleZoom = positiveNumber(zoom, "zoom");
const x = Number(centerX), y = Number(centerY);
if (!Number.isFinite(x) || !Number.isFinite(y)) {
throw new TypeError("crop center must be finite");
}
const scale = Math.min(viewWidth / imageWidth, viewHeight / imageHeight) * scaleZoom;
const width = imageWidth * scale;
const height = imageHeight * scale;
return {
width,
height,
left: viewWidth / 2 - x * width,
top: viewHeight / 2 - y * height,
};
}
export function cropCenterBounds({
viewportWidth, viewportHeight, sourceWidth, sourceHeight, zoom,
}) {
const geometry = cropGeometry({
viewportWidth, viewportHeight, sourceWidth, sourceHeight, zoom,
centerX: 0.5, centerY: 0.5,
});
const visibleX = Math.min(Number(viewportWidth) / OUTPUT_PIXELS, geometry.width);
const visibleY = Math.min(Number(viewportHeight) / OUTPUT_PIXELS, geometry.height);
return {
minX: (visibleX - Number(viewportWidth) / 2) / geometry.width,
maxX: 1 + (Number(viewportWidth) / 2 - visibleX) / geometry.width,
minY: (visibleY - Number(viewportHeight) / 2) / geometry.height,
maxY: 1 + (Number(viewportHeight) / 2 - visibleY) / geometry.height,
};
}
export function clampCropCenter(value, bounds) {
return {
centerX: Math.max(bounds.minX, Math.min(bounds.maxX, Number(value.centerX))),
centerY: Math.max(bounds.minY, Math.min(bounds.maxY, Number(value.centerY))),
};
}