dsh-piano 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/client.js +59 -2
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 效果
|
|
6
6
|
|
|
7
|
-
- 左下角一枚 🎹
|
|
7
|
+
- 左下角一枚 🎹 按钮(默认收起,不打扰正常使用)。**按钮可拖动**:按住移动超过 6px 即判定为拖(不会误开面板),松手后位置存 `localStorage`,下次进来仍在原处;400ms 内的 `click` 才算"点开",拖动不会吞掉下一次真正点击。
|
|
8
8
|
- 点开是底部居中的浮动键盘面板:音量滑块、八度移调(− / +)、收起。
|
|
9
9
|
- 键盘含白键 + 黑键;按住后滑动,指到哪个键就响哪个音(按住拖动 = 刮奏)。
|
|
10
10
|
- 设置(音量、起始八度)持久化到 `localStorage`,刷新后保留。
|
package/lib/client.js
CHANGED
|
@@ -20,7 +20,7 @@ window.__ModuleLoader__.load({
|
|
|
20
20
|
|
|
21
21
|
//#region styles
|
|
22
22
|
const CSS = [
|
|
23
|
-
".dshp_btn{box-sizing:border-box;position:fixed;left:16px;bottom:16px;z-index:2147483000;height:44px;min-width:44px;padding:0 14px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border:none;border-radius:22px;background:var(--dsw-alias-bg-elevated,#1f2430);color:var(--dsw-alias-label-primary,#e6e8ee);box-shadow:0 6px 24px rgba(0,0,0,.35);cursor:pointer;user-select:none;font-size:16px;line-height:20px}",
|
|
23
|
+
".dshp_btn{box-sizing:border-box;position:fixed;left:16px;bottom:16px;z-index:2147483000;height:44px;min-width:44px;padding:0 14px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border:none;border-radius:22px;background:var(--dsw-alias-bg-elevated,#1f2430);color:var(--dsw-alias-label-primary,#e6e8ee);box-shadow:0 6px 24px rgba(0,0,0,.35);cursor:pointer;user-select:none;touch-action:none;will-change:transform;font-size:16px;line-height:20px}",
|
|
24
24
|
".dshp_btn:hover{background:var(--dsw-alias-interactive-bg-hover,#2a3140)}",
|
|
25
25
|
".dshp_panel{box-sizing:border-box;position:fixed;left:50%;bottom:16px;transform:translateX(-50%);z-index:2147483000;width:min(94vw,760px);display:flex;flex-direction:column;gap:8px;padding:12px;border-radius:14px;background:var(--dsw-alias-bg-elevated,#1f2430);color:var(--dsw-alias-label-primary,#e6e8ee);box-shadow:0 12px 40px rgba(0,0,0,.45);user-select:none}",
|
|
26
26
|
".dshp_head{display:flex;align-items:center;gap:12px}",
|
|
@@ -321,8 +321,65 @@ window.__ModuleLoader__.load({
|
|
|
321
321
|
setOpen(true);
|
|
322
322
|
}, []);
|
|
323
323
|
|
|
324
|
+
// —— 收起态按钮**可拖动**:移动超过 6px 判定为「拖」(不触发开面板),
|
|
325
|
+
// 松手后位置存 localStorage,下次进来仍在原处。 ——
|
|
326
|
+
const [btnPos, setBtnPos] = useState(() => {
|
|
327
|
+
try { return JSON.parse(localStorage.getItem("dsh-piano:btnPos") || "null"); } catch { return null; }
|
|
328
|
+
});
|
|
329
|
+
const btnPosRef = useRef(btnPos);
|
|
330
|
+
btnPosRef.current = btnPos;
|
|
331
|
+
const dragRef = useRef(null);
|
|
332
|
+
const draggedRef = useRef(false);
|
|
333
|
+
const dragClearRef = useRef(0);
|
|
334
|
+
|
|
335
|
+
const onBtnDown = (e) => {
|
|
336
|
+
if (e.pointerType === "mouse" && e.button !== 0) return;
|
|
337
|
+
draggedRef.current = false;
|
|
338
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
339
|
+
dragRef.current = { x: e.clientX, y: e.clientY, left: r.left, top: r.top, moved: false };
|
|
340
|
+
try { e.currentTarget.setPointerCapture(e.pointerId); } catch {}
|
|
341
|
+
};
|
|
342
|
+
const onBtnMove = (e) => {
|
|
343
|
+
const d = dragRef.current;
|
|
344
|
+
if (!d) return;
|
|
345
|
+
const dx = e.clientX - d.x;
|
|
346
|
+
const dy = e.clientY - d.y;
|
|
347
|
+
if (!d.moved && Math.abs(dx) + Math.abs(dy) > 6) d.moved = true;
|
|
348
|
+
if (!d.moved) return;
|
|
349
|
+
const left = Math.max(4, Math.min(window.innerWidth - 70, d.left + dx));
|
|
350
|
+
const top = Math.max(4, Math.min(window.innerHeight - 50, d.top + dy));
|
|
351
|
+
btnPosRef.current = { left, top };
|
|
352
|
+
setBtnPos({ left, top });
|
|
353
|
+
};
|
|
354
|
+
const onBtnUp = (e) => {
|
|
355
|
+
const d = dragRef.current;
|
|
356
|
+
dragRef.current = null;
|
|
357
|
+
try { e.currentTarget.releasePointerCapture(e.pointerId); } catch {}
|
|
358
|
+
if (!d || !d.moved) return;
|
|
359
|
+
draggedRef.current = true;
|
|
360
|
+
const pos = btnPosRef.current;
|
|
361
|
+
if (pos) { try { localStorage.setItem("dsh-piano:btnPos", JSON.stringify(pos)); } catch {} }
|
|
362
|
+
// 拖完不一定紧跟 click(拖到按钮外松手就点不出来)→ 400ms 后自动清标志,
|
|
363
|
+
// 免得把**下一次**真正的点击吞掉
|
|
364
|
+
if (dragClearRef.current) window.clearTimeout(dragClearRef.current);
|
|
365
|
+
dragClearRef.current = window.setTimeout(() => { draggedRef.current = false; }, 400);
|
|
366
|
+
};
|
|
367
|
+
const onBtnClick = () => {
|
|
368
|
+
if (draggedRef.current) { draggedRef.current = false; return; } // 刚才那一下是拖,不是点
|
|
369
|
+
onOpen();
|
|
370
|
+
};
|
|
371
|
+
|
|
324
372
|
if (!open) {
|
|
325
|
-
return h("button", {
|
|
373
|
+
return h("button", {
|
|
374
|
+
className: "dshp_btn",
|
|
375
|
+
title: "滑动钢琴(可拖动,点开面板)",
|
|
376
|
+
onClick: onBtnClick,
|
|
377
|
+
onPointerDown: onBtnDown,
|
|
378
|
+
onPointerMove: onBtnMove,
|
|
379
|
+
onPointerUp: onBtnUp,
|
|
380
|
+
onPointerCancel: onBtnUp,
|
|
381
|
+
style: btnPos ? { left: btnPos.left + "px", top: btnPos.top + "px", bottom: "auto" } : undefined
|
|
382
|
+
}, "🎹 钢琴");
|
|
326
383
|
}
|
|
327
384
|
|
|
328
385
|
return h("div", { className: "dshp_panel" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-piano",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "滑动钢琴:在 DSH 界面里弹一条钢琴键盘,鼠标/触控板滑过去像刮奏(glissando)一样出声。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,11 +49,13 @@
|
|
|
49
49
|
},
|
|
50
50
|
"compatibility": {
|
|
51
51
|
"dshReleases": {
|
|
52
|
-
"0.2.0-rc.2": "compatible"
|
|
52
|
+
"0.2.0-rc.2": "compatible",
|
|
53
|
+
"0.2.1-rc.2": "compatible",
|
|
54
|
+
"0.2.2-rc.1": "compatible"
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
},
|
|
56
58
|
"scripts": {
|
|
57
59
|
"test": "node test/bundle-check.mjs"
|
|
58
60
|
}
|
|
59
|
-
}
|
|
61
|
+
}
|