Add adaptive coordinate guides to canvas editor
This commit is contained in:
@@ -3,6 +3,8 @@ export const BRUSH_MODE_PIXEL = "pixel";
|
||||
export const CANVAS_VIEW_MIN_SCALE = 1;
|
||||
export const CANVAS_VIEW_MAX_SCALE = 8;
|
||||
export const CANVAS_UNDO_LIMIT = 50;
|
||||
export const COORDINATE_GUIDE_STEPS = Object.freeze([1, 2, 4, 8, 16, 32]);
|
||||
export const COORDINATE_GUIDE_TARGET_SPACING = 48;
|
||||
|
||||
const MODE_SPECS = Object.freeze({
|
||||
[BRUSH_MODE_NORMAL]: Object.freeze({ min: 1, max: 16, presets: Object.freeze([1, 2, 4, 8]) }),
|
||||
@@ -23,23 +25,55 @@ export function normalizeBrushSize(value, mode) {
|
||||
return Math.max(spec.min, Math.min(spec.max, Number.isFinite(parsed) ? parsed : spec.min));
|
||||
}
|
||||
|
||||
export function restoreCanvasToolState(savedV2, savedV1 = null) {
|
||||
const current = record(savedV2);
|
||||
const legacy = record(savedV1);
|
||||
export function restoreCanvasToolState(savedV3, savedV2 = null) {
|
||||
const current = record(savedV3);
|
||||
const legacy = record(savedV2);
|
||||
const source = current || legacy || {};
|
||||
return {
|
||||
paintColor: typeof source.paintColor === "string" ? source.paintColor : null,
|
||||
backgroundColor: typeof source.backgroundColor === "string" ? source.backgroundColor : null,
|
||||
tool: source.tool === "eraser" ? "eraser" : "brush",
|
||||
pixelEditEnabled: Boolean(current?.pixelEditEnabled),
|
||||
pixelEditEnabled: Boolean(source.pixelEditEnabled),
|
||||
normalBrushSize: normalizeBrushSize(
|
||||
current?.normalBrushSize ?? source.brushSize,
|
||||
source.normalBrushSize ?? source.brushSize,
|
||||
BRUSH_MODE_NORMAL,
|
||||
),
|
||||
pixelBrushSize: normalizeBrushSize(current?.pixelBrushSize, BRUSH_MODE_PIXEL),
|
||||
pixelBrushSize: normalizeBrushSize(source.pixelBrushSize, BRUSH_MODE_PIXEL),
|
||||
coordinateGuideEnabled: Boolean(current?.coordinateGuideEnabled),
|
||||
};
|
||||
}
|
||||
|
||||
export function chooseCoordinateGuideStep(
|
||||
logicalPixelCssSize,
|
||||
targetSpacing = COORDINATE_GUIDE_TARGET_SPACING,
|
||||
) {
|
||||
const pixelSize = Math.max(0, Number(logicalPixelCssSize) || 0);
|
||||
const target = Math.max(1, Number(targetSpacing) || COORDINATE_GUIDE_TARGET_SPACING);
|
||||
return COORDINATE_GUIDE_STEPS.reduce((best, candidate) => (
|
||||
Math.abs(candidate * pixelSize - target) < Math.abs(best * pixelSize - target)
|
||||
? candidate
|
||||
: best
|
||||
), COORDINATE_GUIDE_STEPS[0]);
|
||||
}
|
||||
|
||||
export function coordinateGuideTicks({
|
||||
boardStart,
|
||||
boardSize,
|
||||
visibleStart = Number.NEGATIVE_INFINITY,
|
||||
visibleEnd = Number.POSITIVE_INFINITY,
|
||||
step,
|
||||
}) {
|
||||
const start = Number(boardStart) || 0;
|
||||
const size = Math.max(0, Number(boardSize) || 0);
|
||||
const interval = COORDINATE_GUIDE_STEPS.includes(step) ? step : COORDINATE_GUIDE_STEPS[0];
|
||||
const ticks = [];
|
||||
for (let value = 0; value < 64; value += interval) {
|
||||
const position = start + (value / 64) * size;
|
||||
if (position >= visibleStart && position <= visibleEnd) ticks.push({ value, position });
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
|
||||
export function linePoints(from, to) {
|
||||
const points = [];
|
||||
let x = from.x;
|
||||
|
||||
Reference in New Issue
Block a user