rd.rdlevel.cn/script/special.js
2026-01-14 00:55:38 +08:00

396 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { createElementEvent } from "./View.js";
let curx = 0;
let cury = 0;
let rowx;
let columny;
let positions = {
"c1": { "x": 64, "name": "第一拍" },
"c2": { "x": 88, "name": "第二拍" },
"c3": { "x": 112, "name": "第三拍" },
"c4": { "x": 136, "name": "第四拍" },
"c5": { "x": 160, "name": "第五拍" },
"c6": { "x": 184, "name": "第六拍" },
"c7": { "x": 249, "name": "第七拍" },
"ccharacter": { "x": 35, "name": "角色" },
"ccenter": { "x": 176, "name": "中心" },
"cheart": { "x": 317, "name": "心" },
"r1": { "y": 162, "name": "四轨时的第四轨" },
"r2": { "y": 141, "name": "三轨时的第三轨" },
"r3": { "y": 120, "name": "二轨时的第一轨/四轨时的第三轨" },
"r4": { "y": 99, "name": "一轨时的第一轨/三轨时的第二轨" },
"r5": { "y": 78, "name": "二轨时的第二轨/四轨时的第二轨" },
"r6": { "y": 57, "name": "三轨时的第一轨" },
"r7": { "y": 36, "name": "四轨时的第一轨" },
};
function themePosition() {
let theme_positions = document.getElementById("theme-positions");
if (!theme_positions) return;
let perx = theme_positions.querySelector(".per>span.x");
let pery = theme_positions.querySelector(".per>span.y");
let pxx = theme_positions.querySelector(".px>span.x");
let pxy = theme_positions.querySelector(".px>span.y");
let infobox = theme_positions.querySelector(".infobox");
let selectbox = theme_positions.querySelector(".selectbox");
let other = theme_positions.querySelector(".other");
perx.innerText = "100%";
pery.innerText = "100%";
pxx.innerText = "352px";
pxy.innerText = "198px";
infobox.style.right = "calc(10px)";
infobox.style.top = "calc(10px)";
selectbox.style.left = "50%";
selectbox.style.bottom = "50%";
selectbox.style.width = "0";
selectbox.style.height = "0";
other.innerText = "";
theme_positions.addEventListener("mouseenter", function (event) {
});
theme_positions.addEventListener("mousemove", function (event) {
let x = event.clientX - theme_positions.getBoundingClientRect().left;
let y = event.clientY - theme_positions.getBoundingClientRect().top;
let width = theme_positions.offsetWidth;
let height = theme_positions.offsetHeight;
let x_percent = parseFloat(((x / width) * 100).toFixed(2));
let y_percent = parseFloat(((y / height) * 100).toFixed(2));
x = parseFloat((x_percent * 3.52).toFixed(0));
y = parseFloat((y_percent * 1.98).toFixed(0));
rowx = null;
columny = null;
for (let key in positions) {
if (
positions[key].x !== null && Math.abs(x - positions[key].x) < 5
) {
rowx = positions[key].x;
}
if (
positions[key].y !== null && Math.abs(y - positions[key].y) < 5
) {
columny = positions[key].y;
}
}
if (rowx) {
perx.innerText = (rowx / 3.52).toFixed(2) + "%";
perx.classList.add("c");
pxx.innerText = rowx + "px";
pxx.classList.add("c");
} else {
perx.innerText = x_percent.toFixed(2) + "%";
perx.classList.remove("c");
pxx.innerText = x + "px";
pxx.classList.remove("c");
}
if (columny) {
pery.innerText = (100 - columny / 1.98).toFixed(2) + "%";
pery.classList.add("c");
pxy.innerText = 198 - columny + "px";
pxy.classList.add("c");
} else {
pery.innerText = (100 - y_percent).toFixed(2) + "%";
pery.classList.remove("c");
pxy.innerText = 198 - y + "px";
pxy.classList.remove("c");
}
infobox.style.right = "calc(" + (100 - x_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.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.height = columny ? "10.61%" : rowx ? "100%" : "6px";
let rowname = rowx
? positions[
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) {
perx.innerText = "100%";
pery.innerText = "100%";
pxx.innerText = "352px";
pxy.innerText = "198px";
infobox.style.right = "calc(10px)";
infobox.style.top = "calc(10px)";
selectbox.style.left = "50%";
selectbox.style.bottom = "50%";
selectbox.style.width = "0";
selectbox.style.height = "0";
perx.classList.remove("c");
pery.classList.remove("c");
pxx.classList.remove("c");
pxy.classList.remove("c");
other.innerText = "";
});
}
function rdview() {
let rdview = document.getElementsByClassName("rdview")[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] || "&nbsp;"}</div>`);
number.innerHTML = lineDoms.join("");
}
function initCanvas() {
const lang = textarea.value.split("\n")[0];
const code = textarea.value.split("\n").slice(1).join("\n");
rdcanvas.innerHTML = RDViewRender(lang, code);
}
initCanvas();
initLineNumbers();
textarea.addEventListener("input", initLineNumbers);
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] || "&nbsp;"}</div>`);
number.innerHTML = lineDoms.join("");
}
function initCanvas() {
// const lang = textarea.value.split('\n')[0]
// const code = textarea.value.split('\n').slice(1).join('\n')
// rdcanvas.innerHTML = RDViewRender(lang, code)
// try {
// JSON.parse(`[${textarea.value}]`);
// } catch (e) {
// rdcanvas.innerHTML = `<div style="color: red; font-weight: bold;">JSON解析错误${e.message}</div>`;
// }
let objs = [];
try {
objs = JSON.parse(`[${textarea.value}]`);
} 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);
}
}
}
//rdcanvas.innerHTML = RDView2Render(json);
initCanvas();
initLineNumbers();
textarea.addEventListener("input", initLineNumbers);
textarea.addEventListener("input", initCanvas);
}
window.$docsify.plugins = [].concat(window.$docsify.plugins, function (hook) {
hook.doneEach(function () {
themePosition();
rdview();
rdview2();
document.documentElement.scrollTop = document.body.scrollTop = 0;
});
});
import("./docsify.min.js").then(() => {
});