feat: first version
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<noscript>要使用本程序,请启用JavaScript。</noscript>
|
<noscript>要使用本程序,请启用JavaScript。</noscript>
|
||||||
|
<a href="https://github.com/mattuylee/numerical-notation-editor" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
+39
-22
@@ -21,6 +21,7 @@ import {
|
|||||||
createParagraph,
|
createParagraph,
|
||||||
createParagraphWithNotations,
|
createParagraphWithNotations,
|
||||||
} from "../util/paragraph";
|
} from "../util/paragraph";
|
||||||
|
import { convertTone, convertToneTo } from "../util/tone-convert";
|
||||||
import { exportFile, loadFile, saveFile } from "../util/file";
|
import { exportFile, loadFile, saveFile } from "../util/file";
|
||||||
import { findParagraphAndNotation, resetGlobalData } from "../util/editor";
|
import { findParagraphAndNotation, resetGlobalData } from "../util/editor";
|
||||||
import {
|
import {
|
||||||
@@ -74,9 +75,28 @@ const handleEditMenu = wrappedAction(({ key }) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const handleConvertMenu = wrappedAction(() => {
|
const handleConvertMenu = ({ key }) => {
|
||||||
console.log(111);
|
switch (true) {
|
||||||
});
|
case key.startsWith("convertTo"):
|
||||||
|
const destTone = key.split("-", 2)[1];
|
||||||
|
convertToneTo(destTone);
|
||||||
|
break;
|
||||||
|
case key === "convert-up":
|
||||||
|
convertTone(2);
|
||||||
|
break;
|
||||||
|
case key === "convert-down":
|
||||||
|
convertTone(-2);
|
||||||
|
break;
|
||||||
|
case key === "convert-up8":
|
||||||
|
convertTone(12);
|
||||||
|
break;
|
||||||
|
case key === "convert-down8":
|
||||||
|
convertTone(-12);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 画布上的点击事件
|
// 画布上的点击事件
|
||||||
const handleClick = wrappedAction((ev) => {
|
const handleClick = wrappedAction((ev) => {
|
||||||
@@ -94,6 +114,9 @@ const handleKeyPress = wrappedAction((ev) => {
|
|||||||
|
|
||||||
if (state.selectedNotationKey) {
|
if (state.selectedNotationKey) {
|
||||||
// 仅选中符号时作用
|
// 仅选中符号时作用
|
||||||
|
if (state.helpDialogVisible || state.configDialogVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
paragraph,
|
paragraph,
|
||||||
notation,
|
notation,
|
||||||
@@ -404,33 +427,27 @@ const editMenu = (
|
|||||||
|
|
||||||
const convertMenu = (
|
const convertMenu = (
|
||||||
<Menu key="tone" onClick={handleConvertMenu}>
|
<Menu key="tone" onClick={handleConvertMenu}>
|
||||||
<SubMenu key="convert-to" title="转到...">
|
<SubMenu key="convertTo" title="转到...">
|
||||||
<Menu.Item key="convert-to-C">1 = C</Menu.Item>
|
<Menu.Item key="convertTo-C">1 = C</Menu.Item>
|
||||||
<Menu.Item key="convert-to-D">1 = D</Menu.Item>
|
<Menu.Item key="convertTo-D">1 = D</Menu.Item>
|
||||||
<Menu.Item key="convert-to-E">1 = E</Menu.Item>
|
<Menu.Item key="convertTo-E">1 = E</Menu.Item>
|
||||||
<Menu.Item key="convert-to-F">1 = F</Menu.Item>
|
<Menu.Item key="convertTo-F">1 = F</Menu.Item>
|
||||||
<Menu.Item key="convert-to-G">1 = G</Menu.Item>
|
<Menu.Item key="convertTo-G">1 = G</Menu.Item>
|
||||||
<Menu.Item key="convert-to-A">1 = A</Menu.Item>
|
<Menu.Item key="convertTo-A">1 = A</Menu.Item>
|
||||||
<Menu.Item key="convert-to-B">1 = B</Menu.Item>
|
<Menu.Item key="convertTo-B">1 = B</Menu.Item>
|
||||||
<Menu.Item key="convert-to-bC">
|
<Menu.Item key="convertTo-♭D">
|
||||||
1 = <sup>♭</sup>C
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item key="convert-to-bD">
|
|
||||||
1 = <sup>♭</sup>D
|
1 = <sup>♭</sup>D
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="convert-to-bE">
|
<Menu.Item key="convertTo-♭E">
|
||||||
1 = <sup>♭</sup>E
|
1 = <sup>♭</sup>E
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="convert-to-bF">
|
<Menu.Item key="convertTo-♭G">
|
||||||
1 = <sup>♭</sup>F
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item key="convert-to-bG">
|
|
||||||
1 = <sup>♭</sup>G
|
1 = <sup>♭</sup>G
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="convert-to-bA">
|
<Menu.Item key="convertTo-♭A">
|
||||||
1 = <sup>♭</sup>A
|
1 = <sup>♭</sup>A
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="convert-to-bB">
|
<Menu.Item key="convertTo-♭B">
|
||||||
1 = <sup>♭</sup>B
|
1 = <sup>♭</sup>B
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</SubMenu>
|
</SubMenu>
|
||||||
|
|||||||
+11
-1
@@ -27,6 +27,9 @@ const separators = ["│", "‖"];
|
|||||||
function isNote(notationOrNote) {
|
function isNote(notationOrNote) {
|
||||||
return notes.includes(notationOrNote?.note || notationOrNote);
|
return notes.includes(notationOrNote?.note || notationOrNote);
|
||||||
}
|
}
|
||||||
|
function isPauseNote(notationOrNote) {
|
||||||
|
return notations.zero === (notationOrNote?.note || notationOrNote);
|
||||||
|
}
|
||||||
function isSeparator(notationOrNote) {
|
function isSeparator(notationOrNote) {
|
||||||
return separators.includes(notationOrNote?.note || notationOrNote);
|
return separators.includes(notationOrNote?.note || notationOrNote);
|
||||||
}
|
}
|
||||||
@@ -56,4 +59,11 @@ function cloneNotation(notation) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { notations, isNote, isSeparator, createNotation, cloneNotation };
|
export {
|
||||||
|
notations,
|
||||||
|
isNote,
|
||||||
|
isPauseNote,
|
||||||
|
isSeparator,
|
||||||
|
createNotation,
|
||||||
|
cloneNotation,
|
||||||
|
};
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import store from "../store/global";
|
||||||
|
import { wrappedAction } from "../store/history";
|
||||||
|
import { isNote, isPauseNote } from "./notation";
|
||||||
|
|
||||||
|
// 音符到音数
|
||||||
|
const noteToLevelMap = {
|
||||||
|
1: 0,
|
||||||
|
2: 2,
|
||||||
|
3: 4,
|
||||||
|
4: 5,
|
||||||
|
5: 7,
|
||||||
|
6: 9,
|
||||||
|
7: 11,
|
||||||
|
};
|
||||||
|
// 音数到音符
|
||||||
|
const levelToNoteMap = {
|
||||||
|
0: 1,
|
||||||
|
1: 1,
|
||||||
|
2: 2,
|
||||||
|
3: 2,
|
||||||
|
4: 3,
|
||||||
|
5: 4,
|
||||||
|
6: 4,
|
||||||
|
7: 5,
|
||||||
|
8: 5,
|
||||||
|
9: 6,
|
||||||
|
10: 7,
|
||||||
|
11: 7,
|
||||||
|
};
|
||||||
|
// 升降到音数
|
||||||
|
const bumpSharpToLevelMap = {
|
||||||
|
"♭": -1,
|
||||||
|
"♯": 1,
|
||||||
|
};
|
||||||
|
// 音数到升降
|
||||||
|
const levelToBumpSharpMap = {
|
||||||
|
1: "♯",
|
||||||
|
3: "♯",
|
||||||
|
6: "♯",
|
||||||
|
8: "♯",
|
||||||
|
10: "♭",
|
||||||
|
};
|
||||||
|
|
||||||
|
const toneToLevelMap = {
|
||||||
|
C: 0,
|
||||||
|
D: 2,
|
||||||
|
E: 4,
|
||||||
|
F: 5,
|
||||||
|
G: 7,
|
||||||
|
A: 9,
|
||||||
|
B: 11,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整体转调
|
||||||
|
* @param {number} deltaVolume 要调整的音数
|
||||||
|
*/
|
||||||
|
const convertTone = wrappedAction(function (deltaVolume) {
|
||||||
|
deltaVolume = deltaVolume | 0;
|
||||||
|
store.paragraphs.forEach((p) => {
|
||||||
|
p.notations.forEach((n) => {
|
||||||
|
if (isNote(n) && !isPauseNote(n)) {
|
||||||
|
n.octave += Math.trunc(deltaVolume / 12);
|
||||||
|
let newLevel =
|
||||||
|
noteToLevelMap[n.note] +
|
||||||
|
(deltaVolume % 12) +
|
||||||
|
(n.prefixSups || []).reduce(
|
||||||
|
(prev, next) => prev + (bumpSharpToLevelMap[next] | 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
if (newLevel >= 12) {
|
||||||
|
n.octave += 1;
|
||||||
|
newLevel -= 12;
|
||||||
|
} else if (newLevel < 0) {
|
||||||
|
n.octave -= 1;
|
||||||
|
newLevel += 12;
|
||||||
|
}
|
||||||
|
n.note = String(levelToNoteMap[newLevel]);
|
||||||
|
n.prefixSups = (n.prefixSups || []).filter(
|
||||||
|
(c) => c !== "♯" && c !== "♭"
|
||||||
|
);
|
||||||
|
if (levelToBumpSharpMap[newLevel]) {
|
||||||
|
n.prefixSups.unshift(levelToBumpSharpMap[newLevel]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 转到1 = *
|
||||||
|
const convertToneTo = wrappedAction((destTone) => {
|
||||||
|
let deltaVolume = -(
|
||||||
|
toneToLevelMap[destTone.split("").at(-1)] -
|
||||||
|
toneToLevelMap[store.tone.split("").at(-1)]
|
||||||
|
);
|
||||||
|
if (destTone.startsWith("♭") || store.tone.startsWith("♯")) {
|
||||||
|
deltaVolume -= 1;
|
||||||
|
}
|
||||||
|
if (destTone.startsWith("♯") || store.tone.startsWith("♭")) {
|
||||||
|
deltaVolume += 1;
|
||||||
|
}
|
||||||
|
convertTone(deltaVolume);
|
||||||
|
store.tone = destTone;
|
||||||
|
});
|
||||||
|
|
||||||
|
export { convertTone, convertToneTo };
|
||||||
Reference in New Issue
Block a user