merge upstream
This commit is contained in:
+5
-34
@@ -36,11 +36,6 @@
|
|||||||
</script>
|
</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import "/script/rdview.js";
|
import "/script/rdview.js";
|
||||||
import {
|
|
||||||
Extensions,
|
|
||||||
IconStyle,
|
|
||||||
Point,
|
|
||||||
} from "/script/Extensions.js";
|
|
||||||
|
|
||||||
function escapeHtml(unsafe) {
|
function escapeHtml(unsafe) {
|
||||||
return unsafe
|
return unsafe
|
||||||
@@ -58,30 +53,7 @@
|
|||||||
...{
|
...{
|
||||||
markdown: {
|
markdown: {
|
||||||
renderer: {
|
renderer: {
|
||||||
code: function (code, lang) {
|
code: function (code, lang) {if (
|
||||||
if (
|
|
||||||
lang.trim().startsWith(
|
|
||||||
"rdview2",
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
const langParts = lang
|
|
||||||
.trim().split(" ");
|
|
||||||
const width =
|
|
||||||
parseInt(
|
|
||||||
langParts[1],
|
|
||||||
) || 8;
|
|
||||||
const height =
|
|
||||||
parseInt(
|
|
||||||
langParts[2],
|
|
||||||
) || 4;
|
|
||||||
const scale =
|
|
||||||
(parseFloat(
|
|
||||||
langParts[3],
|
|
||||||
) || 1) * 2;
|
|
||||||
return `<div class="rdview2-container"><canvas class="rdview2-canvas" image-rendering: pixelated;" data-width="${width}" data-height="${height}" data-scale="${scale}"" data='${
|
|
||||||
JSON.stringify(code)
|
|
||||||
}'></canvas></div>`;
|
|
||||||
} else if (
|
|
||||||
lang.trim().startsWith(
|
lang.trim().startsWith(
|
||||||
"rdview",
|
"rdview",
|
||||||
)
|
)
|
||||||
@@ -126,7 +98,8 @@
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script src="/script/docsify.min.js"></script>
|
<script type="module" src="./script/special.js"></script>
|
||||||
|
<!-- <script src="/script/docsify.min.js"></script> -->
|
||||||
<script src="/script/zoom-image.min.js"></script>
|
<script src="/script/zoom-image.min.js"></script>
|
||||||
<script src="/script/search.min.js"></script>
|
<script src="/script/search.min.js"></script>
|
||||||
<script src="/script/emoji.min.js"></script>
|
<script src="/script/emoji.min.js"></script>
|
||||||
@@ -134,10 +107,8 @@
|
|||||||
<script src="/script/switchLightDarkMode.js"></script>
|
<script src="/script/switchLightDarkMode.js"></script>
|
||||||
<script src="/script/otto.js"></script>
|
<script src="/script/otto.js"></script>
|
||||||
<script src="/script/custommethod-search.js"></script>
|
<script src="/script/custommethod-search.js"></script>
|
||||||
<script
|
<!-- <script
|
||||||
src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-yaml.js"
|
src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-yaml.js"
|
||||||
></script>
|
></script> -->
|
||||||
<script type="module" src="/script/special.js"></script>
|
|
||||||
<script type="module" src="/script/rdview2.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -20,4 +20,72 @@ g 1 1 5 4 #0ff{
|
|||||||
};
|
};
|
||||||
</textarea></div></div>
|
</textarea></div></div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="rdview2"><div class="canvas"></div><div class="editor"><div class="number"></div><textarea class="area" spellcheck="false" placeholder="Enter code here">
|
||||||
|
{ "bar": 1, "beat": 1, "y": 0, "type": "MoveRoom", "if": "1d0", "roomPosition": [50, 50], "scale": [70, 100], "angle": 20, "pivot": [0, 0], "duration": 1, "ease": "Linear" },
|
||||||
|
{ "bar": 1, "beat": 1, "y": 6, "type": "AddOneshotBeat", "pulseType": "Triangle", "tick": 2, "subdivisions": 2, "subdivSound": true },
|
||||||
|
{ "bar": 1, "beat": 2, "y": 0, "type": "AddClassicBeat", "tick": 0.5, "swing": 0, "hold": 0 },
|
||||||
|
{ "bar": 1, "beat": 2, "y": 1, "type": "ReorderRooms", "order": [1, 3, 2, 0] },
|
||||||
|
{ "bar": 1, "beat": 2, "y": 5, "type": "SetSpeed", "speed": 1, "duration": 0, "ease": "Linear" },
|
||||||
|
{ "bar": 1, "beat": 3, "y": 3, "type": "AddOneshotBeat", "pulseType": "Wave", "tick": 2 },
|
||||||
|
{ "bar": 1, "beat": 5, "y": 1, "type": "SetBeatsPerMinute", "if": "~3d0", "beatsPerMinute": 100 },
|
||||||
|
{ "bar": 1, "beat": 5, "y": 5, "type": "SetGameSound", "soundType": "SmallMistake", "filename": "" },
|
||||||
|
{ "bar": 1, "beat": 5, "y": 6, "type": "SetHeartExplodeInterval", "intervalType": "GatherAndCeil", "interval": 1 },
|
||||||
|
{ "bar": 1, "beat": 4, "y": 4, "type": "AddOneshotBeat", "pulseType": "Wave", "freezeBurnMode": "Burnshot", "interval": 2, "tick": 1 },
|
||||||
|
{ "bar": 1, "beat": 5, "y": 2, "type": "SetBackgroundColor", "rooms": [0], "backgroundType": "Color", "color": "FFFFFFFF", "filter": "NearestNeighbor" },
|
||||||
|
{ "bar": 1, "beat": 7, "y": 0, "type": "AddClassicBeat", "tag": "1", "tick": 0.5, "hold": 1, "swing": 0.5, "setXs": "NoChange" },
|
||||||
|
{ "bar": 1, "beat": 7, "y": 6, "type": "AddOneshotBeat", "pulseType": "Wave", "freezeBurnMode": "Freezeshot", "interval": 2, "tick": 1, "delay": 0.5, "skipshot": true },
|
||||||
|
{ "bar": 1, "beat": 8, "y": 4, "type": "SetCountingSound", "voiceSource": "JyiCount", "enabled": true, "volume": 100, "subdivOffset": 0.5 },
|
||||||
|
{ "bar": 1, "beat": 8, "y": 1, "type": "SetVisible", "visible": true },
|
||||||
|
{ "bar": 1, "beat": 8, "y": 2, "type": "ShowStatusSign", "if": "1d0", "text": "RhythmBase.View!", "duration": 5, "useBeats": true, "narrate": true },
|
||||||
|
{ "bar": 1, "beat": 8, "y": 3, "type": "Tint", "border": "Glow", "borderColor": "FF0000FF", "tint": true, "tintColor": "001BFFFF", "opacity": 100, "duration": 3, "ease": "Linear" },
|
||||||
|
{ "bar": 1, "beat": 8, "y": 5, "type": "TextExplosion", "rooms": [0], "text": "Explosion", "color": "000000", "mode": "OneColor", "direction": "Left", "speed": 100, "ease": "Linear" },
|
||||||
|
{ "bar": 2, "beat": 2, "y": 5, "type": "SayReadyGetSetGo", "tag": "1", "rooms": [4], "phraseToSay": "JustSayRea", "voiceSource": "Nurse", "tick": 1, "volume": 100 },
|
||||||
|
{ "bar": 2, "beat": 3, "y": 4, "type": "SetOneshotWave", "waveType": "BoomAndRush", "height": 100, "width": 100 },
|
||||||
|
{ "bar": 2, "beat": 3, "y": 1, "type": "Move", "position": [50, 50], "duration": 1, "ease": "Linear" },
|
||||||
|
{ "bar": 2, "beat": 3, "y": 3, "type": "PlayAnimation", "expression": "neutral" },
|
||||||
|
{ "bar": 2, "beat": 3, "y": 2, "type": "NewWindowDance", "tab": "Windows", "preset": "Move", "position": [50, 50], "reference": "Center", "easingDuration": 1, "ease": "Linear" },
|
||||||
|
{ "bar": 2, "beat": 5, "y": 0, "type": "BassDrop", "if": "1&~2d0", "rooms": [0], "strength": "High" },
|
||||||
|
{ "bar": 2, "beat": 5, "y": 1, "type": "ShowDialogue", "rooms": [4], "text": "Samurai_Happy: SAMURAI!", "speed": 1, "panelSide": "Bottom", "portraitSide": "Left", "playTextSounds": true },
|
||||||
|
{ "bar": 2, "beat": 5, "y": 2, "type": "FloatingText", "rooms": [0], "id": 0, "text": "等/呀/等/得/好/心/慌……", "times": "", "color": "00F4FFFF", "outlineColor": "0011FFFF", "textPosition": [50, 50], "font": "Default", "size": 8, "angle": 0, "showChildren": true, "fadeOutRate": 3, "mode": "FadeOut", "anchor": "MiddleCenter", "narrate": true, "narrationCategory": "Subtitles" },
|
||||||
|
{ "bar": 2, "beat": 6, "y": 4, "type": "SetPlayStyle", "PlayStyle": "Normal", "NextBar": 1, "Relative": true },
|
||||||
|
{ "bar": 2, "beat": 7, "y": 6, "type": "SetHandOwner", "rooms": [0], "hand": "Right", "character": "Player" },
|
||||||
|
{ "bar": 2, "beat": 8, "y": 3, "type": "SetBeatSound", "row": 0, "sound": {"filename": "Shaker"} },
|
||||||
|
{ "bar": 2, "beat": 8, "y": 4, "type": "TintRows", "if" : "1&~2d1", "rooms": [0], "border": "Outline", "borderColor": "2BFF00FF", "tint": true, "tintColor": "007E0EFF", "opacity": 100, "duration": 0, "ease": "Linear", "effect": "None" },
|
||||||
|
{ "bar": 3, "beat": 1, "y": 2, "type": "PulseCamera", "rooms": [0], "strength": 1, "count": 1, "frequency": 1 },
|
||||||
|
{ "bar": 3, "beat": 1, "y": 1, "type": "ShowHands", "rooms": [0], "hand": "Right", "action": "Show", "extent": "Full", "forceRaise": true, "align": false, "instant": false },
|
||||||
|
{ "bar": 3, "beat": 1, "y": 0, "type": "MoveCamera", "rooms": [0], "cameraPosition": [50, 50], "duration": 1, "ease": "Linear" },
|
||||||
|
{ "bar": 2, "beat": 7, "y": 5, "type": "SetCrotchetsPerBar", "crotchetsPerBar": 7, "visualBeatMultiplier": 1 },
|
||||||
|
{ "bar": 2, "beat": 6, "y": 3, "type": "SetRoomPerspective", "cornerPositions": [[0, 0], [100, 0], [0, 100], [100, 100]], "duration": 1, "ease": "Linear" },
|
||||||
|
{ "bar": 3, "beat": 3, "y": 2, "type": "SayReadyGetSetGo", "if": "1d0", "rooms": [4], "phraseToSay": "SayGetSetOne", "voiceSource": "Nurse", "tick": 1, "volume": 100 },
|
||||||
|
{ "bar": 3, "beat": 3, "y": 6, "type": "FlipScreen", "rooms": [0], "flipX": false, "flipY": true },
|
||||||
|
{ "bar": 3, "beat": 4, "y": 6, "type": "InvertColors", "rooms": [0], "enable": true },
|
||||||
|
{ "bar": 3, "beat": 6, "y": 6, "type": "SayReadyGetSetGo", "rooms": [4], "phraseToSay": "JustSayAndStop", "voiceSource": "Nurse", "tick": 1, "volume": 100 },
|
||||||
|
{ "bar": 3, "beat": 5, "y": 3, "type": "DesktopColor", "endColor": "00ffff", "duration": 2, "ease": "Linear" },
|
||||||
|
{ "bar": 3, "beat": 5, "y": -1, "type": "AdvanceText", "id": 0, "text": "text 字段不存在于原事件中,但是 RDView 提供了支持。" },
|
||||||
|
{ "bar": 3, "beat": 5.5, "y": -1, "type": "PulseFreeTimeBeat", "row": 0, "action": "Increment", "hold": 0 },
|
||||||
|
{ "bar": 3, "beat": 8, "y": 4, "type": "NarrateRowInfo", "row": 0, "infoType": "Connect", "soundOnly": false, "narrateSkipBeats": "On", "skipsUnstable": false, "customPlayer": "AutoDetect" },
|
||||||
|
{ "bar": 4, "beat": 1, "y": 2, "type": "PaintHands", "rooms": [0], "hands": "Right", "border": "Outline", "borderColor": "AFFF00FF", "tint": true, "tintColor": "4FAF00FF", "opacity": 100, "duration": 0 },
|
||||||
|
{ "bar": 3, "beat": 8, "y": 3, "type": "HideWindow", "show": false },
|
||||||
|
{ "bar": 3, "beat": 8, "y": 5, "type": "Comment", "tab": "Actions", "text": "五彩斑斓的黑", "color": "8C00FF", "show": false },
|
||||||
|
{ "bar": 4, "beat": 1, "y": 6, "type": "SetWindowContent", "contentMode": "OnTop" },
|
||||||
|
{ "bar": 4, "beat": 2, "y": 4, "type": "PlaySong", "song": {"filename": "sndOrientalTechno"}, "bpm": 100, "loop": false },
|
||||||
|
{ "bar": 4, "beat": 1, "y": 4, "type": "CallCustomMethod", "methodName": "", "executionTime": "OnBar", "sortOffset": 0 },
|
||||||
|
{ "bar": 4, "beat": 2, "y": 2, "type": "FadeRoom", "opacity": 100, "duration": 2, "ease": "Linear" },
|
||||||
|
{ "bar": 4, "beat": 2, "y": 6, "type": "SetRowXs", "pattern": "-x--x-", "syncoBeat": 3, "syncoSwing": 0, "syncoVolume": 70, "syncoPitch": 100, "syncoStyle": "Chirp", "syncoPlayModifierSound": true, "syncoPlayModifierOffSound": true },
|
||||||
|
{ "bar": 4, "beat": 3, "y": 3, "type": "ChangeCharacter", "row": 0, "character": "Samurai", "transition": "Instant" },
|
||||||
|
{ "bar": 4, "beat": 5, "y": 2, "type": "ShowRooms", "rooms": [1, 3], "heights": [0, 0, 0, 0], "transitionTime": 1, "ease": "InOutSine" },
|
||||||
|
{ "bar": 4, "beat": 6, "y": 6, "type": "RenameWindow", "action": "Set", "text": "Minecraft 1.21.1 NeoForge" },
|
||||||
|
{ "bar": 4, "beat": 7, "y": 2, "type": "SetVFXPreset", "rooms": [0], "preset": "Vignette", "enable": true },
|
||||||
|
{ "bar": 4, "beat": 7, "y": 4, "type": "SetTheme", "rooms": [0], "preset": "None", "skipPaintEffects": false },
|
||||||
|
{ "bar": 4, "beat": 7, "y": 3, "type": "PlaySound", "sound": {"filename": "Shaker"}, "customSoundType": "CueSound" },
|
||||||
|
{ "bar": 4, "beat": 7, "y": 5, "type": "SetRoomContentMode", "mode": "Center" },
|
||||||
|
{ "bar": 4, "beat": 8, "y": 6, "type": "TagAction", "Action": "Run", "Tag": "Nothing" },
|
||||||
|
{ "bar": 5, "beat": 1, "y": 3, "type": "SetClapSounds", "rowType": "Classic", "p1Sound": {"filename": "ClapHit"} },
|
||||||
|
{ "bar": 5, "beat": 1, "y": 4, "type": "ChangePlayersRows", "playerMode": "OneOrTwoPlayers", "players": ["NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange", "NoChange"], "cpuMarkers": ["Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto", "Otto"] },
|
||||||
|
{ "bar": 5, "beat": 1, "y": 2, "type": "PulseCamera", "rooms": [0], "strength": 1, "count": 1, "frequency": 1 },
|
||||||
|
{ "bar": 5, "beat": 1, "y": 5, "type": "ReadNarration", "text": "一名身穿红色盔甲的武士跟着音乐节拍点头。", "category": "Description" }
|
||||||
|
</textarea></div></div>
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
# 更新信息
|
# 更新信息
|
||||||
|
|
||||||
|
#### 2026-01-14
|
||||||
|
- 制作人员表增加了
|
||||||
|
- RDView 对正式版编辑器新特性的部分适配
|
||||||
|
- 正在逐步同步 RDView2(RhythmBase.View) 的适配
|
||||||
|
|
||||||
#### 2025-11-29
|
#### 2025-11-29
|
||||||
- 调整目录结构
|
- 调整目录结构
|
||||||
- 双人模式措辞更改
|
- 双人模式措辞更改
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 6.5 KiB |
File diff suppressed because it is too large
Load Diff
+1412
File diff suppressed because it is too large
Load Diff
@@ -1,143 +0,0 @@
|
|||||||
import { Extensions, IconStyle } from "/script/Extensions.js";
|
|
||||||
function rend() {
|
|
||||||
const codeBlocks = document.querySelectorAll("canvas.rdview2-canvas");
|
|
||||||
codeBlocks.forEach((block) => {
|
|
||||||
// 清理旧的实例
|
|
||||||
if (block.cleanup) {
|
|
||||||
block.cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
const width = block.getAttribute("data-width") || 8;
|
|
||||||
const height = block.getAttribute("data-height") || 4;
|
|
||||||
const scale = block.getAttribute("data-scale") || 2;
|
|
||||||
const data = block.getAttribute("data");
|
|
||||||
const ctx = block.getContext("2d", { alpha: false, desynchronized: true });
|
|
||||||
block.width = width * scale * 14;
|
|
||||||
block.height = height * scale * 14;
|
|
||||||
if (!data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const jsonData = JSON.parse(`[${JSON.parse(data)}]`);
|
|
||||||
|
|
||||||
let lastActive = false;
|
|
||||||
let evtId = 0;
|
|
||||||
let frameId = null;
|
|
||||||
let cachedRect = null;
|
|
||||||
let mdown = false;
|
|
||||||
|
|
||||||
const eventPositions = jsonData.map(evt => ({
|
|
||||||
evt,
|
|
||||||
x: ((evt.beat ?? 1) - 1) * scale * 14,
|
|
||||||
y: (evt.y ?? 0) * scale * 14
|
|
||||||
}));
|
|
||||||
|
|
||||||
const style = new IconStyle();
|
|
||||||
style.Scale = scale;
|
|
||||||
|
|
||||||
const updateRect = () => {
|
|
||||||
cachedRect = block.getBoundingClientRect();
|
|
||||||
};
|
|
||||||
updateRect();
|
|
||||||
|
|
||||||
let rectTimeout;
|
|
||||||
const debouncedUpdateRect = () => {
|
|
||||||
clearTimeout(rectTimeout);
|
|
||||||
rectTimeout = setTimeout(updateRect, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
const observer = new ResizeObserver(debouncedUpdateRect);
|
|
||||||
observer.observe(block);
|
|
||||||
|
|
||||||
window.addEventListener("resize", debouncedUpdateRect, { passive: true });
|
|
||||||
window.addEventListener("scroll", debouncedUpdateRect, { passive: true });
|
|
||||||
|
|
||||||
block.render = (x, y, active) => {
|
|
||||||
const point = { x, y };
|
|
||||||
let currentEvtId = null;
|
|
||||||
for (let i = 0; i < eventPositions.length; i++) {
|
|
||||||
const { evt } = eventPositions[i];
|
|
||||||
if (evt.area?.contains(point)) {
|
|
||||||
currentEvtId = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentEvtId === evtId && active === lastActive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
evtId = currentEvtId;
|
|
||||||
lastActive = active;
|
|
||||||
|
|
||||||
ctx.clearRect(0, 0, block.width, block.height);
|
|
||||||
|
|
||||||
for (const { evt, x: posX, y: posY } of eventPositions) {
|
|
||||||
const isHovered = evt.area?.contains(point) ?? false;
|
|
||||||
style.Hover = isHovered;
|
|
||||||
style.Active = isHovered ? active : false;
|
|
||||||
evt.area = Extensions.DrawEventIcon(ctx, evt, { x: posX, y: posY }, style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const throttledRender = (x, y, active) => {
|
|
||||||
if (frameId !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
frameId = requestAnimationFrame(() => {
|
|
||||||
block.render(x, y, active);
|
|
||||||
frameId = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const getMousePos = (e) => ({
|
|
||||||
x: e.clientX - cachedRect.left,
|
|
||||||
y: e.clientY - cachedRect.top
|
|
||||||
});
|
|
||||||
|
|
||||||
block.addEventListener("mousemove", (e) => {
|
|
||||||
const { x, y } = getMousePos(e);
|
|
||||||
console.log(x, y);
|
|
||||||
throttledRender(x, y, mdown);
|
|
||||||
}, { passive: true });
|
|
||||||
|
|
||||||
block.addEventListener("mousedown", (e) => {
|
|
||||||
const { x, y } = getMousePos(e);
|
|
||||||
mdown = true;
|
|
||||||
block.render(x, y, mdown);
|
|
||||||
});
|
|
||||||
|
|
||||||
block.addEventListener("mouseup", (e) => {
|
|
||||||
const { x, y } = getMousePos(e);
|
|
||||||
mdown = false;
|
|
||||||
block.render(x, y, mdown);
|
|
||||||
});
|
|
||||||
|
|
||||||
block.addEventListener("mouseleave", () => {
|
|
||||||
if (frameId !== null) {
|
|
||||||
cancelAnimationFrame(frameId);
|
|
||||||
frameId = null;
|
|
||||||
}
|
|
||||||
mdown = false;
|
|
||||||
evtId = null;
|
|
||||||
lastActive = false;
|
|
||||||
block.render(-1, -1, mdown);
|
|
||||||
}, { passive: true });
|
|
||||||
|
|
||||||
block.cleanup = () => {
|
|
||||||
observer.disconnect();
|
|
||||||
window.removeEventListener("resize", debouncedUpdateRect);
|
|
||||||
window.removeEventListener("scroll", debouncedUpdateRect);
|
|
||||||
clearTimeout(rectTimeout);
|
|
||||||
if (frameId !== null) {
|
|
||||||
cancelAnimationFrame(frameId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
block.render(-1, -1, mdown);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.$docsify.plugins = [].concat(window.$docsify.plugins, function (hook) {
|
|
||||||
hook.doneEach(function () {
|
|
||||||
rend();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
+237
-57
@@ -1,3 +1,5 @@
|
|||||||
|
import { createElementEvent } from "./View.js";
|
||||||
|
|
||||||
let curx = 0;
|
let curx = 0;
|
||||||
let cury = 0;
|
let cury = 0;
|
||||||
let rowx;
|
let rowx;
|
||||||
@@ -21,7 +23,7 @@ let positions = {
|
|||||||
"r5": { "y": 78, "name": "二轨时的第二轨/四轨时的第二轨" },
|
"r5": { "y": 78, "name": "二轨时的第二轨/四轨时的第二轨" },
|
||||||
"r6": { "y": 57, "name": "三轨时的第一轨" },
|
"r6": { "y": 57, "name": "三轨时的第一轨" },
|
||||||
"r7": { "y": 36, "name": "四轨时的第一轨" },
|
"r7": { "y": 36, "name": "四轨时的第一轨" },
|
||||||
}
|
};
|
||||||
|
|
||||||
function themePosition() {
|
function themePosition() {
|
||||||
let theme_positions = document.getElementById("theme-positions");
|
let theme_positions = document.getElementById("theme-positions");
|
||||||
@@ -61,45 +63,74 @@ function themePosition() {
|
|||||||
rowx = null;
|
rowx = null;
|
||||||
columny = null;
|
columny = null;
|
||||||
for (let key in positions) {
|
for (let key in positions) {
|
||||||
if (positions[key].x !== null && Math.abs(x - positions[key].x) < 5)
|
if (
|
||||||
|
positions[key].x !== null && Math.abs(x - positions[key].x) < 5
|
||||||
|
) {
|
||||||
rowx = positions[key].x;
|
rowx = positions[key].x;
|
||||||
if (positions[key].y !== null && Math.abs(y - positions[key].y) < 5)
|
}
|
||||||
|
if (
|
||||||
|
positions[key].y !== null && Math.abs(y - positions[key].y) < 5
|
||||||
|
) {
|
||||||
columny = positions[key].y;
|
columny = positions[key].y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rowx) {
|
if (rowx) {
|
||||||
perx.innerText = (rowx / 3.52).toFixed(2) + "%"
|
perx.innerText = (rowx / 3.52).toFixed(2) + "%";
|
||||||
perx.classList.add("c")
|
perx.classList.add("c");
|
||||||
pxx.innerText = rowx + "px"
|
pxx.innerText = rowx + "px";
|
||||||
pxx.classList.add("c")
|
pxx.classList.add("c");
|
||||||
}
|
} else {
|
||||||
else {
|
perx.innerText = x_percent.toFixed(2) + "%";
|
||||||
perx.innerText = x_percent.toFixed(2) + "%"
|
perx.classList.remove("c");
|
||||||
perx.classList.remove("c")
|
pxx.innerText = x + "px";
|
||||||
pxx.innerText = x + "px"
|
pxx.classList.remove("c");
|
||||||
pxx.classList.remove("c")
|
|
||||||
}
|
}
|
||||||
if (columny) {
|
if (columny) {
|
||||||
pery.innerText = (100 - columny / 1.98).toFixed(2) + "%"
|
pery.innerText = (100 - columny / 1.98).toFixed(2) + "%";
|
||||||
pery.classList.add("c")
|
pery.classList.add("c");
|
||||||
pxy.innerText = 198 - columny + "px"
|
pxy.innerText = 198 - columny + "px";
|
||||||
pxy.classList.add("c")
|
pxy.classList.add("c");
|
||||||
}
|
} else {
|
||||||
else {
|
pery.innerText = (100 - y_percent).toFixed(2) + "%";
|
||||||
pery.innerText = (100 - y_percent).toFixed(2) + "%"
|
pery.classList.remove("c");
|
||||||
pery.classList.remove("c")
|
pxy.innerText = 198 - y + "px";
|
||||||
pxy.innerText = 198 - y + "px"
|
pxy.classList.remove("c");
|
||||||
pxy.classList.remove("c")
|
|
||||||
}
|
}
|
||||||
infobox.style.right = "calc(" + (100 - x_percent) + "% + 10px)";
|
infobox.style.right = "calc(" + (100 - x_percent) + "% + 10px)";
|
||||||
infobox.style.top = "calc(" + (y_percent) + "% + 10px)";
|
infobox.style.top = "calc(" + y_percent + "% + 10px)";
|
||||||
selectbox.style.left = rowx ? (rowx / 3.52 - 3.41) + "%" : columny ? "0" : "calc(" + x_percent + "% - 3px";
|
selectbox.style.left = rowx
|
||||||
selectbox.style.bottom = columny ? (100 - columny / 1.98 - 5.305) + "%" : rowx ? "0" : "calc(" + (100 - y_percent) + "% - 3px)";
|
? (rowx / 3.52 - 3.41) + "%"
|
||||||
|
: columny
|
||||||
|
? "0"
|
||||||
|
: "calc(" + x_percent + "% - 3px";
|
||||||
|
selectbox.style.bottom = columny
|
||||||
|
? (100 - columny / 1.98 - 5.305) + "%"
|
||||||
|
: rowx
|
||||||
|
? "0"
|
||||||
|
: "calc(" + (100 - y_percent) + "% - 3px)";
|
||||||
selectbox.style.width = rowx ? "6.82%" : columny ? "100%" : "6px";
|
selectbox.style.width = rowx ? "6.82%" : columny ? "100%" : "6px";
|
||||||
selectbox.style.height = columny ? "10.61%" : rowx ? "100%" : "6px";
|
selectbox.style.height = columny ? "10.61%" : rowx ? "100%" : "6px";
|
||||||
let rowname = rowx ? positions[Object.keys(positions).find(key => positions[key].x === rowx)].name : "";
|
let rowname = rowx
|
||||||
let columnname = columny ? positions[Object.keys(positions).find(key => positions[key].y === columny)].name : "";
|
? positions[
|
||||||
theme_positions.querySelector(".other").innerText = rowname && columnname ? columnname + "上的" + rowname : rowname ? rowname : columnname ? columnname : "";
|
Object.keys(positions).find((key) => positions[key].x === rowx)
|
||||||
|
].name
|
||||||
|
: "";
|
||||||
|
let columnname = columny
|
||||||
|
? positions[
|
||||||
|
Object.keys(positions).find((key) =>
|
||||||
|
positions[key].y === columny
|
||||||
|
)
|
||||||
|
].name
|
||||||
|
: "";
|
||||||
|
theme_positions.querySelector(".other").innerText =
|
||||||
|
rowname && columnname
|
||||||
|
? columnname + "上的" + rowname
|
||||||
|
: rowname
|
||||||
|
? rowname
|
||||||
|
: columnname
|
||||||
|
? columnname
|
||||||
|
: "";
|
||||||
});
|
});
|
||||||
theme_positions.addEventListener("mouseleave", function (event) {
|
theme_positions.addEventListener("mouseleave", function (event) {
|
||||||
perx.innerText = "100%";
|
perx.innerText = "100%";
|
||||||
@@ -112,13 +143,12 @@ function themePosition() {
|
|||||||
selectbox.style.bottom = "50%";
|
selectbox.style.bottom = "50%";
|
||||||
selectbox.style.width = "0";
|
selectbox.style.width = "0";
|
||||||
selectbox.style.height = "0";
|
selectbox.style.height = "0";
|
||||||
perx.classList.remove("c")
|
perx.classList.remove("c");
|
||||||
pery.classList.remove("c")
|
pery.classList.remove("c");
|
||||||
pxx.classList.remove("c")
|
pxx.classList.remove("c");
|
||||||
pxy.classList.remove("c")
|
pxy.classList.remove("c");
|
||||||
other.innerText = "";
|
other.innerText = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function rdview() {
|
function rdview() {
|
||||||
@@ -129,21 +159,25 @@ function rdview() {
|
|||||||
let number = rdview.querySelector(".number");
|
let number = rdview.querySelector(".number");
|
||||||
const textareaStyles = window.getComputedStyle(textarea);
|
const textareaStyles = window.getComputedStyle(textarea);
|
||||||
[
|
[
|
||||||
'fontFamily', 'fontSize', 'fontWeight',
|
"fontFamily",
|
||||||
'letterSpacing', 'lineHeight', 'padding',
|
"fontSize",
|
||||||
].forEach(property => {
|
"fontWeight",
|
||||||
|
"letterSpacing",
|
||||||
|
"lineHeight",
|
||||||
|
"padding",
|
||||||
|
].forEach((property) => {
|
||||||
number.style[property] = textareaStyles[property];
|
number.style[property] = textareaStyles[property];
|
||||||
});
|
});
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement("canvas");
|
||||||
const context = canvas.getContext('2d');
|
const context = canvas.getContext("2d");
|
||||||
const font = `${textareaStyles.fontSize} ${textareaStyles.fontFamily}`;
|
const font = `${textareaStyles.fontSize} ${textareaStyles.fontFamily}`;
|
||||||
context.font = font;
|
context.font = font;
|
||||||
function calcStringLines(sentence, width) {
|
function calcStringLines(sentence, width) {
|
||||||
if (!width) return 0;
|
if (!width) return 0;
|
||||||
const words = sentence.split('');
|
const words = sentence.split("");
|
||||||
let lineCount = 0;
|
let lineCount = 0;
|
||||||
|
|
||||||
let currentLine = '';
|
let currentLine = "";
|
||||||
for (let i = 0; i < words.length; i++) {
|
for (let i = 0; i < words.length; i++) {
|
||||||
const wordWidth = context.measureText(words[i]).width;
|
const wordWidth = context.measureText(words[i]).width;
|
||||||
const lineWidth = context.measureText(currentLine).width;
|
const lineWidth = context.measureText(currentLine).width;
|
||||||
@@ -154,18 +188,22 @@ function rdview() {
|
|||||||
currentLine += words[i];
|
currentLine += words[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentLine.trim() !== '') lineCount++;
|
if (currentLine.trim() !== "") lineCount++;
|
||||||
return lineCount;
|
return lineCount;
|
||||||
}
|
}
|
||||||
function calcLines() {
|
function calcLines() {
|
||||||
const lines = textarea.value.split('\n');
|
const lines = textarea.value.split("\n");
|
||||||
const textareaWidth = textarea.getBoundingClientRect().width;
|
const textareaWidth = textarea.getBoundingClientRect().width;
|
||||||
const textareaScrollWidth = textareaWidth - textarea.clientWidth;
|
const textareaScrollWidth = textareaWidth - textarea.clientWidth;
|
||||||
const parseNumber = (v) => v.endsWith('px') ? parseInt(v.slice(0, -2), 10) : 0;
|
const parseNumber = (v) =>
|
||||||
|
v.endsWith("px") ? parseInt(v.slice(0, -2), 10) : 0;
|
||||||
const textareaPaddingLeft = parseNumber(textareaStyles.paddingLeft);
|
const textareaPaddingLeft = parseNumber(textareaStyles.paddingLeft);
|
||||||
const textareaPaddingRight = parseNumber(textareaStyles.paddingRight);
|
const textareaPaddingRight = parseNumber(textareaStyles.paddingRight);
|
||||||
const textareaContentWidth = textareaWidth - textareaPaddingLeft - textareaPaddingRight - textareaScrollWidth;
|
const textareaContentWidth = textareaWidth - textareaPaddingLeft -
|
||||||
const numLines = lines.map(lineString => calcStringLines(lineString, textareaContentWidth));
|
textareaPaddingRight - textareaScrollWidth;
|
||||||
|
const numLines = lines.map((lineString) =>
|
||||||
|
calcStringLines(lineString, textareaContentWidth)
|
||||||
|
);
|
||||||
let lineNumbers = [];
|
let lineNumbers = [];
|
||||||
let i = 1;
|
let i = 1;
|
||||||
while (numLines.length > 0) {
|
while (numLines.length > 0) {
|
||||||
@@ -173,8 +211,8 @@ function rdview() {
|
|||||||
lineNumbers.push(i);
|
lineNumbers.push(i);
|
||||||
if (numLinesOfSentence > 1) {
|
if (numLinesOfSentence > 1) {
|
||||||
Array(numLinesOfSentence - 1)
|
Array(numLinesOfSentence - 1)
|
||||||
.fill('')
|
.fill("")
|
||||||
.forEach((_) => lineNumbers.push(''));
|
.forEach((_) => lineNumbers.push(""));
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -184,24 +222,166 @@ function rdview() {
|
|||||||
const lines = calcLines();
|
const lines = calcLines();
|
||||||
const lineDoms = Array.from({
|
const lineDoms = Array.from({
|
||||||
length: lines.length,
|
length: lines.length,
|
||||||
}, (_, i) => `<div>${lines[i] || ' '}</div>`);
|
}, (_, i) => `<div>${lines[i] || " "}</div>`);
|
||||||
number.innerHTML = lineDoms.join('');
|
number.innerHTML = lineDoms.join("");
|
||||||
}
|
}
|
||||||
function initCanvas() {
|
function initCanvas() {
|
||||||
const lang = textarea.value.split('\n')[0]
|
const lang = textarea.value.split("\n")[0];
|
||||||
const code = textarea.value.split('\n').slice(1).join('\n')
|
const code = textarea.value.split("\n").slice(1).join("\n");
|
||||||
rdcanvas.innerHTML = RDViewRender(lang, code)
|
rdcanvas.innerHTML = RDViewRender(lang, code);
|
||||||
}
|
}
|
||||||
initCanvas()
|
initCanvas();
|
||||||
initLineNumbers()
|
initLineNumbers();
|
||||||
textarea.addEventListener('input', initLineNumbers);
|
textarea.addEventListener("input", initLineNumbers);
|
||||||
textarea.addEventListener('input', initCanvas);
|
textarea.addEventListener("input", initCanvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rdview2() {
|
||||||
|
let rdview = document.getElementsByClassName("rdview2")[0];
|
||||||
|
if (!rdview) return;
|
||||||
|
let rdcanvas = rdview.querySelector(".canvas");
|
||||||
|
let textarea = rdview.querySelector("textarea.area");
|
||||||
|
let number = rdview.querySelector(".number");
|
||||||
|
const textareaStyles = window.getComputedStyle(textarea);
|
||||||
|
[
|
||||||
|
"fontFamily",
|
||||||
|
"fontSize",
|
||||||
|
"fontWeight",
|
||||||
|
"letterSpacing",
|
||||||
|
"lineHeight",
|
||||||
|
"padding",
|
||||||
|
].forEach((property) => {
|
||||||
|
number.style[property] = textareaStyles[property];
|
||||||
|
});
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
const context = canvas.getContext("2d");
|
||||||
|
const font = `${textareaStyles.fontSize} ${textareaStyles.fontFamily}`;
|
||||||
|
context.font = font;
|
||||||
|
function calcStringLines(sentence, width) {
|
||||||
|
if (!width) return 0;
|
||||||
|
const words = sentence.split("");
|
||||||
|
let lineCount = 0;
|
||||||
|
|
||||||
|
let currentLine = "";
|
||||||
|
for (let i = 0; i < words.length; i++) {
|
||||||
|
const wordWidth = context.measureText(words[i]).width;
|
||||||
|
const lineWidth = context.measureText(currentLine).width;
|
||||||
|
if (lineWidth + wordWidth > width) {
|
||||||
|
lineCount++;
|
||||||
|
currentLine = words[i];
|
||||||
|
} else {
|
||||||
|
currentLine += words[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentLine.trim() !== "") lineCount++;
|
||||||
|
return lineCount;
|
||||||
|
}
|
||||||
|
function calcLines() {
|
||||||
|
const lines = textarea.value.split("\n");
|
||||||
|
const textareaWidth = textarea.getBoundingClientRect().width;
|
||||||
|
const textareaScrollWidth = textareaWidth - textarea.clientWidth;
|
||||||
|
const parseNumber = (v) =>
|
||||||
|
v.endsWith("px") ? parseInt(v.slice(0, -2), 10) : 0;
|
||||||
|
const textareaPaddingLeft = parseNumber(textareaStyles.paddingLeft);
|
||||||
|
const textareaPaddingRight = parseNumber(textareaStyles.paddingRight);
|
||||||
|
const textareaContentWidth = textareaWidth - textareaPaddingLeft -
|
||||||
|
textareaPaddingRight - textareaScrollWidth;
|
||||||
|
const numLines = lines.map((lineString) =>
|
||||||
|
calcStringLines(lineString, textareaContentWidth)
|
||||||
|
);
|
||||||
|
let lineNumbers = [];
|
||||||
|
let i = 1;
|
||||||
|
while (numLines.length > 0) {
|
||||||
|
const numLinesOfSentence = numLines.shift();
|
||||||
|
lineNumbers.push(i);
|
||||||
|
if (numLinesOfSentence > 1) {
|
||||||
|
Array(numLinesOfSentence - 1)
|
||||||
|
.fill("")
|
||||||
|
.forEach((_) => lineNumbers.push(""));
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return lineNumbers;
|
||||||
|
}
|
||||||
|
function initLineNumbers() {
|
||||||
|
const lines = calcLines();
|
||||||
|
const lineDoms = Array.from({
|
||||||
|
length: lines.length,
|
||||||
|
}, (_, i) => `<div>${lines[i] || " "}</div>`);
|
||||||
|
number.innerHTML = lineDoms.join("");
|
||||||
|
}
|
||||||
|
function initCanvas() {
|
||||||
|
let objs = [];
|
||||||
|
try {
|
||||||
|
objs = JSON.parse(`[${textarea.value}]`);
|
||||||
|
rdcanvas.innerHTML = "";
|
||||||
|
} catch (e) {
|
||||||
|
rdcanvas.innerHTML =
|
||||||
|
`<div style="color: red; font-weight: bold;">JSON解析错误:${e.message}</div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const eventStyle = { "scale": 2.0, "showDuration": false };
|
||||||
|
let maxy = 0;
|
||||||
|
for (let obj of objs) {
|
||||||
|
const style = { ...eventStyle, enabled: obj.active ?? true };
|
||||||
|
const elem = createElementEvent(obj, style);
|
||||||
|
elem.eventStyle = style;
|
||||||
|
elem.style.position = "absolute";
|
||||||
|
elem.style.left = `${
|
||||||
|
((((obj.bar ?? 1) - 1) * 8) + (obj.beat ?? 1) - 1) * 14 *
|
||||||
|
eventStyle.scale
|
||||||
|
}px`;
|
||||||
|
elem.style.top = `${
|
||||||
|
(obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale
|
||||||
|
}px`;
|
||||||
|
if (
|
||||||
|
((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) +
|
||||||
|
elem.offsetHeight > maxy
|
||||||
|
) {
|
||||||
|
maxy = ((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) +
|
||||||
|
elem.offsetHeight;
|
||||||
|
}
|
||||||
|
elem.addEventListener("mousedown", (event) => {
|
||||||
|
const eStyle = elem.eventStyle;
|
||||||
|
eStyle.active = true;
|
||||||
|
elem.onStateChange(eStyle);
|
||||||
|
});
|
||||||
|
elem.addEventListener("mouseover", (event) => {
|
||||||
|
const eStyle = elem.eventStyle;
|
||||||
|
eStyle.hover = true;
|
||||||
|
elem.onStateChange(eStyle);
|
||||||
|
});
|
||||||
|
elem.addEventListener("mouseout", (event) => {
|
||||||
|
const eStyle = elem.eventStyle;
|
||||||
|
eStyle.hover = false;
|
||||||
|
eStyle.active = false;
|
||||||
|
elem.onStateChange(eStyle);
|
||||||
|
});
|
||||||
|
elem.addEventListener("mouseup", (event) => {
|
||||||
|
const eStyle = elem.eventStyle;
|
||||||
|
eStyle.active = false;
|
||||||
|
elem.onStateChange(eStyle);
|
||||||
|
});
|
||||||
|
rdcanvas.style.position = "relative";
|
||||||
|
rdcanvas.style.height = `${maxy + 4 * 14 * eventStyle.scale}px`;
|
||||||
|
if (elem) {
|
||||||
|
rdcanvas.appendChild(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initCanvas();
|
||||||
|
initLineNumbers();
|
||||||
|
textarea.addEventListener("input", initLineNumbers);
|
||||||
|
textarea.addEventListener("input", initCanvas);
|
||||||
|
}
|
||||||
window.$docsify.plugins = [].concat(window.$docsify.plugins, function (hook) {
|
window.$docsify.plugins = [].concat(window.$docsify.plugins, function (hook) {
|
||||||
hook.doneEach(function () {
|
hook.doneEach(function () {
|
||||||
themePosition();
|
themePosition();
|
||||||
rdview();
|
rdview();
|
||||||
|
rdview2();
|
||||||
document.documentElement.scrollTop = document.body.scrollTop = 0;
|
document.documentElement.scrollTop = document.body.scrollTop = 0;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import("./docsify.min.js").then(() => {
|
||||||
|
});
|
||||||
|
|||||||
+1
-1
@@ -162,7 +162,7 @@ div.theme-positions>.infobox {
|
|||||||
|
|
||||||
.markdown-section:has(div.rdview) {}
|
.markdown-section:has(div.rdview) {}
|
||||||
|
|
||||||
div.rdview {
|
div.rdview, div.rdview2 {
|
||||||
& div.canvas {
|
& div.canvas {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user