Add background grid settings
Appearance now has a toggle for the background grid and a choice of subdivisions (none, 2×2 up to 16×16) that split each page-sized cell into fainter lines. Subdivisions are left out when zoomed so far out that they would be under 8 px apart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GaoZtJQZwLXkEgWs8twCia
This commit is contained in:
parent
f018012cdd
commit
3d29255d0c
4 changed files with 46 additions and 7 deletions
|
|
@ -61,6 +61,7 @@
|
|||
--shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||
--page-line: rgba(0, 0, 0, 0.18);
|
||||
--grid-line: rgba(0, 0, 0, 0.05);
|
||||
--grid-line-minor: rgba(0, 0, 0, 0.028);
|
||||
--ghost: rgba(0, 0, 0, 0.045);
|
||||
--ghost-border: rgba(0, 0, 0, 0.12);
|
||||
--radius: 6px;
|
||||
|
|
@ -88,6 +89,7 @@
|
|||
--shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.35);
|
||||
--page-line: rgba(255, 255, 255, 0.16);
|
||||
--grid-line: rgba(255, 255, 255, 0.04);
|
||||
--grid-line-minor: rgba(255, 255, 255, 0.022);
|
||||
--ghost: rgba(255, 255, 255, 0.04);
|
||||
--ghost-border: rgba(255, 255, 255, 0.14);
|
||||
color-scheme: dark;
|
||||
|
|
|
|||
|
|
@ -30,11 +30,28 @@
|
|||
let stage: HTMLDivElement;
|
||||
const cssVars = pageCssVars();
|
||||
|
||||
// Background grid: one cell per active page, aligned to its edges (A4 at the origin if none).
|
||||
const grid = $derived.by(() => {
|
||||
// Background grid: one cell per active page, aligned to its edges (A4 at the origin if none),
|
||||
// optionally split into fainter subdivisions.
|
||||
const gridStyle = $derived.by(() => {
|
||||
const g = settings.data.grid;
|
||||
if (!g.show) return '';
|
||||
const r = (doc.activeId && doc.rects.get(doc.activeId)) || { x: 0, y: 0, ...A4 };
|
||||
const s = viewport.scale;
|
||||
return { w: r.width * s, h: r.height * s, x: viewport.x + r.x * s, y: viewport.y + r.y * s };
|
||||
const w = r.width * s;
|
||||
const h = r.height * s;
|
||||
const lines = (color: string) => [
|
||||
`linear-gradient(to right, ${color} 1px, transparent 1px)`,
|
||||
`linear-gradient(to bottom, ${color} 1px, transparent 1px)`
|
||||
];
|
||||
const images = lines('var(--grid-line)');
|
||||
const sizes = [`${w}px ${h}px`, `${w}px ${h}px`];
|
||||
// Leave out subdivisions once they'd be too dense to read.
|
||||
const n = g.divisions;
|
||||
if (n > 1 && Math.min(w, h) / n >= 8) {
|
||||
images.push(...lines('var(--grid-line-minor)'));
|
||||
sizes.push(`${w / n}px ${h / n}px`, `${w / n}px ${h / n}px`);
|
||||
}
|
||||
return `background-image: ${images.join(', ')}; background-size: ${sizes.join(', ')}; background-position: ${viewport.x + r.x * s}px ${viewport.y + r.y * s}px`;
|
||||
});
|
||||
|
||||
// ---- autosave --------------------------------------------------------
|
||||
|
|
@ -605,7 +622,7 @@
|
|||
class:panning
|
||||
class:erasing={tools.tool === 'eraser'}
|
||||
bind:this={stage}
|
||||
style="background-size: {grid.w}px {grid.h}px; background-position: {grid.x}px {grid.y}px"
|
||||
style={gridStyle}
|
||||
onpointerdown={onPointerDown}
|
||||
onpointermove={onPointerMove}
|
||||
onpointerup={onPointerUp}
|
||||
|
|
@ -760,9 +777,6 @@
|
|||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
background-color: var(--bg-canvas);
|
||||
background-image:
|
||||
linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
|
||||
linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
|
||||
}
|
||||
.stage :global(.cm-content) {
|
||||
user-select: text;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,20 @@
|
|||
<option value="paper">Paper</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="name">Background grid</div><div class="desc">Faint lines behind the pages, one cell per active page.</div></div>
|
||||
<input type="checkbox" class="toggle" bind:checked={s.grid.show} onchange={save} />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="name">Grid subdivisions</div><div class="desc">Split each page-sized cell into a finer grid for sketching and lining things up.</div></div>
|
||||
<select bind:value={s.grid.divisions} onchange={save} disabled={!s.grid.show}>
|
||||
<option value={1}>None</option>
|
||||
<option value={2}>2 × 2</option>
|
||||
<option value={4}>4 × 4</option>
|
||||
<option value={8}>8 × 8</option>
|
||||
<option value={16}>16 × 16</option>
|
||||
</select>
|
||||
</div>
|
||||
{:else if tab === 'input'}
|
||||
<h2>Pen & touch</h2>
|
||||
<div class="row">
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@ import { DEFAULT_PALM, type PalmOptions } from '$lib/ink/palm';
|
|||
export type ThemePref = 'system' | 'light' | 'dark';
|
||||
export type PageStylePref = 'paper' | 'match';
|
||||
|
||||
export interface GridSettings {
|
||||
show: boolean;
|
||||
/** Minor lines per page cell side (1 = page-sized cells only). */
|
||||
divisions: number;
|
||||
}
|
||||
|
||||
export interface GitHubSettings {
|
||||
token: string;
|
||||
owner: string;
|
||||
|
|
@ -18,6 +24,7 @@ export interface GitHubSettings {
|
|||
interface SettingsData {
|
||||
theme: ThemePref;
|
||||
pageStyle: PageStylePref;
|
||||
grid: GridSettings;
|
||||
fingerDraw: boolean;
|
||||
palm: PalmOptions;
|
||||
github: GitHubSettings;
|
||||
|
|
@ -30,6 +37,7 @@ interface SettingsData {
|
|||
const DEFAULTS: SettingsData = {
|
||||
theme: 'system',
|
||||
pageStyle: 'match',
|
||||
grid: { show: true, divisions: 1 },
|
||||
fingerDraw: true,
|
||||
palm: DEFAULT_PALM,
|
||||
github: { token: '', owner: '', repo: '', branch: 'main', dir: '' },
|
||||
|
|
@ -48,6 +56,7 @@ function load(): SettingsData {
|
|||
return {
|
||||
...DEFAULTS,
|
||||
...saved,
|
||||
grid: { ...DEFAULTS.grid, ...saved.grid },
|
||||
palm: { ...DEFAULTS.palm, ...saved.palm },
|
||||
github: { ...DEFAULTS.github, ...saved.github }
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue