nonebot-plugin-osubot 6.24.1__py3-none-any.whl → 6.24.2__py3-none-any.whl
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.
Potentially problematic release.
This version of nonebot-plugin-osubot might be problematic. Click here for more details.
- nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +5 -10
- {nonebot_plugin_osubot-6.24.1.dist-info → nonebot_plugin_osubot-6.24.2.dist-info}/METADATA +1 -1
- {nonebot_plugin_osubot-6.24.1.dist-info → nonebot_plugin_osubot-6.24.2.dist-info}/RECORD +4 -5
- nonebot_plugin_osubot/draw/osu_preview_templates/index.html +0 -437
- {nonebot_plugin_osubot-6.24.1.dist-info → nonebot_plugin_osubot-6.24.2.dist-info}/WHEEL +0 -0
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
7
|
+
<base href="{{ base_url }}">
|
|
7
8
|
<meta name="robots" content="nofollow, noindex, noarchive">
|
|
8
9
|
<title>gif生成测试 网址后加#bid</title>
|
|
9
10
|
</head>
|
|
@@ -53,14 +54,14 @@
|
|
|
53
54
|
<script src="gif.js/gif.js"></script>
|
|
54
55
|
|
|
55
56
|
<script>
|
|
56
|
-
const scaleValue = 0.
|
|
57
|
+
const scaleValue = 0.5;
|
|
57
58
|
const durationValue = 10000;
|
|
58
59
|
const qualityValue = 10;
|
|
59
60
|
const timeSpanValue = 50;
|
|
60
61
|
|
|
61
62
|
const createImg = function () {
|
|
62
63
|
let preview = new Preview(scaleValue);
|
|
63
|
-
const osufile = {{ osu_file
|
|
64
|
+
const osufile = `{{ osu_file }}`;
|
|
64
65
|
preview.load(osufile, function () {
|
|
65
66
|
let actualStartTime;
|
|
66
67
|
const previewEndTime = preview.previewTime + durationValue;
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
const actualEndTime = durationValue === -1 ? preview.endTime : Math.min(actualStartTime + durationValue, preview.endTime);
|
|
75
76
|
let gif = new GIF({
|
|
76
77
|
workers: 4,
|
|
77
|
-
workerScript:
|
|
78
|
+
workerScript: "{{ worker_data_uri }}",
|
|
78
79
|
quality: qualityValue,
|
|
79
80
|
width: preview.screen.width * scaleValue,
|
|
80
81
|
height: preview.screen.height * scaleValue,
|
|
@@ -96,18 +97,12 @@
|
|
|
96
97
|
currentFrame++;
|
|
97
98
|
}
|
|
98
99
|
gif.on('finished', function (blob) {
|
|
99
|
-
|
|
100
|
-
const img = document.createElement('img');
|
|
101
|
-
img.id = 'img';
|
|
102
|
-
img.src = url;
|
|
103
|
-
img.alt = '生成的GIF预览';
|
|
100
|
+
document.getElementById("img").src = URL.createObjectURL(blob);
|
|
104
101
|
});
|
|
105
102
|
gif.render();
|
|
106
103
|
});
|
|
107
104
|
}
|
|
108
|
-
|
|
109
105
|
window.addEventListener('hashchange', createImg);
|
|
110
|
-
|
|
111
106
|
createImg();
|
|
112
107
|
</script>
|
|
113
108
|
</body>
|
|
@@ -50,7 +50,6 @@ nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js,sha256=qLERBxuzsS
|
|
|
50
50
|
nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map,sha256=1Hg6tubanG4YHx_ezCr88Kkcf-po-RxFm2ovxXt8h-Q,29120
|
|
51
51
|
nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js,sha256=yp4wSFV-wF1hnhi4NAPNNmnIiTnl-i1gNM52JdRFlw0,16636
|
|
52
52
|
nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map,sha256=gasS_2E9Lp3sbSC0PtRd70pW7BzYqw7lMcC65aD2k2M,55277
|
|
53
|
-
nonebot_plugin_osubot/draw/osu_preview_templates/index.html,sha256=x4QQ0c1vMIgGkxdapplruSr1Z97bULE9CBY3pkjTvS8,16804
|
|
54
53
|
nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js,sha256=xra2zaBmCtlw-_4uhZM_ipvk_CaakOYIeygREIHDmEM,5338
|
|
55
54
|
nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js,sha256=q9b2KA2qHkWkkGzEq1Djk5RwVr538E0B22jNIIU9n84,736
|
|
56
55
|
nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js,sha256=AXybWPbpUypXCVdz_Vqdk8HjEgDQd6cT-360gGmrCas,1035
|
|
@@ -83,7 +82,7 @@ nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js,sha256=3Fj
|
|
|
83
82
|
nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js,sha256=oueLYtlQCDBpBv_JNwJz_RY6PbDCBbd837NeF8o82T8,1900
|
|
84
83
|
nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js,sha256=TEOiZydvVlGabGebv2V6kSfikc5-S2oUmbwhFfvDxPk,3296
|
|
85
84
|
nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js,sha256=XveUlX-d0vrUnXaGbR8y428s6Nw2zhDR235pFko_MxM,1504
|
|
86
|
-
nonebot_plugin_osubot/draw/osu_preview_templates/pic.html,sha256=
|
|
85
|
+
nonebot_plugin_osubot/draw/osu_preview_templates/pic.html,sha256=q8FgImgnH-FOPRGMtecD6DwN1B-iiLX1SLM-vMQFXy8,4285
|
|
87
86
|
nonebot_plugin_osubot/draw/rating.py,sha256=pA7mGLI4IujmYB6kQf_tSkR7mZGpUAVLRLyaAsZhqTM,20397
|
|
88
87
|
nonebot_plugin_osubot/draw/score.py,sha256=cUD8zpdf8e43Du9Z_A6T3HIP3IxtgSF3wheaNwMBWWk,29277
|
|
89
88
|
nonebot_plugin_osubot/draw/static.py,sha256=wdlzNO3xyiauKiMLr_h-B9uAsFU7fX_Y-fOusYKZP3k,4132
|
|
@@ -448,6 +447,6 @@ nonebot_plugin_osubot/schema/ppysb/__init__.py,sha256=JK2Z4n44gUJPVKdETMJYJ5uIw-
|
|
|
448
447
|
nonebot_plugin_osubot/schema/score.py,sha256=o32jKDESzFwOFPZnzjKqxNIj0MPUL9mFvBqgaZARHac,3269
|
|
449
448
|
nonebot_plugin_osubot/schema/user.py,sha256=sxNmqymG_kIVuGuzfchSv9UML6NPG70cqo2_h5xDIpM,2250
|
|
450
449
|
nonebot_plugin_osubot/utils/__init__.py,sha256=pyv8XxBcCOeQVDj1E4dgvktzcefgQXfKBlarsYGx1sg,815
|
|
451
|
-
nonebot_plugin_osubot-6.24.
|
|
452
|
-
nonebot_plugin_osubot-6.24.
|
|
453
|
-
nonebot_plugin_osubot-6.24.
|
|
450
|
+
nonebot_plugin_osubot-6.24.2.dist-info/WHEEL,sha256=B19PGBCYhWaz2p_UjAoRVh767nYQfk14Sn4TpIZ-nfU,87
|
|
451
|
+
nonebot_plugin_osubot-6.24.2.dist-info/METADATA,sha256=E6_OnpJTXY_ZSRh3e1GqCiUS3xPWFrvb3PuKT32YD6M,4476
|
|
452
|
+
nonebot_plugin_osubot-6.24.2.dist-info/RECORD,,
|
|
@@ -1,437 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<meta charset="UTF-8">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
7
|
-
<meta name="robots" content="nofollow, noindex, noarchive">
|
|
8
|
-
<title>osu! GIF 预览生成器</title>
|
|
9
|
-
<style>
|
|
10
|
-
body {
|
|
11
|
-
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
12
|
-
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
13
|
-
color: #fff;
|
|
14
|
-
margin: 0;
|
|
15
|
-
padding: 20px;
|
|
16
|
-
min-height: 100vh;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.container {
|
|
20
|
-
max-width: 1200px;
|
|
21
|
-
margin: 0 auto;
|
|
22
|
-
display: flex;
|
|
23
|
-
flex-direction: column;
|
|
24
|
-
align-items: center;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.header {
|
|
28
|
-
text-align: center;
|
|
29
|
-
margin-bottom: 30px;
|
|
30
|
-
width: 100%;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
h1 {
|
|
34
|
-
color: #ff66aa;
|
|
35
|
-
text-shadow: 0 0 10px rgba(255, 102, 170, 0.5);
|
|
36
|
-
margin-bottom: 10px;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.instructions {
|
|
40
|
-
background: rgba(0, 0, 0, 0.3);
|
|
41
|
-
padding: 15px;
|
|
42
|
-
border-radius: 10px;
|
|
43
|
-
margin-bottom: 20px;
|
|
44
|
-
width: 100%;
|
|
45
|
-
box-sizing: border-box;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.input-area {
|
|
49
|
-
display: flex;
|
|
50
|
-
flex-wrap: wrap;
|
|
51
|
-
gap: 10px;
|
|
52
|
-
margin-bottom: 20px;
|
|
53
|
-
width: 100%;
|
|
54
|
-
justify-content: center;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.input-group {
|
|
58
|
-
display: flex;
|
|
59
|
-
align-items: center;
|
|
60
|
-
gap: 5px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.input-group label {
|
|
64
|
-
white-space: nowrap;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
input[type="text"] {
|
|
68
|
-
padding: 12px;
|
|
69
|
-
border: none;
|
|
70
|
-
border-radius: 5px;
|
|
71
|
-
background: rgba(255, 255, 255, 0.1);
|
|
72
|
-
color: white;
|
|
73
|
-
width: 200px;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
input[type="checkbox"] {
|
|
77
|
-
width: 16px;
|
|
78
|
-
height: 16px;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.checkbox-group {
|
|
82
|
-
display: flex;
|
|
83
|
-
align-items: center;
|
|
84
|
-
gap: 5px;
|
|
85
|
-
margin-left: 10px;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
button {
|
|
89
|
-
padding: 12px 20px;
|
|
90
|
-
border: none;
|
|
91
|
-
border-radius: 5px;
|
|
92
|
-
background: #ff66aa;
|
|
93
|
-
color: white;
|
|
94
|
-
cursor: pointer;
|
|
95
|
-
transition: background 0.3s;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
button:hover {
|
|
99
|
-
background: #ff3388;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.status {
|
|
103
|
-
margin: 20px 0;
|
|
104
|
-
padding: 15px;
|
|
105
|
-
border-radius: 5px;
|
|
106
|
-
background: rgba(0, 0, 0, 0.3);
|
|
107
|
-
width: 100%;
|
|
108
|
-
text-align: center;
|
|
109
|
-
box-sizing: border-box;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.progress-container {
|
|
113
|
-
width: 100%;
|
|
114
|
-
background: rgba(255, 255, 255, 0.1);
|
|
115
|
-
border-radius: 5px;
|
|
116
|
-
margin: 20px 0;
|
|
117
|
-
overflow: hidden;
|
|
118
|
-
display: none;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.progress-bar {
|
|
122
|
-
width: 0%;
|
|
123
|
-
height: 20px;
|
|
124
|
-
background: linear-gradient(90deg, #ff66aa 0%, #ff3388 100%);
|
|
125
|
-
transition: width 0.3s;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
#result {
|
|
129
|
-
margin-top: 30px;
|
|
130
|
-
text-align: center;
|
|
131
|
-
width: 100%;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
#img {
|
|
135
|
-
max-width: 100%;
|
|
136
|
-
border-radius: 10px;
|
|
137
|
-
box-shadow: 0 0 20px rgba(255, 102, 170, 0.5);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.footer {
|
|
141
|
-
margin-top: 30px;
|
|
142
|
-
text-align: center;
|
|
143
|
-
font-size: 0.9em;
|
|
144
|
-
color: #aaa;
|
|
145
|
-
}
|
|
146
|
-
</style>
|
|
147
|
-
</head>
|
|
148
|
-
|
|
149
|
-
<body>
|
|
150
|
-
<div class="container">
|
|
151
|
-
<div class="header">
|
|
152
|
-
<h1>osu! GIF 预览生成器</h1>
|
|
153
|
-
<div class="instructions">
|
|
154
|
-
<p>输入osu!谱面ID,生成游戏预览GIF</p>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<div class="input-area">
|
|
159
|
-
<div class="input-group">
|
|
160
|
-
<label>谱面ID:</label>
|
|
161
|
-
<input type="text" value="172662" id="beatmapInput" placeholder="例如: 172662" />
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
<div class="input-group">
|
|
165
|
-
<label>缩放比例:</label>
|
|
166
|
-
<input type="text" value="0.2" id="scaleInput" placeholder="建议0.2,0.5以上生成速度显著降低" />
|
|
167
|
-
</div>
|
|
168
|
-
|
|
169
|
-
<div class="input-group">
|
|
170
|
-
<label>帧间隔(ms):</label>
|
|
171
|
-
<input type="text" value="50" id="timeSpanInput" placeholder="建议50,最低15" />
|
|
172
|
-
</div>
|
|
173
|
-
|
|
174
|
-
<div class="input-group">
|
|
175
|
-
<label>开始时间(ms):</label>
|
|
176
|
-
<input type="text" value="-1" id="startTimeInput" placeholder="-1表示第一个note前" />
|
|
177
|
-
<div class="checkbox-group">
|
|
178
|
-
<input type="checkbox" id="usePreviewTimeCheckbox" checked />
|
|
179
|
-
<label for="usePreviewTimeCheckbox">优先使用谱面预览时间</label>
|
|
180
|
-
</div>
|
|
181
|
-
</div>
|
|
182
|
-
|
|
183
|
-
<div class="input-group">
|
|
184
|
-
<label>持续时间(ms):</label>
|
|
185
|
-
<input type="text" value="-1" id="durationInput" placeholder="-1表示到结尾" />
|
|
186
|
-
</div>
|
|
187
|
-
|
|
188
|
-
<div class="input-group">
|
|
189
|
-
<label>GIF质量:</label>
|
|
190
|
-
<input type="text" value="10" id="qualityInput" placeholder="不建议修改,值越小质量越好,但是经测试区别非常小" />
|
|
191
|
-
</div>
|
|
192
|
-
|
|
193
|
-
<button id="generateBtn">生成GIF</button>
|
|
194
|
-
</div>
|
|
195
|
-
|
|
196
|
-
<div class="status" id="status">准备就绪,请输入谱面ID</div>
|
|
197
|
-
|
|
198
|
-
<div class="progress-container" id="progressContainer">
|
|
199
|
-
<div class="progress-bar" id="progressBar"></div>
|
|
200
|
-
</div>
|
|
201
|
-
|
|
202
|
-
<div id="result"></div>
|
|
203
|
-
|
|
204
|
-
<div class="footer">
|
|
205
|
-
<p>使用 osu.direct API 获取谱面数据 | 基于 gif.js 生成GIF</p>
|
|
206
|
-
</div>
|
|
207
|
-
</div>
|
|
208
|
-
|
|
209
|
-
<script src="js/util.js"></script>
|
|
210
|
-
|
|
211
|
-
<script src="js/beatmap/beatmap.js"></script>
|
|
212
|
-
<script src="js/beatmap/timingpoint.js"></script>
|
|
213
|
-
<script src="js/beatmap/hitobject.js"></script>
|
|
214
|
-
<script src="js/beatmap/point.js"></script>
|
|
215
|
-
<script src="js/beatmap/scroll.js"></script>
|
|
216
|
-
|
|
217
|
-
<script src="js/standard/standard.js"></script>
|
|
218
|
-
<script src="js/standard/hitcircle.js"></script>
|
|
219
|
-
<script src="js/standard/slider.js"></script>
|
|
220
|
-
<script src="js/standard/curve/curve.js"></script>
|
|
221
|
-
<script src="js/standard/curve/equaldistancemulticurve.js"></script>
|
|
222
|
-
<script src="js/standard/curve/linearbezier.js"></script>
|
|
223
|
-
<script src="js/standard/curve/catmullcurve.js"></script>
|
|
224
|
-
<script src="js/standard/curve/curvetype.js"></script>
|
|
225
|
-
<script src="js/standard/curve/bezier2.js"></script>
|
|
226
|
-
<script src="js/standard/curve/centripetalcatmullrom.js"></script>
|
|
227
|
-
<script src="js/standard/curve/circumstancedcircle.js"></script>
|
|
228
|
-
<script src="js/standard/spinner.js"></script>
|
|
229
|
-
|
|
230
|
-
<script src="js/taiko/taiko.js"></script>
|
|
231
|
-
<script src="js/taiko/donkat.js"></script>
|
|
232
|
-
<script src="js/taiko/drumroll.js"></script>
|
|
233
|
-
<script src="js/taiko/shaker.js"></script>
|
|
234
|
-
|
|
235
|
-
<script src="js/catch/LegacyRandom.js"></script>
|
|
236
|
-
<script src="js/catch/catch.js"></script>
|
|
237
|
-
<script src="js/catch/fruit.js"></script>
|
|
238
|
-
<script src="js/catch/bananashower.js"></script>
|
|
239
|
-
<script src="js/catch/juicestream.js"></script>
|
|
240
|
-
<script src="js/catch/PalpableCatchHitObject.js"></script>
|
|
241
|
-
|
|
242
|
-
<script src="js/mania/mania.js"></script>
|
|
243
|
-
<script src="js/mania/hitnote.js"></script>
|
|
244
|
-
<script src="js/mania/holdnote.js"></script>
|
|
245
|
-
|
|
246
|
-
<script src="js/preview.js"></script>
|
|
247
|
-
<script src="gif.js/gif.js"></script>
|
|
248
|
-
|
|
249
|
-
<script>
|
|
250
|
-
document.addEventListener('DOMContentLoaded', function () {
|
|
251
|
-
const beatmapInput = document.getElementById('beatmapInput');
|
|
252
|
-
const scaleInput = document.getElementById('scaleInput');
|
|
253
|
-
const timeSpanInput = document.getElementById('timeSpanInput');
|
|
254
|
-
const startTimeInput = document.getElementById('startTimeInput');
|
|
255
|
-
const durationInput = document.getElementById('durationInput');
|
|
256
|
-
const qualityInput = document.getElementById('qualityInput');
|
|
257
|
-
const usePreviewTimeCheckbox = document.getElementById('usePreviewTimeCheckbox');
|
|
258
|
-
const generateBtn = document.getElementById('generateBtn');
|
|
259
|
-
const status = document.getElementById('status');
|
|
260
|
-
const progressContainer = document.getElementById('progressContainer');
|
|
261
|
-
const progressBar = document.getElementById('progressBar');
|
|
262
|
-
const result = document.getElementById('result');
|
|
263
|
-
|
|
264
|
-
generateBtn.addEventListener('click', function () {
|
|
265
|
-
const beatmapID = beatmapInput.value.trim();
|
|
266
|
-
const scaleValue = parseFloat(scaleInput.value.trim());
|
|
267
|
-
const timeSpanValue = parseInt(timeSpanInput.value.trim());
|
|
268
|
-
const startTimeValue = parseInt(startTimeInput.value.trim());
|
|
269
|
-
const durationValue = parseInt(durationInput.value.trim());
|
|
270
|
-
const qualityValue = parseInt(qualityInput.value.trim());
|
|
271
|
-
const usePreviewTime = usePreviewTimeCheckbox.checked;
|
|
272
|
-
|
|
273
|
-
// 验证输入
|
|
274
|
-
if (isNaN(scaleValue) || scaleValue <= 0 || scaleValue > 1) {
|
|
275
|
-
status.textContent = '请输入有效的缩放比例 (0 < 比例 ≤ 1)';
|
|
276
|
-
status.style.color = '#ff6666';
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
if (!beatmapID) {
|
|
280
|
-
status.textContent = '请输入有效的谱面ID';
|
|
281
|
-
status.style.color = '#ff6666';
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
if (isNaN(timeSpanValue) || timeSpanValue < 15) {
|
|
285
|
-
status.textContent = '请输入有效的帧间隔时间';
|
|
286
|
-
status.style.color = '#ff6666';
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
if (isNaN(startTimeValue) || (startTimeValue < 0 && startTimeValue !== -1)) {
|
|
290
|
-
status.textContent = '请输入有效的开始时间';
|
|
291
|
-
status.style.color = '#ff6666';
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
if (isNaN(durationValue) || (durationValue < 0 && durationValue !== -1)) {
|
|
295
|
-
status.textContent = '请输入有效的持续时间';
|
|
296
|
-
status.style.color = '#ff6666';
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
if (isNaN(qualityValue) || qualityValue < 1 || qualityValue > 30) {
|
|
300
|
-
status.textContent = '请输入有效的GIF质量 (1-30)';
|
|
301
|
-
status.style.color = '#ff6666';
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
generateGIF(beatmapID, scaleValue, timeSpanValue, startTimeValue, durationValue, qualityValue, usePreviewTime);
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
function generateGIF(beatmapID, scaleValue, timeSpanValue, startTimeValue, durationValue, qualityValue, usePreviewTime) {
|
|
309
|
-
status.textContent = '正在获取谱面数据...';
|
|
310
|
-
status.style.color = '#fff';
|
|
311
|
-
progressContainer.style.display = 'block';
|
|
312
|
-
progressBar.style.width = '10%';
|
|
313
|
-
|
|
314
|
-
// 清除之前的结果
|
|
315
|
-
result.innerHTML = '';
|
|
316
|
-
|
|
317
|
-
var osuFileUrl = "https://osu.direct/api/osu/" + beatmapID;
|
|
318
|
-
!async function () {
|
|
319
|
-
var self = this;
|
|
320
|
-
let osufile;
|
|
321
|
-
try {
|
|
322
|
-
const response = await fetch(osuFileUrl);
|
|
323
|
-
osufile = await response.text();
|
|
324
|
-
}
|
|
325
|
-
catch (e) {
|
|
326
|
-
console.log(e);
|
|
327
|
-
document.title = "从osu.direct获取谱面文件失败";
|
|
328
|
-
}
|
|
329
|
-
if (!osufile) {
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
var preview = new Preview(scaleValue);
|
|
334
|
-
preview.load(osufile, function () {
|
|
335
|
-
status.textContent = '加载帧...';
|
|
336
|
-
progressBar.style.width = '30%';
|
|
337
|
-
|
|
338
|
-
// 计算实际开始时间
|
|
339
|
-
let actualStartTime;
|
|
340
|
-
|
|
341
|
-
if (usePreviewTime && preview.previewTime >= 0) {
|
|
342
|
-
// 检查预览时间是否有效
|
|
343
|
-
const previewEndTime = durationValue === -1 ? preview.endTime : preview.previewTime + durationValue;
|
|
344
|
-
|
|
345
|
-
if (previewEndTime <= preview.endTime) {
|
|
346
|
-
// 使用谱面预览时间
|
|
347
|
-
actualStartTime = preview.previewTime;
|
|
348
|
-
status.textContent += ' (使用谱面预览时间)';
|
|
349
|
-
} else {
|
|
350
|
-
// 预览时间加上持续时间超过谱面结束时间,使用用户指定的开始时间
|
|
351
|
-
actualStartTime = startTimeValue === -1 ? preview.startTime : Math.max(startTimeValue, 0);
|
|
352
|
-
}
|
|
353
|
-
} else {
|
|
354
|
-
// 使用用户指定的开始时间
|
|
355
|
-
actualStartTime = startTimeValue === -1 ? preview.startTime : Math.max(startTimeValue, 0);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const actualEndTime = durationValue === -1 ? preview.endTime : Math.min(actualStartTime + durationValue, preview.endTime);
|
|
359
|
-
|
|
360
|
-
var gif = new GIF({
|
|
361
|
-
workers: 4,
|
|
362
|
-
workerScript: './gif.js/gif.worker.js',
|
|
363
|
-
quality: qualityValue,
|
|
364
|
-
width: preview.screen.width * scaleValue,
|
|
365
|
-
height: preview.screen.height * scaleValue,
|
|
366
|
-
//transparent: "0x000000",
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
const totalFrames = Math.ceil((actualEndTime - actualStartTime) / timeSpanValue);
|
|
370
|
-
let currentFrame = 0;
|
|
371
|
-
|
|
372
|
-
// 添加帧
|
|
373
|
-
while (currentFrame <= totalFrames) {
|
|
374
|
-
const t = actualStartTime + currentFrame * timeSpanValue;
|
|
375
|
-
preview.at(t);
|
|
376
|
-
|
|
377
|
-
gif.addFrame(preview.ctx, {
|
|
378
|
-
copy: true,
|
|
379
|
-
delay: timeSpanValue
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
currentFrame++;
|
|
383
|
-
progressBar.style.width = (30 + (currentFrame / totalFrames) * 60) + '%';
|
|
384
|
-
}
|
|
385
|
-
// 所有帧已添加
|
|
386
|
-
progressBar.style.width = '95%';
|
|
387
|
-
status.textContent = '最终处理中...';
|
|
388
|
-
|
|
389
|
-
gif.on('finished', function (blob) {
|
|
390
|
-
const url = URL.createObjectURL(blob);
|
|
391
|
-
|
|
392
|
-
const img = document.createElement('img');
|
|
393
|
-
img.id = 'img';
|
|
394
|
-
img.src = url;
|
|
395
|
-
img.alt = '生成的GIF预览';
|
|
396
|
-
|
|
397
|
-
const downloadLink = document.createElement('a');
|
|
398
|
-
downloadLink.href = url;
|
|
399
|
-
downloadLink.download = `osu-preview-${beatmapID}.gif`;
|
|
400
|
-
downloadLink.textContent = '下载GIF';
|
|
401
|
-
downloadLink.className = 'download-btn';
|
|
402
|
-
downloadLink.style.display = 'inline-block';
|
|
403
|
-
downloadLink.style.marginTop = '15px';
|
|
404
|
-
downloadLink.style.padding = '10px 15px';
|
|
405
|
-
downloadLink.style.backgroundColor = '#ff66aa';
|
|
406
|
-
downloadLink.style.color = 'white';
|
|
407
|
-
downloadLink.style.borderRadius = '5px';
|
|
408
|
-
downloadLink.style.textDecoration = 'none';
|
|
409
|
-
|
|
410
|
-
result.appendChild(img);
|
|
411
|
-
result.appendChild(document.createElement('br'));
|
|
412
|
-
result.appendChild(downloadLink);
|
|
413
|
-
|
|
414
|
-
progressBar.style.width = '100%';
|
|
415
|
-
status.textContent = 'GIF生成完成!';
|
|
416
|
-
|
|
417
|
-
//progressContainer.style.display = 'none';
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
gif.render();
|
|
421
|
-
|
|
422
|
-
}, function (error) {
|
|
423
|
-
status.textContent = '错误: ' + error;
|
|
424
|
-
status.style.color = '#ff6666';
|
|
425
|
-
progressContainer.style.display = 'none';
|
|
426
|
-
});
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}();
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
</script>
|
|
435
|
-
</body>
|
|
436
|
-
|
|
437
|
-
</html>
|
|
File without changes
|