@mumulinya167/ccm-pet-assets 2.0.0

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.
Files changed (178) hide show
  1. package/README.md +4 -0
  2. package/assets/calico/calico-collapsing.apng +0 -0
  3. package/assets/calico/calico-dozing.apng +0 -0
  4. package/assets/calico/calico-error.apng +0 -0
  5. package/assets/calico/calico-happy.apng +0 -0
  6. package/assets/calico/calico-idle-follow.svg +324 -0
  7. package/assets/calico/calico-idle.apng +0 -0
  8. package/assets/calico/calico-mini-alert.apng +0 -0
  9. package/assets/calico/calico-mini-crabwalk.apng +0 -0
  10. package/assets/calico/calico-mini-enter.apng +0 -0
  11. package/assets/calico/calico-mini-happy.apng +0 -0
  12. package/assets/calico/calico-mini-idle.apng +0 -0
  13. package/assets/calico/calico-mini-peek.apng +0 -0
  14. package/assets/calico/calico-mini-sleep.apng +0 -0
  15. package/assets/calico/calico-notification.apng +0 -0
  16. package/assets/calico/calico-react-drag.apng +0 -0
  17. package/assets/calico/calico-react-left.apng +0 -0
  18. package/assets/calico/calico-react-poke.apng +0 -0
  19. package/assets/calico/calico-sleeping.apng +0 -0
  20. package/assets/calico/calico-thinking.apng +0 -0
  21. package/assets/calico/calico-waking.apng +0 -0
  22. package/assets/calico/calico-working-building.apng +0 -0
  23. package/assets/calico/calico-working-carrying.apng +0 -0
  24. package/assets/calico/calico-working-conducting.apng +0 -0
  25. package/assets/calico/calico-working-juggling.apng +0 -0
  26. package/assets/calico/calico-working-sweeping.apng +0 -0
  27. package/assets/calico/calico-working-typing.apng +0 -0
  28. package/assets/calico/calico-yawning.apng +0 -0
  29. package/assets/calico.svg +324 -0
  30. package/assets/clawd/LICENSE +22 -0
  31. package/assets/clawd/clawd-about-hero.svg +202 -0
  32. package/assets/clawd/clawd-collapse-sleep.svg +247 -0
  33. package/assets/clawd/clawd-error.svg +94 -0
  34. package/assets/clawd/clawd-happy.svg +161 -0
  35. package/assets/clawd/clawd-headphones-groove.svg +194 -0
  36. package/assets/clawd/clawd-idle-bubble.svg +180 -0
  37. package/assets/clawd/clawd-idle-collapse.svg +101 -0
  38. package/assets/clawd/clawd-idle-doze.svg +72 -0
  39. package/assets/clawd/clawd-idle-follow.svg +64 -0
  40. package/assets/clawd/clawd-idle-living.svg +196 -0
  41. package/assets/clawd/clawd-idle-look.svg +115 -0
  42. package/assets/clawd/clawd-idle-reading.svg +252 -0
  43. package/assets/clawd/clawd-idle-yawn.svg +158 -0
  44. package/assets/clawd/clawd-mini-alert.svg +129 -0
  45. package/assets/clawd/clawd-mini-crabwalk.svg +76 -0
  46. package/assets/clawd/clawd-mini-enter-sleep.svg +64 -0
  47. package/assets/clawd/clawd-mini-enter.svg +114 -0
  48. package/assets/clawd/clawd-mini-happy.svg +124 -0
  49. package/assets/clawd/clawd-mini-idle.svg +83 -0
  50. package/assets/clawd/clawd-mini-peek.svg +82 -0
  51. package/assets/clawd/clawd-mini-sleep.svg +112 -0
  52. package/assets/clawd/clawd-mini-typing.svg +153 -0
  53. package/assets/clawd/clawd-notification.svg +438 -0
  54. package/assets/clawd/clawd-react-annoyed.svg +167 -0
  55. package/assets/clawd/clawd-react-double-jump.svg +229 -0
  56. package/assets/clawd/clawd-react-double.svg +108 -0
  57. package/assets/clawd/clawd-react-drag.svg +102 -0
  58. package/assets/clawd/clawd-react-left.svg +102 -0
  59. package/assets/clawd/clawd-react-right.svg +102 -0
  60. package/assets/clawd/clawd-sleeping.svg +118 -0
  61. package/assets/clawd/clawd-static-base.svg +21 -0
  62. package/assets/clawd/clawd-wake.svg +277 -0
  63. package/assets/clawd/clawd-working-building.svg +329 -0
  64. package/assets/clawd/clawd-working-carrying.svg +178 -0
  65. package/assets/clawd/clawd-working-debugger.svg +245 -0
  66. package/assets/clawd/clawd-working-juggling.svg +183 -0
  67. package/assets/clawd/clawd-working-sweeping.svg +248 -0
  68. package/assets/clawd/clawd-working-thinking.svg +501 -0
  69. package/assets/clawd/clawd-working-typing-boss.svg +307 -0
  70. package/assets/clawd/clawd-working-typing.svg +273 -0
  71. package/assets/clawd/clawd-working-ultrathink.svg +166 -0
  72. package/assets/clawd/clawd-working-wizard.svg +356 -0
  73. package/assets/clawd.svg +64 -0
  74. package/assets/cloudling/cloudling/cloudling-attention.svg +380 -0
  75. package/assets/cloudling/cloudling/cloudling-building.svg +667 -0
  76. package/assets/cloudling/cloudling/cloudling-carrying.svg +604 -0
  77. package/assets/cloudling/cloudling/cloudling-conducting.svg +616 -0
  78. package/assets/cloudling/cloudling/cloudling-dozing-to-sleeping.svg +578 -0
  79. package/assets/cloudling/cloudling/cloudling-dozing.svg +358 -0
  80. package/assets/cloudling/cloudling/cloudling-error.svg +428 -0
  81. package/assets/cloudling/cloudling/cloudling-idle-reading.svg +658 -0
  82. package/assets/cloudling/cloudling/cloudling-idle-to-dozing.svg +568 -0
  83. package/assets/cloudling/cloudling/cloudling-idle-to-sleeping.svg +811 -0
  84. package/assets/cloudling/cloudling/cloudling-idle.svg +255 -0
  85. package/assets/cloudling/cloudling/cloudling-juggling.svg +648 -0
  86. package/assets/cloudling/cloudling/cloudling-mini-alert.svg +390 -0
  87. package/assets/cloudling/cloudling/cloudling-mini-crabwalk.svg +335 -0
  88. package/assets/cloudling/cloudling/cloudling-mini-enter-roll-in.svg +226 -0
  89. package/assets/cloudling/cloudling/cloudling-mini-enter-sleep.svg +232 -0
  90. package/assets/cloudling/cloudling/cloudling-mini-happy.svg +371 -0
  91. package/assets/cloudling/cloudling/cloudling-mini-idle.svg +279 -0
  92. package/assets/cloudling/cloudling/cloudling-mini-peek.svg +328 -0
  93. package/assets/cloudling/cloudling/cloudling-mini-sleep.svg +260 -0
  94. package/assets/cloudling/cloudling/cloudling-mini-typing.svg +692 -0
  95. package/assets/cloudling/cloudling/cloudling-notification.svg +494 -0
  96. package/assets/cloudling/cloudling/cloudling-react-drag.svg +83 -0
  97. package/assets/cloudling/cloudling/cloudling-sleeping-to-idle.svg +555 -0
  98. package/assets/cloudling/cloudling/cloudling-sleeping.svg +500 -0
  99. package/assets/cloudling/cloudling/cloudling-sweeping.svg +292 -0
  100. package/assets/cloudling/cloudling/cloudling-thinking.svg +720 -0
  101. package/assets/cloudling/cloudling/cloudling-typing.svg +354 -0
  102. package/assets/cloudling/cloudling-attention.svg +380 -0
  103. package/assets/cloudling/cloudling-building.svg +667 -0
  104. package/assets/cloudling/cloudling-carrying.svg +604 -0
  105. package/assets/cloudling/cloudling-conducting.svg +616 -0
  106. package/assets/cloudling/cloudling-dozing-to-sleeping.svg +578 -0
  107. package/assets/cloudling/cloudling-dozing.svg +358 -0
  108. package/assets/cloudling/cloudling-error.svg +428 -0
  109. package/assets/cloudling/cloudling-idle-reading.svg +658 -0
  110. package/assets/cloudling/cloudling-idle-to-dozing.svg +568 -0
  111. package/assets/cloudling/cloudling-idle-to-sleeping.svg +811 -0
  112. package/assets/cloudling/cloudling-idle.svg +255 -0
  113. package/assets/cloudling/cloudling-juggling.svg +648 -0
  114. package/assets/cloudling/cloudling-mini-alert.svg +390 -0
  115. package/assets/cloudling/cloudling-mini-crabwalk.svg +335 -0
  116. package/assets/cloudling/cloudling-mini-enter-roll-in.svg +226 -0
  117. package/assets/cloudling/cloudling-mini-enter-sleep.svg +232 -0
  118. package/assets/cloudling/cloudling-mini-happy.svg +371 -0
  119. package/assets/cloudling/cloudling-mini-idle.svg +279 -0
  120. package/assets/cloudling/cloudling-mini-peek.svg +328 -0
  121. package/assets/cloudling/cloudling-mini-sleep.svg +260 -0
  122. package/assets/cloudling/cloudling-mini-typing.svg +692 -0
  123. package/assets/cloudling/cloudling-notification.svg +494 -0
  124. package/assets/cloudling/cloudling-react-drag.svg +83 -0
  125. package/assets/cloudling/cloudling-sleeping-to-idle.svg +555 -0
  126. package/assets/cloudling/cloudling-sleeping.svg +500 -0
  127. package/assets/cloudling/cloudling-sweeping.svg +292 -0
  128. package/assets/cloudling/cloudling-thinking.svg +720 -0
  129. package/assets/cloudling/cloudling-typing.svg +354 -0
  130. package/assets/cloudling.svg +255 -0
  131. package/assets/ghost-attention.svg +19 -0
  132. package/assets/ghost-carrying.svg +19 -0
  133. package/assets/ghost-collapsing.svg +19 -0
  134. package/assets/ghost-dozing.svg +23 -0
  135. package/assets/ghost-error.svg +19 -0
  136. package/assets/ghost-happy.svg +23 -0
  137. package/assets/ghost-idle-action1.svg +19 -0
  138. package/assets/ghost-idle-action2.svg +19 -0
  139. package/assets/ghost-idle-action3.svg +19 -0
  140. package/assets/ghost-idle.svg +11 -0
  141. package/assets/ghost-juggling.svg +19 -0
  142. package/assets/ghost-notification.svg +19 -0
  143. package/assets/ghost-react-double.svg +23 -0
  144. package/assets/ghost-react-drag.svg +23 -0
  145. package/assets/ghost-react-left.svg +19 -0
  146. package/assets/ghost-react-right.svg +19 -0
  147. package/assets/ghost-sleeping.svg +19 -0
  148. package/assets/ghost-sweeping.svg +19 -0
  149. package/assets/ghost-thinking.svg +19 -0
  150. package/assets/ghost-waking.svg +19 -0
  151. package/assets/ghost-working.svg +19 -0
  152. package/assets/ghost-yawning.svg +23 -0
  153. package/assets/ghost.svg +11 -0
  154. package/assets/robot-attention.svg +19 -0
  155. package/assets/robot-carrying.svg +19 -0
  156. package/assets/robot-collapsing.svg +19 -0
  157. package/assets/robot-dozing.svg +23 -0
  158. package/assets/robot-error.svg +19 -0
  159. package/assets/robot-happy.svg +23 -0
  160. package/assets/robot-idle-action1.svg +19 -0
  161. package/assets/robot-idle-action2.svg +19 -0
  162. package/assets/robot-idle-action3.svg +19 -0
  163. package/assets/robot-idle.svg +11 -0
  164. package/assets/robot-juggling.svg +19 -0
  165. package/assets/robot-notification.svg +19 -0
  166. package/assets/robot-react-double.svg +23 -0
  167. package/assets/robot-react-drag.svg +23 -0
  168. package/assets/robot-react-left.svg +19 -0
  169. package/assets/robot-react-right.svg +19 -0
  170. package/assets/robot-sleeping.svg +19 -0
  171. package/assets/robot-sweeping.svg +19 -0
  172. package/assets/robot-thinking.svg +19 -0
  173. package/assets/robot-waking.svg +19 -0
  174. package/assets/robot-working.svg +19 -0
  175. package/assets/robot-yawning.svg +23 -0
  176. package/assets/robot.svg +11 -0
  177. package/manifest.json +889 -0
  178. package/package.json +18 -0
@@ -0,0 +1,428 @@
1
+ <svg id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="-6 -6 36 36" preserveAspectRatio="xMidYMid meet">
2
+ <style><![CDATA[
3
+ .edge-rim-tight { stroke-opacity: .9; }
4
+ .edge-rim-soft { stroke-opacity: .75; }
5
+ .edge-contact { stroke-opacity: .9; }
6
+ .statusbar, .preset {
7
+ font-size: 10px;
8
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
9
+ color: #9fb2ff;
10
+ background: #151824;
11
+ border-radius: 8px;
12
+ padding: 6px 14px;
13
+ min-width: min(820px, calc(100vw - 40px));
14
+ text-align: center;
15
+ letter-spacing: 0.03em;
16
+ }
17
+ .preset {
18
+ color: rgba(224,224,230,.70);
19
+ text-align: left;
20
+ white-space: pre-wrap;
21
+ line-height: 1.45;
22
+ }
23
+ @media (prefers-color-scheme: light) {
24
+ .edge-rim-tight { stroke-opacity: .95; }
25
+ .edge-rim-soft { stroke-opacity: .85; }
26
+ .edge-contact { stroke-opacity: .95; }
27
+ .cloud-drop-shadow { flood-opacity: .13; }
28
+ .statusbar, .preset { background: #fff; color: #3941FF; }
29
+ .food-cloud-shadow { flood-opacity: .28; flood-color: #5060FF; }
30
+ .food-cloud > path {
31
+ stroke: #5870E8 !important;
32
+ stroke-width: 1.2 !important;
33
+ stroke-opacity: .9 !important;
34
+ vector-effect: non-scaling-stroke !important;
35
+ }
36
+ }
37
+ ]]></style>
38
+ <defs>
39
+ <path id="cloud-shape" d="M9.064 3.344a4.578 4.578 0 012.285-.312c1 .115 1.891.54 2.673 1.275.01.01.024.017.037.021a.09.09 0 00.043 0 4.55 4.55 0 013.046.275l.047.022.116.057a4.581 4.581 0 012.188 2.399c.209.51.313 1.041.315 1.595a4.24 4.24 0 01-.134 1.223.123.123 0 00.03.115c.594.607.988 1.33 1.183 2.17.289 1.425-.007 2.71-.887 3.854l-.136.166a4.548 4.548 0 01-2.201 1.388.123.123 0 00-.081.076c-.191.551-.383 1.023-.74 1.494-.9 1.187-2.222 1.846-3.711 1.838-1.187-.006-2.239-.44-3.157-1.302a.107.107 0 00-.105-.024c-.388.125-.78.143-1.204.138a4.441 4.441 0 01-1.945-.466 4.544 4.544 0 01-1.61-1.335c-.152-.202-.303-.392-.414-.617a5.81 5.81 0 01-.37-.961 4.582 4.582 0 01-.014-2.298.124.124 0 00.006-.056.085.085 0 00-.027-.048 4.467 4.467 0 01-1.034-1.651 3.896 3.896 0 01-.251-1.192 5.189 5.189 0 01.141-1.6c.337-1.112.982-1.985 1.933-2.618.212-.141.413-.251.601-.33.215-.089.43-.164.646-.227a.098.098 0 00.065-.066 4.51 4.51 0 01.829-1.615 4.535 4.535 0 011.837-1.388z"/>
40
+ <clipPath id="cloud-clip"><use href="#cloud-shape"/></clipPath>
41
+
42
+ <linearGradient id="body-grad" x1="12" y1="1.5" x2="12" y2="22.8" gradientUnits="userSpaceOnUse">
43
+ <stop id="body-top" offset="0" stop-color="#6A708E"/>
44
+ <stop id="body-mid" offset=".44" stop-color="#333A53"/>
45
+ <stop id="body-bottom" offset="1" stop-color="#151A30"/>
46
+ </linearGradient>
47
+ <radialGradient id="body-hi" cx="9.2" cy="5.2" r="18" gradientUnits="userSpaceOnUse">
48
+ <stop offset="0" stop-color="#8B92B2" stop-opacity=".16"/>
49
+ <stop offset=".62" stop-color="#6C7394" stop-opacity=".08"/>
50
+ <stop offset="1" stop-color="#6C7394" stop-opacity="0"/>
51
+ </radialGradient>
52
+ <radialGradient id="body-core" cx="12.2" cy="17.5" r="11.8" gradientUnits="userSpaceOnUse">
53
+ <stop id="core-stop-a" offset="0" stop-color="#0C1023" stop-opacity=".22"/>
54
+ <stop id="core-stop-b" offset=".68" stop-color="#0C1023" stop-opacity=".09"/>
55
+ <stop offset="1" stop-color="#0C1023" stop-opacity="0"/>
56
+ </radialGradient>
57
+
58
+ <radialGradient id="flow-cool" cx="0.5" cy="0.5" r="0.65">
59
+ <stop offset="0" stop-color="#858DAE" stop-opacity=".26"/>
60
+ <stop offset=".52" stop-color="#697290" stop-opacity=".13"/>
61
+ <stop offset="1" stop-color="#697290" stop-opacity="0"/>
62
+ </radialGradient>
63
+ <radialGradient id="flow-deep" cx="0.5" cy="0.5" r="0.60">
64
+ <stop offset="0" stop-color="#020514" stop-opacity=".56"/>
65
+ <stop offset=".58" stop-color="#020514" stop-opacity=".18"/>
66
+ <stop offset="1" stop-color="#020514" stop-opacity="0"/>
67
+ </radialGradient>
68
+ <linearGradient id="flow-band-grad" x1="1" y1="0" x2="23" y2="0" gradientUnits="userSpaceOnUse">
69
+ <stop offset="0" stop-color="#747D9E" stop-opacity="0"/>
70
+ <stop offset=".45" stop-color="#747D9E" stop-opacity=".16"/>
71
+ <stop offset="1" stop-color="#747D9E" stop-opacity="0"/>
72
+ </linearGradient>
73
+
74
+ <linearGradient id="eye-grad" x1="12" y1="8.5" x2="12" y2="15.8" gradientUnits="userSpaceOnUse">
75
+ <stop offset="0" stop-color="#A9BCFF"/>
76
+ <stop offset=".54" stop-color="#6B89FF"/>
77
+ <stop offset="1" stop-color="#3941FF"/>
78
+ </linearGradient>
79
+
80
+ <filter id="cloud-shadow" x="-75%" y="-75%" width="250%" height="250%">
81
+ <feDropShadow id="hard-shadow" dx="0" dy=".8" stdDeviation="1.15" flood-color="#040611" flood-opacity=".70"/>
82
+ <feDropShadow id="blue-glow" dx="0" dy="0" stdDeviation="2.1" flood-color="#3941FF" flood-opacity=".18"/>
83
+ </filter>
84
+ <filter id="mist-blur" x="-30%" y="-30%" width="160%" height="160%">
85
+ <feGaussianBlur id="mist-blur-node" stdDeviation=".34"/>
86
+ </filter>
87
+ <filter id="ground-blur" x="-50%" y="-80%" width="200%" height="260%">
88
+ <feGaussianBlur stdDeviation="1"/>
89
+ </filter>
90
+ </defs>
91
+
92
+ <g id="rain" display="none" stroke="#7180C2" stroke-width=".45" stroke-linecap="round"></g>
93
+ <ellipse id="ground" cx="12" cy="22.9" rx="8.7" ry="1.25" fill="#030513" opacity=".48" filter="url(#ground-blur)"/>
94
+
95
+ <g id="cloud-root">
96
+ <g filter="url(#cloud-shadow)">
97
+ <use href="#cloud-shape" fill="url(#body-grad)" stroke="#9CA8D8" stroke-opacity=".22" stroke-width=".34"/>
98
+ <rect x="-3" y="-3" width="30" height="30" fill="url(#body-hi)" clip-path="url(#cloud-clip)"/>
99
+ <rect x="-3" y="-3" width="30" height="30" fill="url(#body-core)" clip-path="url(#cloud-clip)"/>
100
+ <g id="flow-layer" clip-path="url(#cloud-clip)" filter="url(#mist-blur)">
101
+ <ellipse id="flow-light" cx="8.5" cy="7.0" rx="14.8" ry="8.4" fill="url(#flow-cool)" opacity=".34"/>
102
+ <ellipse id="flow-dark" cx="15.6" cy="17.4" rx="13.6" ry="7.8" fill="url(#flow-deep)" opacity=".30"/>
103
+ <rect id="flow-band" x="-10" y="2.0" width="44" height="9.4" fill="url(#flow-band-grad)" opacity=".26" transform="rotate(-12 12 12)"/>
104
+ </g>
105
+ </g>
106
+
107
+ <g id="eyes" fill="none" stroke-linecap="round" stroke-linejoin="round">
108
+ <g id="eye-l" transform="translate(8.95 12.2) rotate(-5)">
109
+ <path d="M-1.15 -1.35 L1.15 1.35 M1.15 -1.35 L-1.15 1.35" stroke="#FFFFFF" stroke-width="1.42" stroke-opacity=".18"/>
110
+ <path d="M-1.15 -1.35 L1.15 1.35 M1.15 -1.35 L-1.15 1.35" stroke="url(#eye-grad)" stroke-width="1.08"/>
111
+ </g>
112
+ <g id="eye-r" transform="translate(15.05 12.25) rotate(6)">
113
+ <path d="M-1.15 -1.35 L1.15 1.35 M1.15 -1.35 L-1.15 1.35" stroke="#FFFFFF" stroke-width="1.42" stroke-opacity=".18"/>
114
+ <path d="M-1.15 -1.35 L1.15 1.35 M1.15 -1.35 L-1.15 1.35" stroke="url(#eye-grad)" stroke-width="1.08"/>
115
+ </g>
116
+ </g>
117
+ </g>
118
+ <g id="__cloudling-export-shims" opacity="0" pointer-events="none" style="display:none">
119
+ <g id="params"></g>
120
+ <g id="preset"></g>
121
+ <g id="statusbar"></g>
122
+ </g>
123
+
124
+ <script type="application/ecmascript"><![CDATA[
125
+ const TAU = Math.PI * 2;
126
+ const DEFAULTS = {
127
+ period: 4.0,
128
+ breathAmp: 0.070,
129
+ breathSpeed: 1.00,
130
+ squeezeStart: 0.53,
131
+ squeezeDuration: 0.66,
132
+ squeezeRamp: 0.60,
133
+ squeezePower: 0.95,
134
+ reboundOvershoot: 0.018,
135
+ reboundDamping: 0.78,
136
+ squashAmp: 0.088,
137
+ squashXBoost: 0.058,
138
+ squeezeDropY: 0.30,
139
+ rainDelay: 0.05,
140
+ rainDuration: 0.66,
141
+ rainBurstPower: 1.00,
142
+ flowAlpha: 0.56,
143
+ flowTravel: 4.1,
144
+ flowSpeed: 1.25,
145
+ flowBlur: 0.50,
146
+ darkFlowAlpha: 0.48,
147
+ bandAlpha: 0.28,
148
+ twistFlowBoost: 0.55,
149
+ rainBaseOpacity: 0.58,
150
+ rainBurstOpacity: 0.34,
151
+ rainBaseSpeed: 0.62,
152
+ rainBurstSpeed: 0.82,
153
+ rainBaseLength: 1.30,
154
+ rainBurstLength: 1.60,
155
+ rainCount: 8,
156
+ rainDrift: 0.40,
157
+ eyeDim: 0.08,
158
+ };
159
+ let P = { ...DEFAULTS };
160
+ let paused = false;
161
+ let pauseStart = 0;
162
+ let pausedTotal = 0;
163
+ const startedAt = performance.now();
164
+ const RAIN_LINES = [
165
+ { x: 1.8, y: 22.9, len: 1.15, delay: 0.04, alpha: 0.78 },
166
+ { x: 4.3, y: 24.1, len: 1.00, delay: 0.31, alpha: 0.52 },
167
+ { x: 6.5, y: 22.9, len: 0.92, delay: 0.62, alpha: 0.42 },
168
+ { x: 9.1, y: 24.5, len: 0.88, delay: 0.83, alpha: 0.36 },
169
+ { x: 14.9, y: 23.4, len: 0.92, delay: 0.18, alpha: 0.40 },
170
+ { x: 17.4, y: 24.4, len: 1.05, delay: 0.49, alpha: 0.54 },
171
+ { x: 20.0, y: 23.0, len: 1.22, delay: 0.70, alpha: 0.82 },
172
+ { x: 22.6, y: 24.0, len: 1.00, delay: 0.92, alpha: 0.50 },
173
+ ];
174
+
175
+ const PARAM_DEFS = [
176
+ { group: '循环 / CYCLE' },
177
+ { key: 'period', label: '总周期 s', min: 3.6, max: 7.0, step: 0.1 },
178
+ { key: 'squeezeStart', label: '开始拧的位置', min: 0.08, max: 0.70, step: 0.01 },
179
+ { key: 'squeezeDuration', label: '拧+回弹时长', min: 0.22, max: 0.86, step: 0.01 },
180
+ { key: 'squeezeRamp', label: '压扁用时占比', min: 0.20, max: 0.70, step: 0.01 },
181
+ { key: 'squeezePower', label: '压扁曲线硬度', min: 0.6, max: 3.0, step: 0.05 },
182
+ { group: '云体呼吸 / BODY' },
183
+ { key: 'breathAmp', label: '呼吸大小幅度', min: 0.00, max: 0.10, step: 0.005 },
184
+ { key: 'breathSpeed', label: '呼吸速度倍数', min: 0.3, max: 2.0, step: 0.05 },
185
+ { key: 'squashAmp', label: '拧毛巾压扁幅度', min: 0.00, max: 0.16, step: 0.005 },
186
+ { key: 'squashXBoost', label: '压扁横向膨胀', min: 0.00, max: 0.12, step: 0.005 },
187
+ { key: 'squeezeDropY', label: '压扁下沉', min: 0.00, max: 0.90, step: 0.02 },
188
+ { key: 'reboundOvershoot', label: '回弹过冲', min: 0.00, max: 0.08, step: 0.002 },
189
+ { key: 'reboundDamping', label: '回弹衰减', min: 0.20, max: 1.20, step: 0.05 },
190
+ { group: '挤出的雨 / BURST' },
191
+ { key: 'rainDelay', label: '雨跟拧的错位', min: 0.00, max: 0.14, step: 0.01 },
192
+ { key: 'rainDuration', label: '雨随拧持续', min: 0.20, max: 0.86, step: 0.01 },
193
+ { key: 'rainBurstPower', label: '雨峰曲线硬度', min: 0.5, max: 3.0, step: 0.05 },
194
+ { group: '乌云流动 / FLOW' },
195
+ { key: 'flowAlpha', label: '浅色漫反射流动', min: 0.00, max: 0.90, step: 0.01 },
196
+ { key: 'darkFlowAlpha', label: '暗部漫反射流动', min: 0.00, max: 0.90, step: 0.01 },
197
+ { key: 'bandAlpha', label: '漫反射流带强度', min: 0.00, max: 0.80, step: 0.01 },
198
+ { key: 'flowTravel', label: '流动位移', min: 0.0, max: 7.0, step: 0.1 },
199
+ { key: 'flowSpeed', label: '流动速度', min: 0.2, max: 3.0, step: 0.05 },
200
+ { key: 'flowBlur', label: '流动柔化', min: 0.0, max: 1.0, step: 0.02 },
201
+ { key: 'twistFlowBoost', label: '拧时流动加速感', min: 0.00, max: 1.20, step: 0.05 },
202
+ { group: '雨 / RAIN' },
203
+ { key: 'rainCount', label: '雨线数量', min: 2, max: 8, step: 1 },
204
+ { key: 'rainBaseOpacity', label: '常态雨透明度', min: 0.05, max: 1.0, step: 0.01 },
205
+ { key: 'rainBurstOpacity', label: '挤出时增亮', min: 0.00, max: 0.70, step: 0.01 },
206
+ { key: 'rainBaseSpeed', label: '常态雨速度', min: 0.15, max: 1.5, step: 0.05 },
207
+ { key: 'rainBurstSpeed', label: '挤出时加速', min: 0.00, max: 1.8, step: 0.05 },
208
+ { key: 'rainBaseLength', label: '常态雨长度', min: 0.40, max: 2.4, step: 0.05 },
209
+ { key: 'rainBurstLength', label: '挤出时变长', min: 0.00, max: 2.8, step: 0.05 },
210
+ { key: 'rainDrift', label: '雨线斜移', min: 0.00, max: 1.2, step: 0.02 },
211
+ { group: '眼睛 / EYES' },
212
+ { key: 'eyeDim', label: '拧时眼睛变暗', min: 0.00, max: 0.30, step: 0.01 },
213
+ ];
214
+
215
+ const el = {
216
+ cloudRoot: document.getElementById('cloud-root'),
217
+ rain: document.getElementById('rain'),
218
+ bodyGrad: document.getElementById('body-grad'),
219
+ bodyHi: document.getElementById('body-hi'),
220
+ bodyCore: document.getElementById('body-core'),
221
+ coreA: document.getElementById('core-stop-a'),
222
+ coreB: document.getElementById('core-stop-b'),
223
+ eyeGrad: document.getElementById('eye-grad'),
224
+ eyes: document.getElementById('eyes'),
225
+ eyeL: document.getElementById('eye-l'),
226
+ eyeR: document.getElementById('eye-r'),
227
+ flowLight: document.getElementById('flow-light'),
228
+ flowDark: document.getElementById('flow-dark'),
229
+ flowBand: document.getElementById('flow-band'),
230
+ blur: document.getElementById('mist-blur-node'),
231
+ ground: document.getElementById('ground'),
232
+ hardShadow: document.getElementById('hard-shadow'),
233
+ blueGlow: document.getElementById('blue-glow'),
234
+ status: document.getElementById('statusbar'),
235
+ preset: document.getElementById('preset'),
236
+ };
237
+
238
+ const RAIN_COPIES = 2;
239
+ const rainPaths = RAIN_LINES.map(() => {
240
+ const copies = [];
241
+ for (let i = 0; i < RAIN_COPIES; i++) {
242
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
243
+ path.setAttribute('fill', 'none');
244
+ el.rain.appendChild(path);
245
+ copies.push(path);
246
+ }
247
+ return copies;
248
+ });
249
+
250
+ function buildParams() {
251
+ const params = document.getElementById('params');
252
+ params.innerHTML = '';
253
+ for (const def of PARAM_DEFS) {
254
+ if (def.group) {
255
+ const h = document.createElement('h3');
256
+ h.textContent = def.group;
257
+ params.appendChild(h);
258
+ continue;
259
+ }
260
+ const lab = document.createElement('label');
261
+ lab.innerHTML = `
262
+ <span>${def.label}</span>
263
+ <input type="range" data-key="${def.key}" min="${def.min}" max="${def.max}" step="${def.step}" value="${P[def.key]}"/>
264
+ <span class="val" data-val="${def.key}">${formatValue(P[def.key], def.step)}</span>
265
+ `;
266
+ const range = lab.querySelector('input');
267
+ const val = lab.querySelector('[data-val]');
268
+ range.oninput = e => {
269
+ P[def.key] = parseFloat(e.target.value);
270
+ if (def.key === 'rainCount') P[def.key] = Math.round(P[def.key]);
271
+ val.textContent = formatValue(P[def.key], def.step);
272
+ updatePreset();
273
+ };
274
+ params.appendChild(lab);
275
+ }
276
+ updatePreset();
277
+ }
278
+
279
+ function formatValue(v, step) {
280
+ if (Number.isInteger(step)) return String(v);
281
+ if (step >= 0.1) return Number(v).toFixed(1);
282
+ if (step >= 0.01) return Number(v).toFixed(2);
283
+ return Number(v).toFixed(3);
284
+ }
285
+
286
+ function updatePreset() {
287
+ const keys = PARAM_DEFS.filter(d => d.key).map(d => d.key);
288
+ const subset = {};
289
+ keys.forEach(k => subset[k] = P[k]);
290
+ el.preset.textContent = `当前参数: ${JSON.stringify(subset)}`;
291
+ }
292
+
293
+ function clamp01(v) { return Math.max(0, Math.min(1, v)); }
294
+ function mix(a, b, t) { return a + (b - a) * t; }
295
+ function smoothstep(edge0, edge1, x) {
296
+ const t = clamp01((x - edge0) / (edge1 - edge0));
297
+ return t * t * (3 - 2 * t);
298
+ }
299
+ function wrap01(v) {
300
+ return ((v % 1) + 1) % 1;
301
+ }
302
+
303
+ function cycleLocal(phase, start, duration) {
304
+ const u = wrap01(phase - start);
305
+ if (u > duration) return null;
306
+ return u / duration;
307
+ }
308
+
309
+ function squeezeAt(phase) {
310
+ const u = cycleLocal(phase, P.squeezeStart, P.squeezeDuration);
311
+ if (u === null) return 0;
312
+ const ramp = clamp01(P.squeezeRamp);
313
+ if (u <= ramp) {
314
+ return Math.pow(smoothstep(0, 1, u / ramp), P.squeezePower);
315
+ }
316
+ const release = (u - ramp) / Math.max(0.001, 1 - ramp);
317
+ return Math.pow(1 - smoothstep(0, 1, release), P.squeezePower);
318
+ }
319
+
320
+ function rainBurstAt(phase) {
321
+ const start = wrap01(P.squeezeStart + P.rainDelay);
322
+ const u = cycleLocal(phase, start, P.rainDuration);
323
+ if (u === null) return 0;
324
+ const rampInCycle = Math.max(0.04, P.squeezeDuration * P.squeezeRamp);
325
+ const ramp = clamp01(rampInCycle / Math.max(0.001, P.rainDuration));
326
+ if (u <= ramp) {
327
+ return Math.pow(smoothstep(0, 1, u / ramp), P.rainBurstPower);
328
+ }
329
+ const release = (u - ramp) / Math.max(0.001, 1 - ramp);
330
+ return Math.pow(1 - smoothstep(0, 1, release), P.rainBurstPower);
331
+ }
332
+
333
+ function reboundAt(phase) {
334
+ const start = wrap01(P.squeezeStart + P.squeezeDuration * P.squeezeRamp);
335
+ const duration = Math.max(0.08, P.squeezeDuration * (1 - P.squeezeRamp));
336
+ const u = cycleLocal(phase, start, duration);
337
+ if (u === null) return 0;
338
+ return Math.sin(Math.PI * u) * Math.pow(1 - u, P.reboundDamping);
339
+ }
340
+
341
+ function renderAt(timeMs) {
342
+ const t = timeMs / 1000;
343
+ const phase = (t / P.period) % 1;
344
+ const squeeze = squeezeAt(phase);
345
+ const rainBurst = rainBurstAt(phase);
346
+ const rebound = reboundAt(phase);
347
+ const breath = 0.5 + 0.5 * Math.sin(TAU * (phase * P.breathSpeed - 0.18));
348
+ const breathScale = 1 + (breath - 0.5) * 2 * P.breathAmp;
349
+ const sx = 1.02 * breathScale + squeeze * P.squashXBoost - rebound * P.reboundOvershoot * 0.35;
350
+ const sy = 0.995 * breathScale - squeeze * P.squashAmp + rebound * P.reboundOvershoot;
351
+ const ty = 0.08 + (breath - 0.5) * 0.18 + squeeze * P.squeezeDropY - rebound * 0.12;
352
+ const twist = Math.sin(TAU * phase * 2.0) * squeeze;
353
+ const rot = (breath - 0.5) * 1.1 - squeeze * 1.15 + rebound * 0.55 + twist * 0.55;
354
+ el.cloudRoot.setAttribute(
355
+ 'transform',
356
+ `translate(12 ${(12.1 + ty).toFixed(3)}) rotate(${rot.toFixed(3)}) scale(${sx.toFixed(4)} ${sy.toFixed(4)}) translate(-12 -12)`
357
+ );
358
+
359
+ const flow = t / P.period * P.flowSpeed * (1 + squeeze * P.twistFlowBoost);
360
+ el.bodyGrad.setAttribute('y1', (1.0 + Math.sin(flow * TAU * 0.36) * 0.35).toFixed(3));
361
+ el.bodyGrad.setAttribute('y2', (22.9 + Math.cos(flow * TAU * 0.32) * 0.30).toFixed(3));
362
+ el.bodyHi.setAttribute('cx', (9.2 + Math.sin(flow * TAU * 0.28) * 0.65).toFixed(3));
363
+ el.bodyHi.setAttribute('cy', (5.2 + Math.cos(flow * TAU * 0.24) * 0.35).toFixed(3));
364
+ el.bodyHi.setAttribute('r', (18.0 + Math.sin(flow * TAU * 0.20) * 0.18).toFixed(3));
365
+ el.bodyCore.setAttribute('cx', (12.2 + Math.sin(flow * TAU * 0.26 + 1.5) * 0.55).toFixed(3));
366
+ el.bodyCore.setAttribute('cy', (17.5 + Math.cos(flow * TAU * 0.22) * 0.40).toFixed(3));
367
+ el.bodyCore.setAttribute('r', (11.2 + Math.sin(flow * TAU * 0.18) * 0.25).toFixed(3));
368
+ el.coreA.setAttribute('stop-opacity', '0.20');
369
+ el.coreB.setAttribute('stop-opacity', '0.08');
370
+
371
+ const travel = P.flowTravel;
372
+ el.blur.setAttribute('stdDeviation', P.flowBlur.toFixed(3));
373
+ el.flowLight.setAttribute('cx', (8.5 + Math.sin(flow * TAU * 0.45) * travel * 0.55).toFixed(3));
374
+ el.flowLight.setAttribute('cy', (7.0 + Math.cos(flow * TAU * 0.34) * travel * 0.18).toFixed(3));
375
+ el.flowLight.setAttribute('opacity', (P.flowAlpha * 0.50).toFixed(3));
376
+ el.flowDark.setAttribute('cx', (15.6 + Math.cos(flow * TAU * 0.40) * travel * 0.55).toFixed(3));
377
+ el.flowDark.setAttribute('cy', (17.4 + Math.sin(flow * TAU * 0.32) * travel * 0.20).toFixed(3));
378
+ el.flowDark.setAttribute('opacity', (P.darkFlowAlpha * 0.70).toFixed(3));
379
+ const bandX = -13 + ((flow * 18) % 24);
380
+ el.flowBand.setAttribute('transform', `translate(${bandX.toFixed(3)} 0) rotate(-12 12 12)`);
381
+ el.flowBand.setAttribute('opacity', (P.bandAlpha * 0.46).toFixed(3));
382
+
383
+ const eyeYOffset = squeeze * 0.14;
384
+ el.eyes.setAttribute('opacity', (0.90 - squeeze * P.eyeDim + Math.sin(flow * TAU * 1.0) * 0.012).toFixed(3));
385
+ el.eyeGrad.setAttribute('y1', (8.5 + Math.sin(flow * TAU * 0.74) * 0.8).toFixed(3));
386
+ el.eyeGrad.setAttribute('y2', (15.8 + Math.sin(flow * TAU * 0.74) * 0.8).toFixed(3));
387
+ el.eyeL.setAttribute('transform', `translate(8.95 ${(12.2 + eyeYOffset).toFixed(3)}) rotate(${(-5 - squeeze * 1.5).toFixed(3)}) scale(${(1 - squeeze * 0.030).toFixed(3)})`);
388
+ el.eyeR.setAttribute('transform', `translate(15.05 ${(12.25 + eyeYOffset).toFixed(3)}) rotate(${(6 + squeeze * 1.2).toFixed(3)}) scale(${(1 - squeeze * 0.030).toFixed(3)})`);
389
+
390
+ el.hardShadow.setAttribute('flood-opacity', '0.62');
391
+ el.blueGlow.setAttribute('flood-opacity', '0.14');
392
+ el.ground.setAttribute('rx', (8.5 + (breath - 0.5) * 0.4).toFixed(3));
393
+ el.ground.setAttribute('opacity', '0.42');
394
+
395
+ const rainPower = clamp01(P.rainBaseOpacity + rainBurst * P.rainBurstOpacity);
396
+ el.rain.setAttribute('opacity', rainPower.toFixed(3));
397
+ el.rain.setAttribute('stroke-width', (0.36 + rainBurst * 0.13).toFixed(3));
398
+ RAIN_LINES.forEach((line, i) => {
399
+ const visible = i < P.rainCount;
400
+ const speed = P.rainBaseSpeed + rainBurst * P.rainBurstSpeed;
401
+ const fall = mix(2.6, 6.2, rainBurst);
402
+ const len = (line.len * P.rainBaseLength) + rainBurst * P.rainBurstLength;
403
+ rainPaths[i].forEach((path, copyIndex) => {
404
+ const p = (t * speed + line.delay + copyIndex / RAIN_COPIES) % 1;
405
+ const fadeIn = smoothstep(0.00, 0.24, p);
406
+ const fadeOut = 1 - smoothstep(0.76, 1.00, p);
407
+ const fade = Math.max(0.12, fadeIn * fadeOut);
408
+ const y1 = line.y + p * fall - squeeze * 0.30 - copyIndex * 0.15;
409
+ const x1 = line.x - p * P.rainDrift - squeeze * 0.12;
410
+ const y2 = y1 + len;
411
+ const x2 = x1 - 0.42;
412
+ path.setAttribute('d', `M${x1.toFixed(3)} ${y1.toFixed(3)} L${x2.toFixed(3)} ${y2.toFixed(3)}`);
413
+ path.setAttribute('opacity', visible ? (line.alpha * fade * 0.72).toFixed(3) : '0');
414
+ });
415
+ });
416
+
417
+ el.status.textContent = `phase ${phase.toFixed(2)} · squeeze ${squeeze.toFixed(2)} · rainBurst ${rainBurst.toFixed(2)} · rebound ${rebound.toFixed(2)} · sx ${sx.toFixed(3)} · sy ${sy.toFixed(3)}`;
418
+ }
419
+
420
+ function loop(now) {
421
+ if (!paused) {
422
+ renderAt(now - startedAt - pausedTotal);
423
+ }
424
+ requestAnimationFrame(loop);
425
+ }
426
+ requestAnimationFrame(loop);
427
+ ]]></script>
428
+ </svg>