fix:修导出时钟与切页卡顿

导出与播放共用模拟时钟;换循环、重排播放头、<grok-bot> 重挂和构建产物对齐。
自定义/动画面板留下不重画,角色高度对齐,表情走弹簧。
This commit is contained in:
Edom
2026-08-19 02:01:29 +08:00
parent 1ba126c92b
commit 851f2b8c6c
17 changed files with 179 additions and 84 deletions
+22
View File
@@ -72,6 +72,17 @@
place-items: center;
box-shadow: inset 0 -8px 18px rgba(40, 30, 10, 0.08), 0 12px 28px rgba(0,0,0,.3);
}
.missing {
width: min(100%, 280px);
margin: 12px auto 0;
padding: 22px 18px;
border-radius: 16px;
background: #2a2823;
color: #d8d0c0;
font-size: 13px;
}
.missing strong { display: block; margin-bottom: 8px; color: var(--accent); font-weight: 560; }
.missing a { color: var(--accent); }
.disk-login svg { width: 64px; height: 64px; overflow: visible; color-scheme: light; --bg: var(--disk); --fg: #111; }
.disk-login span {
display: block;
@@ -181,6 +192,12 @@
<span style="display:block;margin-top:8px;font-size:10px;color:#8d877b;text-align:center">登录 sizePx: 64</span>
</div>
</div>
<div class="missing" id="missing-geo" hidden>
<strong>几何未加载</strong>
本仓库不包含 <code>geometry-data.js</code>。把符合
<a href="geometry.schema.md">geometry.schema.md</a>
的数据放到同目录后刷新,即可本地预览。不要提交或再分发从商业应用抽出的造型。
</div>
<div class="modes">
<button id="mode-onboard" aria-pressed="true">登录轮换</button>
<button id="mode-hold" aria-pressed="false">锁定状态</button>
@@ -296,6 +313,10 @@
document.getElementById("mode-hold").setAttribute("aria-pressed", mode === "hold");
}
if (!window.GROK_GEO?.shapes || typeof window.GROK?.create !== "function") {
document.getElementById("missing-geo").hidden = false;
} else {
GROK_META.groups.forEach((group) => {
const h = document.createElement("h2");
h.textContent = group.label;
@@ -387,6 +408,7 @@
document.getElementById("act-spin").onclick = () => bots.forEach((el) => el.spinOnce(1));
document.getElementById("act-bounce").onclick = () => bots.forEach((el) => el.bounceOnce());
document.getElementById("act-burst").onclick = () => bots.forEach((el) => el.burstOnce());
}
</script>
</body>
</html>
+2 -1
View File
@@ -56,7 +56,8 @@
connectedCallback() {
if (this._handle) return;
const root = this.attachShadow({ mode: "open" });
const root = this.shadowRoot || this.attachShadow({ mode: "open" });
root.replaceChildren();
const box = document.createElement("div");
box.setAttribute("part", "disk");
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+18 -3
View File
@@ -276,10 +276,20 @@
this.svg.style.setProperty("--bg", this.eyeColor || EYE_BG);
}
_clock() {
return this.driven ? this.last : performance.now();
}
setState(name, { resetEyes = false } = {}) {
if (!this.playlists[name]) return;
this.state = name;
this.stateAt = performance.now();
this.stateAt = this._clock();
if (this.driven) {
this.trick = null;
this.spinTurn = null;
this.hopAt = -1;
this.wildWide = false;
}
const list = this.playlists[name];
this.eyeIdx = 0;
if (resetEyes) {
@@ -407,6 +417,11 @@
return this.snapshot();
}
setSize(px) {
this.sizePx = px > 0 ? px : null;
this._applyPoseScale();
}
_applyPoseScale() {
const sc = this.loginWrap ? poseScale(this.shapeName) : (this.pose.scale || 1);
this.pose.scale = sc;
@@ -529,7 +544,7 @@
}
_cycleShapeTrick() {
if (this.reduceMotion || this.paused) return;
if (this.reduceMotion || this.paused || this.driven) return;
this.trickCycle = (this.trickCycle + 1) % 5;
this.wildWide = false;
if (this.trickCycle === 0) this._pn(1);
@@ -686,7 +701,7 @@
this.celebrateAt = now + 6200;
}
if (now >= this.trickAt) {
if (!this.driven && now >= this.trickAt) {
if ((V_T.has(this.state) || B_T.has(this.state)) && !this.spinTurn && this.hopAt < 0 && !this.trick) {
const z = Math.random();
if (V_T.has(this.state)) {