Skip to content

1.1.2 —— 提词器毛玻璃与文字描边、背景贴合重构

Choose a tag to compare

@Dyse-Sofqi Dyse-Sofqi released this 03 Oct 22:51

1.1.2 (2026-10-04)

新增功能

  • 提词器背景新增「毛玻璃」效果:面板背景以 backdrop-filter 模糊并提饱和(saturate(1.4),与高亮索引卡片悬停时的观感一致)其覆盖的底层编辑器内容,配合较低的「背景透明度」即得桌面歌词式的毛玻璃观感。设置页「提词器」页签、「背景透明度」之下新增两项:「毛玻璃效果」开关(默认开)与「毛玻璃模糊强度」滑条(0–40px,默认 16px,带「重置为初始值」按钮)。实现沿用提词器「CSS 变量驱动 + 类开关」惯例:开关走根元素 is-glass 类、模糊半径走 --tp-glass-blur 变量,设置变更经 applySettingsToAll() 实时套用到所有实例;.glimpse-tp-body 的过渡列表同步补上 backdrop-filter,开关切换有 0.2s 过渡。「隐藏背景」激活时毛玻璃自动撤除 —— 否则全透明背景之下会留下一块没有边框、没有底色的纯模糊矩形(模糊的是背后内容,视觉上像一块脏玻璃),两种状态互斥才各自成立。旧 data.json 缺失的新字段经 Object.assign 默认值合并自动回退,无需迁移
  • 提词器文字新增「描边」(桌面歌词风格,复杂背景上更易读,始终生效——与只在隐藏背景时出现的投影不同):设置页新增「文字描边」折叠分组(与「文字阴影」同款折叠交互:setHeading() 分组头 + chevron),内含四项,默认值即当前调优结果:开启、外侧描边、1px、白色
    • 描边方式二选一:
      • 字形描边(-webkit-text-stroke + paint-order: stroke fill):描边中心线与字形边缘重合,paint-order 把描边垫在渐变/字体颜色填充之下——内半侧被填充盖住、只露外半侧,笔画粗细不受影响。HTML 文本的 paint-order 需 Chromium 123+(当前 Obsidian 内核满足),旧内核下退化为笔画略粗可接受。-webkit-text-stroke 可继承,逐字渐变的 .glimpse-grad-char 字符 span 无需单独声明
      • 外侧描边(SVG feMorphology 膨胀滤镜):滤镜链为「feMorphology(dilate) 膨胀文字 alpha 轮廓 → feFlood 染描边色 → feComposite(in) 裁出彩色轮廓 → feMerge 垫回 SourceGraphic 之下」,作用于渲染后的像素,渐变、逐字渐变、半透明填充全部兼容,且完整线宽外露(字形描边只露一半)。滤镜定义由 TeleprompterManager 构造时注入 document.body(零尺寸隐藏 <svg>,全文档共享单个定义——线宽/颜色是全局设置),插件卸载时整棵摘除;feMorphology 的 radius 与 feFlood 的 flood-color 是 SVG 属性而非 CSS,由 applySettingsToAll() 用 JS 先同步滤镜参数、再切窗口类,避免引用到旧值;滤镜区域外扩 50%(默认 10% 余量在矮内容上会把膨胀结果裁掉)。已知取舍:膨胀核为矩形,线宽拉大后斜向笔画拐角略显方正
    • 线宽滑条 0–12px:字形描边可见约为一半、外侧描边为完整线宽(设置描述已注明);颜色为色板,「清除」恢复默认白——null 的语义收敛为「默认描边色」,兜底色统一走 DEFAULT_STROKE_COLOR_VALUE 常量(applySettings、滤镜 flood-color、CSS 变量兜底三处对齐,避免「重置后变黑」的不一致)
    • 与投影叠加:filter 是单属性、两条规则会整体互相覆盖,「外侧描边 + 隐藏背景 + 投影开」专门合并为一条 url(#…) drop-shadow(…) 规则;投影关闭、占位文本等情形各有回退(占位文本保持轻量不加滤镜,:not(.is-placeholder) 保证不与轻量规则争特异性)
  • 音乐下载新增「平台 Cookie 自动续期回写」(Cookie JAR)(上一迭代完成、随本版归档发布):手工从浏览器 F12 复制粘贴的平台 Cookie 是静态字符串——网易云 MUSIC_U / QQ qm_keyst 均为 HttpOnly、读不到 document.cookie,平台在校验接口里回吐续期后的新凭证时本地永远拿旧的,过段时间就「Cookie 过期」只能重新复制。现由独立的 cookieJar.ts 解析响应头 Set-Cookie,经域名白名单 + 平台 Cookie 名白名单双重把关(防止把 A 平台凭证写到 B 平台、防止埋点/AB 垃圾 Cookie 堆进 data.json)后与原值逐项合并落盘;删除语义不落地(Max-Age=0 / 已过期一律忽略,平台一次清理动作不会抹掉用户粘贴的凭证);续期时间戳存 platformCookiesUpdatedAt。设置页各平台 Cookie 行的状态徽标升级为实时计算:「已配置(N 字符)」,发生续期后追加「已自动续期 MM-DD HH:mm」;手动重新粘贴或清空会使旧续期标记失效。请求侧同步收紧:平台标识等传输标记只用于定位平台、出站请求头前一律摘除
  • 字体选择模态框「取消/确定」前置到标题行:模态框较小,按钮放底部要滚到底才能点到。现合并进标题行——标题居左、取消/确定居右(CTA 高亮),打开弹窗即见,列表再长也无需滚动;底部原操作区移除后内容区还省出一行高度。确认/关闭逻辑与 Esc 取消行为不变

问题修复

  • 修复「提词器背景远宽于内容(宽度与内容失配)」:典型表现为背景横贯整个视口、正文只有一行居中短句,两侧大片空白。排查确认窗口并未锁定宽度(widthLocked: false),根因有二:其一,宽度适配的唯一触发点是「异步 Markdown 渲染完成回调」——回调因渲染竞态(renderSeq 旧渲染被新渲染覆盖)、渲染挂起或异常而未执行时,宽度就永久停留在旧值,且整条链路上没有任何自愈机制;其二,自然宽度测量把工具栏按钮克隆进探针一起量,而克隆出的按钮是纵向堆叠的块级盒,量出的既不是真实工具栏宽度(flex 单行约 530px),也让工具栏参与撑宽窗口。本次重构为「CSS 原生贴合 + 多重再适配触发」,测量正确与否都不再影响可见结果:
    • 可见面板 width: fit-content 直接包住内容:背景面板自己贴合正文(上限 max-width: 100% 钳到根宽、长文本照常换行;min-width: 240px 与根一致防短行难抓取),即使宽度状态因异步异常失配,可见背景也不留大片空白;宽度锁定(is-width-locked)与拖宽进行中(is-resizing)铺满根宽——用户所选宽度生效、拖到哪面板就多宽,保留拖宽的即时反馈
    • 根窗口改为 pointer-events: none,仅可见的面板/工具栏/拖拽把手打回 auto:失配变宽的透明区域不再拦截背后编辑器的点击;拖拽/滚轮经子元素冒泡到根监听器不受影响,:hover 悬停链经子元素命中祖先(工具栏悬停显示、锁定态悬停显示均正常),模式菜单的 mouseleave 关闭同样正常
    • 拖宽把手从根移到面板(body)上:始终贴着可见面板的右缘,而不是可能失配的根窗口边缘;拖宽期间 is-resizing 让面板临时铺满根宽以跟随鼠标
    • 测量只测内容:工具栏不再参与宽度计算,改为 flex-wrap: wrap + max-width: 100% 自动换行收纳(居中排布、行距沿用 gap),窗口比工具栏窄时悬停工具栏折成多行而不是把窗口撑宽
    • 再适配多重触发:渲染完成回调之外新增三道兜底——① 内容区 ResizeObserver(捕捉字体迟载、主题切换、逐字渐变重包、异步迟到写入等事后盒子变化);② 视口 resize 监听(可用宽度变化后钳制结果随之更新);③ 每秒一次周期再同步(任何漏触发导致的失配 1s 内自愈)。配两道防闪烁护栏:renderSettled 标志——异步渲染进行中跳过适配(contentEl.empty() 后逐帧量到残缺内容会让宽度来回跳);is-resizing 期间一律让路(拖宽直接写根宽,再适配会把宽度抢回去)
    • 验证:真实失配场景(状态宽 1392px vs 内容约 900px @ 32px 字号)重载后即收敛;背景隐藏/穿透锁定/占位文本/逐字渐变各组合下的样式回归逐一核对(占位轻量规则与外描边滤镜规则的特异性关系、:hover 链、穿透锁定态按钮显隐均保持原行为)