@lrplrplrp/dsh-live2d 0.1.1 → 0.1.3
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/assets/model_list.json +2 -2
- package/cordis.patch.yml +2 -2
- package/lib/client.js +110 -76
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/assets/model_list.json
CHANGED
package/cordis.patch.yml
CHANGED
package/lib/client.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
//
|
|
12
12
|
// 移除了原项目的:对话框、小飞机游戏、关闭/关于/GitHub 按钮。
|
|
13
13
|
|
|
14
|
-
window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
14
|
+
window.__ModuleLoader__.load({ id: '@lrplrplrp/dsh-live2d', factory: (require) => {
|
|
15
15
|
var module = { exports: {} }
|
|
16
16
|
var exports = module.exports
|
|
17
17
|
|
|
@@ -27,6 +27,9 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
27
27
|
const POSITION_KEY = 'dsh-live2d.position'
|
|
28
28
|
const ACTIVE_MODEL_KEY = 'dsh-live2d.activeModel'
|
|
29
29
|
|
|
30
|
+
// 容器默认屏幕位置(无本地存档时使用),对应 position:fixed 的 left/top
|
|
31
|
+
const DEFAULT_POSITION = { x: 1240, y: 330 }
|
|
32
|
+
|
|
30
33
|
// 本地文件路由前缀(由 host 端 index.js 注册)
|
|
31
34
|
const LIB_BASE = '/plugins/dsh-live2d/lib/'
|
|
32
35
|
const ASSETS_BASE = '/plugins/dsh-live2d/assets/'
|
|
@@ -69,13 +72,13 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
69
72
|
url: ASSETS_BASE + 'deepseek_l2d/deepseek.model3.json',
|
|
70
73
|
canvasWidth: 300,
|
|
71
74
|
canvasHeight: 400,
|
|
72
|
-
config: { x:
|
|
75
|
+
config: { x: 0, y: 0, scaleX: 1.5, scaleY: 1.5 },
|
|
73
76
|
animations: {
|
|
74
77
|
IDLE: { motion: { group: 'Idle', index: 0 }, loop: false },
|
|
75
|
-
THINKING: { motion: { group: 'Anima', index: 2 }, loop:
|
|
78
|
+
THINKING: { motion: { group: 'Anima', index: 2 }, loop: true },
|
|
76
79
|
THINK_END: { motion: { group: 'Anima', index: 1 }, loop: false },
|
|
77
|
-
WORKING: {
|
|
78
|
-
SPEAKING: { motion: { group: 'Anima', index: 0 }, loop:
|
|
80
|
+
WORKING: { expression: 'puzzled' },
|
|
81
|
+
SPEAKING: { motion: { group: 'Anima', index: 0 }, loop: true },
|
|
79
82
|
SUCCESS: { expression: 'happy' },
|
|
80
83
|
ERROR: { expression: 'unhappy' },
|
|
81
84
|
},
|
|
@@ -204,8 +207,9 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
204
207
|
const LIVE2D_CSS = [
|
|
205
208
|
'#dsh-live2d-container {',
|
|
206
209
|
' position: fixed;',
|
|
207
|
-
'
|
|
208
|
-
' left:
|
|
210
|
+
' top: 330px;',
|
|
211
|
+
' left: 1240px;',
|
|
212
|
+
' bottom: auto;',
|
|
209
213
|
' z-index: 9999;',
|
|
210
214
|
// 容器本身不拦截指针事件,画布区域点击完全穿透到页面,不影响输入;
|
|
211
215
|
// 只有拖拽图标与画布大小手柄单独开启 pointer-events。
|
|
@@ -243,52 +247,48 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
243
247
|
'#dsh-live2d-container:hover .dsh-live2d-label {',
|
|
244
248
|
' opacity: 1;',
|
|
245
249
|
'}',
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
'
|
|
250
|
-
'
|
|
251
|
-
'
|
|
252
|
-
'
|
|
250
|
+
// 控制浮层:固定定位,位置由 JS 动态计算——理想位置是画布右下角,
|
|
251
|
+
// 但会被夹在视口内(画布拖出屏幕时,图标停在离画布右下角最近的屏幕边缘)。
|
|
252
|
+
// 浮层本身不拦截指针(pointer-events:none),只有里面的图标可点。
|
|
253
|
+
'#dsh-live2d-controls {',
|
|
254
|
+
' position: fixed;',
|
|
255
|
+
' z-index: 10000;',
|
|
256
|
+
' display: flex;',
|
|
257
|
+
' align-items: center;',
|
|
258
|
+
' gap: 8px;',
|
|
259
|
+
' pointer-events: none;',
|
|
260
|
+
'}',
|
|
261
|
+
// 画布大小拖拽手柄:常驻右下角浮层,与移动图标并排
|
|
262
|
+
'#dsh-live2d-controls .dsh-live2d-resize {',
|
|
263
|
+
' width: 16px;',
|
|
264
|
+
' height: 16px;',
|
|
253
265
|
' border-right: 2px solid rgba(96,165,250,0.9);',
|
|
254
266
|
' border-bottom: 2px solid rgba(96,165,250,0.9);',
|
|
255
267
|
' cursor: nwse-resize;',
|
|
256
|
-
' opacity: 0;',
|
|
257
|
-
' transition: opacity 0.2s;',
|
|
268
|
+
' opacity: 0.7;',
|
|
258
269
|
' pointer-events: auto;',
|
|
259
|
-
'
|
|
260
|
-
'}',
|
|
261
|
-
'#dsh-live2d-container.hovering .dsh-live2d-resize {',
|
|
262
|
-
' opacity: 0.9;',
|
|
270
|
+
' flex: none;',
|
|
263
271
|
'}',
|
|
264
|
-
//
|
|
265
|
-
'#dsh-live2d-
|
|
266
|
-
'
|
|
267
|
-
'
|
|
268
|
-
' bottom: 9px;',
|
|
269
|
-
' width: 22px;',
|
|
270
|
-
' height: 22px;',
|
|
272
|
+
// 拖拽移动图标:常驻右下角浮层
|
|
273
|
+
'#dsh-live2d-controls .dsh-live2d-drag {',
|
|
274
|
+
' width: 26px;',
|
|
275
|
+
' height: 26px;',
|
|
271
276
|
' display: flex;',
|
|
272
277
|
' align-items: center;',
|
|
273
278
|
' justify-content: center;',
|
|
274
279
|
' border-radius: 6px;',
|
|
275
|
-
' background: rgba(31,41,55,0.
|
|
276
|
-
' color: rgba(226,232,240,0.
|
|
277
|
-
' font-size:
|
|
280
|
+
' background: rgba(31,41,55,0.75);',
|
|
281
|
+
' color: rgba(226,232,240,0.95);',
|
|
282
|
+
' font-size: 15px;',
|
|
278
283
|
' line-height: 1;',
|
|
279
284
|
' cursor: grab;',
|
|
280
285
|
' user-select: none;',
|
|
281
286
|
' pointer-events: auto;',
|
|
282
|
-
' opacity: 0;',
|
|
283
|
-
'
|
|
284
|
-
' z-index: 2;',
|
|
285
|
-
'}',
|
|
286
|
-
'#dsh-live2d-container.hovering .dsh-live2d-drag {',
|
|
287
|
-
' opacity: 0.9;',
|
|
287
|
+
' opacity: 0.85;',
|
|
288
|
+
' flex: none;',
|
|
288
289
|
'}',
|
|
289
|
-
'#dsh-live2d-
|
|
290
|
+
'#dsh-live2d-controls .dsh-live2d-drag:active {',
|
|
290
291
|
' cursor: grabbing;',
|
|
291
|
-
' opacity: 0.9;',
|
|
292
292
|
'}',
|
|
293
293
|
].join('\n')
|
|
294
294
|
|
|
@@ -691,17 +691,38 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
691
691
|
* 会优先满足 bottom,拖动看起来"完全没反应"。
|
|
692
692
|
*/
|
|
693
693
|
function place(containerEl, x, y) {
|
|
694
|
-
//
|
|
695
|
-
//
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
const maxY = Math.max(0, window.innerHeight - rect.height)
|
|
699
|
-
containerEl.style.left = Math.min(Math.max(x, 0), maxX) + 'px'
|
|
700
|
-
containerEl.style.top = Math.min(Math.max(y, 0), maxY) + 'px'
|
|
694
|
+
// 画布可自由定位(允许拖出屏幕),仅写入 left/top;bottom 必须置 auto,
|
|
695
|
+
// 否则 left/top 与 bottom 同时生效时浏览器优先满足 bottom,拖动无反应。
|
|
696
|
+
containerEl.style.left = x + 'px'
|
|
697
|
+
containerEl.style.top = y + 'px'
|
|
701
698
|
containerEl.style.bottom = 'auto'
|
|
702
699
|
}
|
|
703
700
|
|
|
704
|
-
|
|
701
|
+
// 控制浮层跟随画布右下角:clamp=true 时被夹在视口内(画布在屏幕内时图标贴
|
|
702
|
+
// 画布右下角;画布拖出屏幕时图标停在最近屏幕边缘);clamp=false 时不夹边,
|
|
703
|
+
// 用于拖动画布大小手柄的过程中——否则手柄会被夹在视口底边,鼠标越过后即
|
|
704
|
+
// 收不到 pointermove,表现为"向下拖不动"。
|
|
705
|
+
function updateControls(containerEl, controlsEl, clamp = true) {
|
|
706
|
+
if (!containerEl || !controlsEl) return
|
|
707
|
+
const cr = containerEl.getBoundingClientRect()
|
|
708
|
+
const cs = controlsEl.getBoundingClientRect()
|
|
709
|
+
const w = cs.width || 60
|
|
710
|
+
const h = cs.height || 34
|
|
711
|
+
const OFFSET = 4 // 图标相对画布右下角内缩一点
|
|
712
|
+
const MARGIN = 4 // 离屏幕边缘的最小间距
|
|
713
|
+
let x = cr.right - w - OFFSET
|
|
714
|
+
let y = cr.bottom - h - OFFSET
|
|
715
|
+
if (clamp) {
|
|
716
|
+
x = Math.min(Math.max(x, MARGIN), window.innerWidth - w - MARGIN)
|
|
717
|
+
y = Math.min(Math.max(y, MARGIN), window.innerHeight - h - MARGIN)
|
|
718
|
+
}
|
|
719
|
+
controlsEl.style.left = x + 'px'
|
|
720
|
+
controlsEl.style.top = y + 'px'
|
|
721
|
+
controlsEl.style.right = 'auto'
|
|
722
|
+
controlsEl.style.bottom = 'auto'
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function setupDrag(handleEl, containerEl, controlsEl) {
|
|
705
726
|
let pointerId = null
|
|
706
727
|
let startX = 0
|
|
707
728
|
let startY = 0
|
|
@@ -715,6 +736,9 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
715
736
|
const saved = getPosition()
|
|
716
737
|
if (saved && Number.isFinite(saved.x) && Number.isFinite(saved.y)) {
|
|
717
738
|
place(containerEl, saved.x, saved.y)
|
|
739
|
+
} else {
|
|
740
|
+
// 无本地存档时使用默认位置
|
|
741
|
+
place(containerEl, DEFAULT_POSITION.x, DEFAULT_POSITION.y)
|
|
718
742
|
}
|
|
719
743
|
|
|
720
744
|
const finish = () => {
|
|
@@ -756,6 +780,7 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
756
780
|
curX = origX + (e.clientX - startX)
|
|
757
781
|
curY = origY + (e.clientY - startY)
|
|
758
782
|
place(containerEl, curX, curY)
|
|
783
|
+
updateControls(containerEl, controlsEl)
|
|
759
784
|
e.preventDefault()
|
|
760
785
|
}
|
|
761
786
|
|
|
@@ -855,6 +880,7 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
855
880
|
function Live2DWidget() {
|
|
856
881
|
const containerRef = useRef(null)
|
|
857
882
|
const dragHandleRef = useRef(null)
|
|
883
|
+
const controlsRef = useRef(null)
|
|
858
884
|
const engineRef = useRef(null)
|
|
859
885
|
const cleanupDragRef = useRef(null)
|
|
860
886
|
const lastStateRef = useRef(DSHState.IDLE)
|
|
@@ -887,28 +913,19 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
887
913
|
engine.init(containerRef.current).then((ok) => {
|
|
888
914
|
if (ok) {
|
|
889
915
|
engine.playAnimation('IDLE')
|
|
916
|
+
updateControls(containerRef.current, controlsRef.current)
|
|
890
917
|
}
|
|
891
918
|
})
|
|
892
919
|
|
|
893
|
-
cleanupDragRef.current = setupDrag(dragHandleRef.current, containerRef.current)
|
|
920
|
+
cleanupDragRef.current = setupDrag(dragHandleRef.current, containerRef.current, controlsRef.current)
|
|
894
921
|
|
|
895
|
-
//
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
const onMouseMove = (e) => {
|
|
899
|
-
const el = containerRef.current
|
|
900
|
-
if (!el) return
|
|
901
|
-
const rect = el.getBoundingClientRect()
|
|
902
|
-
const inside = e.clientX >= rect.left && e.clientX <= rect.right &&
|
|
903
|
-
e.clientY >= rect.top && e.clientY <= rect.bottom
|
|
904
|
-
if (inside) el.classList.add('hovering')
|
|
905
|
-
else el.classList.remove('hovering')
|
|
906
|
-
}
|
|
907
|
-
window.addEventListener('mousemove', onMouseMove)
|
|
922
|
+
// 窗口尺寸变化时把图标夹回视口内(画布可能因此相对移出屏幕)
|
|
923
|
+
const onResize = () => updateControls(containerRef.current, controlsRef.current)
|
|
924
|
+
window.addEventListener('resize', onResize)
|
|
908
925
|
|
|
909
926
|
return () => {
|
|
910
927
|
cleanupDragRef.current?.()
|
|
911
|
-
window.removeEventListener('
|
|
928
|
+
window.removeEventListener('resize', onResize)
|
|
912
929
|
engine.destroy()
|
|
913
930
|
}
|
|
914
931
|
}, [])
|
|
@@ -941,6 +958,7 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
941
958
|
if (!engine || !engine.ready) return
|
|
942
959
|
const factor = e.deltaY < 0 ? 1.08 : 1 / 1.08
|
|
943
960
|
engine.zoomBy(factor)
|
|
961
|
+
updateControls(containerRef.current, controlsRef.current)
|
|
944
962
|
}, [])
|
|
945
963
|
|
|
946
964
|
// 画布大小手柄:拖动右下角改变 canvasWidth/canvasHeight
|
|
@@ -953,20 +971,27 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
953
971
|
|
|
954
972
|
const startX = e.clientX
|
|
955
973
|
const startY = e.clientY
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
974
|
+
// 起点尺寸必须取 canvas 自身(CSS 像素),不能取 container 的
|
|
975
|
+
// getBoundingClientRect():container 是 pointer-events:none 且内含一个
|
|
976
|
+
// position:fixed 的控制浮层,某些布局下其 rect 高度会塌缩为 0 / 与画布
|
|
977
|
+
// 不一致,导致 startH 错乱、向下拖时 h 计算异常、画布大小"拖不动"。
|
|
978
|
+
const canvasEl = engine.canvas
|
|
979
|
+
const startW = canvasEl ? canvasEl.offsetWidth : containerEl.getBoundingClientRect().width
|
|
980
|
+
const startH = canvasEl ? canvasEl.offsetHeight : containerEl.getBoundingClientRect().height
|
|
959
981
|
const pointerId = e.pointerId
|
|
960
982
|
|
|
961
|
-
try { e.
|
|
983
|
+
try { e.currentTarget.setPointerCapture(pointerId) } catch {}
|
|
962
984
|
|
|
963
985
|
const move = (ev) => {
|
|
964
986
|
if (ev.pointerId !== pointerId) return
|
|
965
987
|
const dw = ev.clientX - startX
|
|
966
988
|
const dh = ev.clientY - startY
|
|
989
|
+
// 拖动过程中不夹边(clamp=false):手柄自由跟随画布右下角,向下拖
|
|
990
|
+
// 时不会被夹在视口底边、鼠标越过后收不到 pointermove 而"拖不动"。
|
|
967
991
|
const w = Math.min(800, Math.max(100, startW + dw))
|
|
968
992
|
const h = Math.min(800, Math.max(100, startH + dh))
|
|
969
993
|
engine.setCanvasSize(w, h)
|
|
994
|
+
updateControls(containerEl, controlsRef.current, false)
|
|
970
995
|
}
|
|
971
996
|
const up = (ev) => {
|
|
972
997
|
if (ev.pointerId !== pointerId) return
|
|
@@ -974,6 +999,8 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
974
999
|
window.removeEventListener('pointermove', move)
|
|
975
1000
|
window.removeEventListener('pointerup', up)
|
|
976
1001
|
window.removeEventListener('pointercancel', up)
|
|
1002
|
+
// 松手后把图标夹回视口内(静止状态始终留在网页可见区域)。
|
|
1003
|
+
updateControls(containerEl, controlsRef.current, true)
|
|
977
1004
|
}
|
|
978
1005
|
window.addEventListener('pointermove', move)
|
|
979
1006
|
window.addEventListener('pointerup', up)
|
|
@@ -985,18 +1012,25 @@ window.__ModuleLoader__.load({ id: 'dsh-live2d', factory: (require) => {
|
|
|
985
1012
|
id: 'dsh-live2d-container',
|
|
986
1013
|
onWheel: onWheel,
|
|
987
1014
|
},
|
|
988
|
-
//
|
|
989
|
-
|
|
990
|
-
ref: dragHandleRef,
|
|
991
|
-
className: 'dsh-live2d-drag',
|
|
992
|
-
title: '拖动移动看板娘;鼠标滚轮缩放模型大小',
|
|
993
|
-
}, '✥'),
|
|
994
|
-
// 画布大小手柄:仅鼠标悬停画布(容器)时显示
|
|
1015
|
+
// 控制浮层:固定钉在视口右下角,独立于画布。画布可以拖出屏幕,
|
|
1016
|
+
// 但这两个图标始终留在页面内可见可点。
|
|
995
1017
|
h('div', {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1018
|
+
ref: controlsRef,
|
|
1019
|
+
id: 'dsh-live2d-controls',
|
|
1020
|
+
},
|
|
1021
|
+
// 画布大小手柄
|
|
1022
|
+
h('div', {
|
|
1023
|
+
className: 'dsh-live2d-resize',
|
|
1024
|
+
title: '拖动改变画布大小',
|
|
1025
|
+
onPointerDown: onResizePointerDown,
|
|
1026
|
+
}),
|
|
1027
|
+
// 拖拽移动图标:只有拖动它才能移动整个看板娘
|
|
1028
|
+
h('div', {
|
|
1029
|
+
ref: dragHandleRef,
|
|
1030
|
+
className: 'dsh-live2d-drag',
|
|
1031
|
+
title: '拖动移动看板娘;鼠标滚轮缩放模型大小',
|
|
1032
|
+
}, '✥'),
|
|
1033
|
+
),
|
|
1000
1034
|
)
|
|
1001
1035
|
}
|
|
1002
1036
|
|
package/lib/index.js
CHANGED
|
@@ -37,7 +37,7 @@ const PLUGIN_ROOT = resolvedDir ? join(resolvedDir, '..') : null
|
|
|
37
37
|
const LIB_DIR = PLUGIN_ROOT ? join(PLUGIN_ROOT, 'lib') : null
|
|
38
38
|
const ASSETS_DIR = PLUGIN_ROOT ? join(PLUGIN_ROOT, 'assets') : null
|
|
39
39
|
|
|
40
|
-
export const name = 'dsh-live2d'
|
|
40
|
+
export const name = '@lrplrplrp/dsh-live2d'
|
|
41
41
|
|
|
42
42
|
const STATE_ENDPOINT = '/plugins/dsh-live2d/state'
|
|
43
43
|
const CONFIG_ENDPOINT = '/plugins/dsh-live2d/config'
|