mirror of
https://github.com/alesimula/Murine-launcher.git
synced 2026-10-28 09:43:42 +00:00
WEBSITE - WIP - icon shapes - move mode fixes
This commit is contained in:
1 parent
c6ab2ab2b4
commit
108113a0d4
3 files changed
+26
-8
No files matched your search
+1
-1
@@ -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"
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user