optimize: community polish — crossfade, position lock, effort sync

- 双图层交叉淡化人像过渡:备用层加载完成才淡入,无白闪;拖动 120ms 快速过渡、落定 340ms 慢速过渡,prefers-reduced-motion 直切
- 滑块位置固定:原生模型座位按钮级 180px 固定足迹(选择器限定 button,避免误伤 label/effort 子元素)+ 滑块 flex 固定尺寸 + 交互期 rAF 漂移补偿
- 原生推理等级与滑块实时同步:拖动预览乐观回写共享 directory store,松手提交、失败/Esc/取消自动回滚
- 滑动更丝滑:移除图片序列模式下对隐藏 video 的每帧 seek,24 张锚点预加载 + decoding=async,交叉淡化走合成器动画
- 滑块自定义光标:liang-cursor.cur(热点居中 16,16),加载失败回退 ew-resize
- 版本升至 0.2.0,随包新增 CHANGELOG.md 优化说明
This commit is contained in:
jiaererw
2026-08-18 16:32:25 +08:00
parent 08f60e8ef3
commit 9c06acf15b
9 changed files with 1164 additions and 714 deletions

View File

@@ -41,7 +41,24 @@ body[data-liang-skin="on"] .liang-skin-backdrop {
.liang-skin-backdrop[data-media="sequence"] .liang-skin-sequence-frame {
display: block;
/* Crossfade layers: inactive sits transparent and slightly enlarged, the
active one eases back to a calm 1:1. Dragging swaps fast so the preview
stays glued to the pointer; settling swaps slow for a gentle landing. */
opacity: 0;
transform: translateY(-50%) scale(1.018);
transition:
opacity 120ms ease-out,
transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
will-change: opacity, transform;
}
.liang-skin-backdrop[data-media="sequence"] .liang-skin-sequence-frame.is-active {
opacity: var(--liang-portrait-opacity, 0.82);
transform: translateY(-50%) scale(1);
}
.liang-skin-backdrop[data-crossfade="slow"] .liang-skin-sequence-frame {
transition-duration: 340ms, 520ms;
}
.liang-skin-backdrop[data-media="video"] .liang-skin-sequence-frame,
@@ -337,7 +354,14 @@ body[data-liang-skin="on"]:is(
--liang-control-rail: var(--dsw-alias-border-l3, rgb(0 0 0 / 16%));
position: relative;
display: flex;
/* Fixed footprint: the native model seat to the right changes its label
width when the reasoning effort changes, which reflows the trailing flex
row. Pin this control's own size so it never contributes to that shift
(absolute position is additionally locked during interaction in JS). */
flex: 0 0 124px;
width: 124px;
min-width: 124px;
max-width: 124px;
height: 28px;
align-items: center;
margin: 0 3px;
@@ -349,6 +373,19 @@ body[data-liang-skin="on"] .liang-effort-control {
--liang-control-rail: color-mix(in srgb, var(--liang-secondary) 28%, transparent);
}
/* The native model seat (composer input.model) widens with the effort label
text; give it a stable footprint under the Liang skin so switching effort
never reflows the slider out of position. The label ellipsizes instead.
Button-scoped on purpose: the inner label/effort spans also contain this
class substring and must never be sized (sizing them pushed the effort text
out of the button, splitting the model+effort pair apart). */
body[data-liang-skin="on"] button[class*="_7KE1Ra_trigger"] {
box-sizing: border-box;
width: 180px;
min-width: 180px;
max-width: 180px;
}
.liang-effort-control__ticks {
position: absolute;
z-index: 0;
@@ -415,7 +452,9 @@ body[data-liang-skin="on"] .liang-effort-control {
width: calc(100% - 7px);
height: 28px;
margin: 0 3.5px;
cursor: ew-resize;
/* Branded pointer (centered hotspot baked into the .cur); fall back to the
native resize cursor if the asset fails to load. */
cursor: url("/plugins/dsh-client-liang-intensity-skin/assets/liang-cursor.cur") 16 16, ew-resize;
appearance: none;
background: transparent;
touch-action: pan-y;
@@ -620,7 +659,10 @@ body[data-liang-skin="on"] .liang-effort-control__range::-webkit-slider-thumb {
@media (max-width: 760px) {
.liang-effort-control {
flex-basis: 92px;
width: 92px;
min-width: 92px;
max-width: 92px;
}
.liang-skin-backdrop video,
@@ -636,6 +678,7 @@ body[data-liang-skin="on"] .liang-effort-control__range::-webkit-slider-thumb {
.liang-skin-backdrop,
.liang-skin-backdrop video,
.liang-skin-backdrop img,
.liang-skin-backdrop .liang-skin-sequence-frame,
body[data-liang-skin="on"] button,
body[data-liang-skin="on"] input,
body[data-liang-skin="on"] textarea {