WEBSITE - WIP - icon shapes - move mode fixes

This commit is contained in:
Alex Sim committed 2026-10-11 03:22:27 +02:00
1 parent c6ab2ab2b4
commit 108113a0d4
3 files changed
+26 -8

No files matched your search

+1 -1
View File
@@ -5,7 +5,7 @@ description: >-
url: "https://alesimula.github.io"
baseurl: ""
version: "1.0.21" #Website version - increase to invalidate cached resources
version: "1.0.22" #Website version - increase to invalidate cached resources
github_repo: "alesimula/Murine-launcher"
icon_url: "https://raw.githubusercontent.com/alesimula/Murine-launcher/refs/heads/main/image/app_icon/icon_browser_fullsize.svg"
icon_freeform_url: "https://raw.githubusercontent.com/alesimula/Murine-launcher/refs/heads/main/image/app_icon/icon_freeform.svg"
+19 -5
View File
@@ -532,14 +532,14 @@
for (const b of $('se-mirror').querySelectorAll('[data-pivot]')) b.setAttribute('aria-pressed', b.dataset.pivot === pivotMode);
if (moving) { const c = pivot(shapes[active]); $('se-pivot-mark').setAttribute('transform', `translate(${c.x} ${c.y})`); }
// The stretch marks: in Move mode on the pivot cross, past the end of its arms; in Edit mode from the
// middle of the box, around a dot.
// centre of mass, around a dot.
const info = stretchInfo(shapes[active]);
$('se-stretch-arrows').setAttribute('d', moving ? stretchArrows(info, 4) : '');
const editMark = !moving && info && pts;
$('se-stretch-mark').style.display = editMark ? '' : 'none';
if (editMark) {
const b = measure(lines[active][0]);
$('se-stretch-mark').setAttribute('transform', `translate(${b.x + b.width / 2} ${b.y + b.height / 2})`);
const c = centroid(shapes[active]);
$('se-stretch-mark').setAttribute('transform', `translate(${c.x} ${c.y})`);
$('se-stretch-mark').querySelector('path').setAttribute('d', stretchArrows(info, 1.6));
}
@@ -725,6 +725,7 @@
const w = wpt(pts[sel]);
drag = { kind: 'point', dx: w.x - at.x, dy: w.y - at.y }; // the point keeps its distance from the finger
} else if (g.move) {
pickedCorner = -1; // grabbing the shape itself lets go of the handle, back to the rotation pill
drag = { kind: 'move', from: at, orig: shapes[active] };
} else {
const c = boxHandles(activeBox), anchor = c[opposite(g.resize)];
@@ -797,6 +798,7 @@
if (e.key === 'Escape') { pickedCorner = -1; e.preventDefault(); return render(); }
if (!mv) return;
checkpoint();
pickedCorner = -1;
shapes[active] = transform(shapes[active], 1, 0, 0, mv[0] * step, mv[1] * step);
sync();
} else if (sel < 0) return;
@@ -898,12 +900,22 @@
// Rotation slider: one undo step per drag, and every value is turned from the shape as it was when the
// drag started, so the points don't pick up rounding from hundreds of small turns.
let turnFrom = null;
// Turning around the middle of the box: that middle moves as the shape turns, so a faded mark stays on
// the point the turn pivots around, and fades out shortly after the turn.
let ghostTimer = 0;
const ghost = (c) => {
clearTimeout(ghostTimer);
if (pivotMode !== 'box') return;
$('se-pivot-ghost').setAttribute('transform', `translate(${c.x} ${c.y})`);
$('se-pivot-ghost').classList.remove('off');
};
const ghostOff = () => { clearTimeout(ghostTimer); ghostTimer = setTimeout(() => $('se-pivot-ghost').classList.add('off'), 800); };
$('se-turn').addEventListener('input', (e) => {
if (!turnFrom) { checkpoint(); turnFrom = shapes[active]; }
if (!turnFrom) { checkpoint(); turnFrom = shapes[active]; ghost(pivot(turnFrom)); }
shapes[active] = rotated(turnFrom, +e.target.value - (turnFrom.rot || 0));
sync(); render();
});
['change', 'blur'].forEach((t) => $('se-turn').addEventListener(t, () => (turnFrom = null)));
['change', 'blur'].forEach((t) => $('se-turn').addEventListener(t, () => { turnFrom = null; ghostOff(); }));
// The icon switches between the slider and typing the angle; any typed angle is wrapped into 0-359.
$('se-turn-mode').onclick = () => {
turnTyping = !turnTyping;
@@ -916,6 +928,8 @@
const deg = ((v - (sh.rot || 0)) % 360 + 360) % 360;
if (deg < 0.005 || deg > 359.995) return render();
checkpoint();
ghost(pivot(sh));
ghostOff();
shapes[active] = rotated(sh, deg);
sync(); render();
});
+6 -2
View File
@@ -94,7 +94,7 @@ noindex: true # and out of search engines
background: var(--md-surface-container); border: 1px solid var(--md-outline-variant); border-radius: var(--md-shape-xs); }
.se-pill button { width: 34px; height: 34px; display: inline-flex; align-items: center; justify-content: center; padding: 0;
border: 0; border-radius: var(--md-shape-full); background: transparent; color: var(--md-primary); cursor: pointer; }
.se-pill button:hover:not(:disabled) { background: var(--md-surface-container-high); }
.se-pill button:hover:not(:disabled):not([aria-pressed="true"]) { background: var(--md-surface-container-high); }
.se-pill button:disabled { opacity: .35; cursor: default; }
.se-pill button[aria-pressed="true"] { background: var(--md-primary-container); color: var(--md-on-primary-container); }
.se-pill .material-symbols-outlined { font-size: 20px; }
@@ -145,8 +145,10 @@ noindex: true # and out of search engines
.se-mirror button[aria-pressed="true"] { background: var(--md-primary-container); color: var(--md-on-primary-container); }
.se-mirror svg { width: 20px; height: 20px; }
.se-pivot { display: flex; gap: 2px; padding-left: 5px; margin-left: 3px; border-left: 1px solid var(--md-outline-variant); }
.se-pivot-ghost { pointer-events: none; fill: none; stroke: var(--md-primary); stroke-width: .55; stroke-linecap: round; opacity: .8; transition: opacity .6s; }
.se-pivot-ghost.off { opacity: 0; }
.se-pivot-mark { pointer-events: none; fill: none; stroke: var(--md-primary); stroke-width: .6; stroke-linecap: round; stroke-linejoin: round; }
.se-stage-btn:hover, .se-mirror button:hover { background: var(--md-surface-container-high); }
.se-stage-btn:hover, .se-mirror button:hover:not([aria-pressed="true"]) { background: var(--md-surface-container-high); }
.se-stage-tools[hidden], .se-mirror[hidden], .se-stage-btn[hidden] { display: none; }
.se-stage-btn svg { width: 22px; height: 22px; }
/* Shape cards under the canvas. */
@@ -212,6 +214,8 @@ noindex: true # and out of search engines
<rect class="se-resize" width="2.2" height="6" rx="1.1" style="cursor: ew-resize"/>
<rect class="se-resize" width="6" height="2.2" rx="1.1" style="cursor: ns-resize"/>
<rect class="se-resize" width="2.2" height="6" rx="1.1" style="cursor: ew-resize"/>
<!-- where a turn around the middle of the box pivots: that middle moves as the shape turns -->
<g id="se-pivot-ghost" class="se-pivot-ghost off"><circle r="1.8" stroke-dasharray=".7 .7"/><path d="M0 -4V-2.2M0 2.2V4M-4 0H-2.2M2.2 0H4"/></g>
<g id="se-pivot-mark" class="se-pivot-mark"><circle r="1.8"/><path d="M0 -4V-2.2M0 2.2V4M-4 0H-2.2M2.2 0H4"/><circle r=".5" fill="var(--md-primary)" stroke="none"/><path id="se-stretch-arrows"/></g>
</g>
</svg>