修色板被裁切 + 让人看得出能选全色域

用户两个反馈:
① 色板直接被挡住了一半
② 它不是完全的颜色,好像只有蓝色

① 根因:色板用 position:absolute,而它在
   <details class="tax-form-box"> 里面,那个容器有 overflow:hidden。
   色相条正好在面板最底部 —— 被裁掉了,所以看不见。
   改 position:fixed,直接相对视口定位,任何祖先 overflow 都管不到。
   位置改由 JS 按触发按钮坐标算,并处理三种情况:
     右边超出→左移;下方不够→翻上方;都放不下→贴视口底边
   另加 resize/scroll 监听,避免滚动后色板漂走。

② 不是 bug,是 ① 的连带后果:
   HSV 色板本来就只显示当前色相的深浅变化,换颜色靠色相条。
   色相条被裁掉后,用户只看到一片蓝,自然以为只有蓝色。
   修好裁切后已实测 6 个色相各不相同:
     0°红 60°黄 120°绿 180°青 240°蓝 300°品红
   同时把色相条从 14px 加高到 18px 并加内描边,
   让它一眼就能认出是光谱条,而不是一条灰线。

验证(用真实后台容器结构复刻测试页,details 带 overflow:hidden):
  面板四边 elementFromPoint 都能命中自己 → 未被任何容器裁切
  色相条可见、高 18px;面板总高 367px
  滚到页面底部再开面板仍完整可见
  6 个色相取样互不相同,色板能覆盖全色域
  实际取色 #0ce779 正常
  4 个路由 200
This commit is contained in:
2026-11-04 19:01:04 +08:00
parent 338a35cacd
commit a2a3306169
3 changed files with 68 additions and 19 deletions
+48 -7
View File
@@ -847,17 +847,58 @@
// ---- 打开 / 关闭 ----
function openPanel() {
panel.hidden = false;
// 面板可能超出视口底部,翻到上方
var r = trigger.getBoundingClientRect();
panel.classList.remove('cp-up');
var need = panel.offsetHeight + 8;
if (r.bottom + need > window.innerHeight && r.top > need) {
panel.classList.add('cp-up');
}
drawSV(); moveCursor();
positionPanel();
}
/* 色板是 position:fixed,位置必须自己算。
*
* 🔴 为什么不用 absolute 贴按钮:后台这个表单在
* <details class="tax-form-box"> 里,那个容器有 overflow:hidden,
* absolute 会被裁掉下半部分 —— 色相条正好在底部,连带看不见,
* 用户就以为"色板只有蓝色"。fixed 不受任何祖先 overflow 影响。
*
* 定位规则:
* ① 默认贴在触发按钮下方,左边缘对齐按钮
* ② 右边超出视口就往左挪
* ③ 下方空间不够就翻到按钮上方
* ④ 都放不下(屏幕太矮)就贴住视口上下边,保证能看全 */
function positionPanel() {
if (panel.hidden) { return; }
var r = trigger.getBoundingClientRect();
var pw = panel.offsetWidth;
var ph = panel.offsetHeight;
var vw = window.innerWidth;
var vh = window.innerHeight;
var gap = 8;
var margin = 10;
// 水平:默认左对齐按钮
var left = r.left;
if (left + pw + margin > vw) { left = vw - pw - margin; }
if (left < margin) { left = margin; }
// 垂直:优先下方
var top = r.bottom + gap;
if (top + ph + margin > vh) {
var above = r.top - gap - ph;
if (above >= margin) {
top = above; // 放上面
} else {
top = Math.max(margin, vh - ph - margin); // 都放不下:贴住底部
}
}
panel.style.left = Math.round(left) + 'px';
panel.style.top = Math.round(top) + 'px';
}
function closePanel() { panel.hidden = true; }
// 窗口尺寸变化 / 滚动时重新定位,避免色板"漂走"
window.addEventListener('resize', positionPanel);
window.addEventListener('scroll', positionPanel, true);
trigger.addEventListener('click', function (e) {
e.stopPropagation();
if (panel.hidden) { openPanel(); } else { closePanel(); }