元素拾取悬停0.3秒自动钻入子元素, 无需先锁定再调层级
- 进入新交互区域先吸附交互元素, 悬停300ms后自动钻入光标最深处 - 钻入后跟随光标在卡片内部移动; PageUp/PageDown 保留为手动上下调层(未锁定时直接锁定)
This commit is contained in:
parent
150d7ce9c9
commit
309898045c
@ -1256,6 +1256,9 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => {
|
||||
let badge = null;
|
||||
let target = null;
|
||||
let deepTarget = null;
|
||||
let lastSnap = null;
|
||||
let drilled = false;
|
||||
let hoverTimer = 0;
|
||||
let locked = false;
|
||||
let chain = [];
|
||||
let chainIndex = 0;
|
||||
@ -1341,7 +1344,7 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => {
|
||||
if (locked) {
|
||||
badge.textContent = '已锁定 ' + (chainIndex + 1) + '/' + chain.length + ' · ' + tag + (name ? ' · ' + name.slice(0, 42) : '') + ' · [PageUp]升 [PageDown]钻入子元素 [空格]确认 [Esc]取消';
|
||||
} else {
|
||||
badge.textContent = '拾取 · ' + tag + (name ? ' · ' + name.slice(0, 42) : '') + ' · [空格]锁定 [Esc]取消 · 可直接翻页后继续拾取';
|
||||
badge.textContent = '拾取 · ' + tag + (name ? ' · ' + name.slice(0, 42) : '') + ' · 悬停0.3秒自动钻入 · [PageUp/PageDown]手动调层 [空格]确认 [Esc]取消 · 可直接翻页后继续拾取';
|
||||
}
|
||||
badge.style.left = Math.max(0, rect.left) + 'px';
|
||||
badge.style.top = Math.max(0, rect.top - 34) + 'px';
|
||||
@ -1387,25 +1390,26 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => {
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const lock = () => {
|
||||
if (locked || !target) return;
|
||||
const lockAt = (base) => {
|
||||
if (locked || !base) return;
|
||||
locked = true;
|
||||
chain = buildChain(target);
|
||||
chain = buildChain(base);
|
||||
chainIndex = Math.max(0, chain.length - 1);
|
||||
// 把光标下最深处元素到锁定元素之间的子级路径并入链,PageDown 可钻入卡片内部的标题/价格等子元素
|
||||
if (deepTarget && target !== deepTarget && target.contains(deepTarget)) {
|
||||
// 把光标下最深处元素到锁定元素之间的子级路径并入链,PageDown/PageUp 可在卡片与其内部子元素间切换
|
||||
if (deepTarget && base !== deepTarget && base.contains(deepTarget)) {
|
||||
const below = [];
|
||||
let current = deepTarget;
|
||||
while (current && current !== target && target.contains(current)) {
|
||||
while (current && current !== base && base.contains(current)) {
|
||||
below.unshift(current);
|
||||
const root = current.getRootNode();
|
||||
current = root instanceof ShadowRoot ? root.host : current.parentElement;
|
||||
}
|
||||
chain = chain.concat(below);
|
||||
}
|
||||
selected = chain[chainIndex] || target;
|
||||
selected = chain[chainIndex] || base;
|
||||
updateBox();
|
||||
};
|
||||
const lock = () => lockAt(target);
|
||||
const adjustLevel = (delta) => {
|
||||
if (!locked || !chain.length) return;
|
||||
const next = Math.min(chain.length - 1, Math.max(0, chainIndex + delta));
|
||||
@ -1421,7 +1425,27 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => {
|
||||
const move = (event) => {
|
||||
if (finished || locked) return;
|
||||
deepTarget = deepestOf(event);
|
||||
target = firstElement(event);
|
||||
const snapped = firstElement(event);
|
||||
if (snapped !== lastSnap) {
|
||||
// 进入新的交互区域:先吸附交互元素,悬停 0.3 秒后自动钻入光标最深处
|
||||
lastSnap = snapped;
|
||||
drilled = false;
|
||||
target = snapped;
|
||||
clearTimeout(hoverTimer);
|
||||
if (deepTarget && deepTarget !== snapped) {
|
||||
hoverTimer = setTimeout(() => {
|
||||
if (finished || locked) return;
|
||||
drilled = true;
|
||||
target = deepTarget;
|
||||
updateBox();
|
||||
}, 300);
|
||||
}
|
||||
updateBox();
|
||||
return;
|
||||
}
|
||||
if (drilled && deepTarget && snapped.contains(deepTarget)) {
|
||||
target = deepTarget; // 已钻入:跟随光标在卡片内部移动
|
||||
}
|
||||
updateBox();
|
||||
};
|
||||
const click = (event) => {
|
||||
@ -1444,21 +1468,24 @@ const PICKER_BOOTSTRAP_SOURCE = `(() => {
|
||||
else lock();
|
||||
return;
|
||||
}
|
||||
if (locked && event.key === 'PageUp' && !event.repeat) {
|
||||
if (event.key === 'PageDown' && !event.repeat) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
adjustLevel(-1);
|
||||
if (locked) adjustLevel(1);
|
||||
else lockAt(deepTarget || target); // 未锁定时直接锁定光标最深处(如卡片内的标题)
|
||||
return;
|
||||
}
|
||||
if (locked && event.key === 'PageDown' && !event.repeat) {
|
||||
if (event.key === 'PageUp' && !event.repeat) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
adjustLevel(1);
|
||||
if (locked) adjustLevel(-1);
|
||||
else if (target) lockAt(target); // 未锁定时锁定吸附到的交互元素(如整张卡片)
|
||||
}
|
||||
};
|
||||
const cleanup = () => {
|
||||
if (finished) return;
|
||||
finished = true;
|
||||
clearTimeout(hoverTimer);
|
||||
window.removeEventListener('mousemove', move, true);
|
||||
window.removeEventListener('mousedown', click, true);
|
||||
window.removeEventListener('click', click, true);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user