Create circleOfFifths.js
This commit is contained in:
261
circleOfFifths.js
Normal file
261
circleOfFifths.js
Normal file
@@ -0,0 +1,261 @@
|
||||
let outRatio = 0.8;
|
||||
let outC1;
|
||||
let outC2;
|
||||
let outCH;
|
||||
let outCT;
|
||||
let outCSP; // 分隔
|
||||
let outText = ["沒有升降", "1 個 #", "2 個 #", "3 個 #", "4 個 #", "5 個 # / 7 個 b", "6 個 # / 6 個 b", "7 個 # / 5 個 b", "4 個 b", "3 個 b", "2 個 b", "1 個 b"]
|
||||
let outTextSize = 15;
|
||||
|
||||
let majorRatio = 0.74;
|
||||
let majorC1;
|
||||
let majorC2;
|
||||
let majorCT;
|
||||
let majorText = ["C", "G", "D", "A", "E", "B/Cb", "F#/Gb", "C#/Db", "Ab", "Eb", "Bb", "F"]
|
||||
let majorTextSize = 22;
|
||||
|
||||
let minorRatio = 0.65;
|
||||
let minorC1;
|
||||
let minorC2;
|
||||
let minorCT;
|
||||
let minorText = ["Am", "Em", "Bm", "F#m", "C#m", "G#m/Abm", "D#m/Ebm", "A#m/Bbm", "Fm", "Cm", "Gm", "Dm"]
|
||||
let minorTextSize = 17;
|
||||
|
||||
let detailText1 = [
|
||||
"C 大調 / A 小調",
|
||||
"G 大調 / E 小調",
|
||||
"D 大調 / B 小調",
|
||||
"A 大調 / F# 小調",
|
||||
"E 大調 / C# 小調",
|
||||
"B 或 Cb 大調 / G# 或 Ab 小調",
|
||||
"F# 或 Gb 大調 / D# 或 Eb 小調",
|
||||
"C# 或 Db 大調 / A# 或 Bb 小調",
|
||||
"Ab 大調 / F 小調",
|
||||
"Eb 大調 / C 小調",
|
||||
"Bb 大調 / G 小調",
|
||||
"F 大調 / D 小調"
|
||||
]
|
||||
|
||||
let coreRatio = 0.57;
|
||||
let coreType = "Detail";
|
||||
|
||||
let dbText = "This is the default debug text."
|
||||
|
||||
let mouseDir;
|
||||
|
||||
let acc = 0;
|
||||
let vel = 0;
|
||||
let angle = -3.5; // 1 = 1/12 TAU, global angle
|
||||
|
||||
let locked = true;
|
||||
|
||||
function setup() {
|
||||
createCanvas(800, 800);
|
||||
ellipseMode(CENTER);
|
||||
colorMode(HSB, 100);
|
||||
//colors
|
||||
outC1 = color(60, 30, 70);
|
||||
outC2 = color(60, 30, 80);
|
||||
outCH = color(60, 30, 100);
|
||||
outCT = color(60, 0, 95);
|
||||
outCSP = color(60, 20, 95);
|
||||
majorC1 = color(80, 30, 80);
|
||||
majorC2 = color(80, 30, 70);
|
||||
majorCT = color(80, 30, 20);
|
||||
minorC1 = color(80, 30, 75);
|
||||
minorC2 = color(80, 30, 65);
|
||||
minorCT = color(80, 10, 90);
|
||||
|
||||
lockButton = createButton('[Locked]');
|
||||
lockButton.position(19, 19);
|
||||
lockButton.mousePressed(toggleLocked);
|
||||
|
||||
}
|
||||
|
||||
function toggleLocked() {
|
||||
if (locked) {
|
||||
lockButton.html("Lock");
|
||||
locked = false;
|
||||
} else {
|
||||
lockButton.html("[Locked]");
|
||||
locked = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function highlighted() {
|
||||
let x = mouseDir - angle;
|
||||
while (x < 0) {
|
||||
x += 12;
|
||||
}
|
||||
x = ((x * 10000) % 120000) / 10000;
|
||||
|
||||
return floor(x);
|
||||
}
|
||||
|
||||
function drawOuter(ang) {
|
||||
stroke(outCSP);
|
||||
for (i = 0; i < 12; i++) {
|
||||
fill((i % 2 == 0) ? outC1 : outC2);
|
||||
|
||||
if (i == highlighted()) {
|
||||
fill(outCH);
|
||||
|
||||
}
|
||||
let j = i + ang;
|
||||
arc(0, 0, width * outRatio, height * outRatio, TAU * (j / 12), TAU * ((j + 1) / 12) - 0.000001, PIE);
|
||||
}
|
||||
stroke(20);
|
||||
noFill();
|
||||
ellipse(0, 0, width * outRatio);
|
||||
}
|
||||
|
||||
function drawOuterText(ang) {
|
||||
for (i = 0; i < 12; i++) {
|
||||
let j = i + ang + 3.5; // 把第一個字畫到右方
|
||||
push();
|
||||
rotate(TAU * (j / 12));
|
||||
textAlign(CENTER);
|
||||
textSize(outTextSize);
|
||||
noStroke();
|
||||
fill(outCT);
|
||||
text(outText[i], 0, -(height * outRatio / 2 * 0.945));
|
||||
pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function drawMajor(ang) {
|
||||
stroke(90);
|
||||
for (i = 0; i < 12; i++) {
|
||||
fill((i % 2 == 0) ? majorC1 : majorC2);
|
||||
let j = i + ang;
|
||||
arc(0, 0, width * majorRatio, height * majorRatio, TAU * (j / 12), TAU * ((j + 1) / 12) - 0.000001);
|
||||
}
|
||||
}
|
||||
|
||||
function drawMajorText(ang) {
|
||||
for (i = 0; i < 12; i++) {
|
||||
let j = i + ang + 3.5;
|
||||
push();
|
||||
rotate(TAU * (j / 12));
|
||||
textAlign(CENTER);
|
||||
textSize(majorTextSize);
|
||||
noStroke();
|
||||
fill(majorCT);
|
||||
text(majorText[i], 0, -(height * majorRatio / 2 * 0.91));
|
||||
pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function drawMinor(ang) {
|
||||
noStroke();
|
||||
for (i = 0; i < 12; i++) {
|
||||
fill((i % 2 == 0) ? minorC1 : minorC2);
|
||||
let j = i + ang;
|
||||
arc(0, 0, width * minorRatio, height * minorRatio, TAU * (j / 12), TAU * ((j + 1) / 12) - 0.000001);
|
||||
}
|
||||
}
|
||||
|
||||
function drawMinorText(ang) {
|
||||
for (i = 0; i < 12; i++) {
|
||||
let j = i + ang + 3.5;
|
||||
push();
|
||||
rotate(TAU * (j / 12));
|
||||
textAlign(CENTER);
|
||||
textSize(minorTextSize);
|
||||
noStroke();
|
||||
fill(minorCT);
|
||||
text(minorText[i], 0, -(height * minorRatio / 2 * 0.91));
|
||||
pop();
|
||||
}
|
||||
}
|
||||
|
||||
function drawCore(ang) {
|
||||
switch (coreType) {
|
||||
case "Empty":
|
||||
drawCoreEmpty(ang);
|
||||
break;
|
||||
case "Black":
|
||||
drawCoreBlack(ang);
|
||||
break;
|
||||
case "Detail":
|
||||
drawCoreDetail(ang);
|
||||
break;
|
||||
default:
|
||||
drawCoreEmpty(ang);
|
||||
}
|
||||
}
|
||||
|
||||
function drawCoreDetail(ang) {
|
||||
fill(100);
|
||||
stroke(40);
|
||||
ellipse(0, 0, width * coreRatio);
|
||||
fill(20);
|
||||
noStroke();
|
||||
textAlign(CENTER);
|
||||
textSize(22);
|
||||
text(detailText1[highlighted()], 0, height * 0.1);
|
||||
}
|
||||
|
||||
|
||||
function drawCoreEmpty(ang) {
|
||||
fill(100);
|
||||
stroke(40);
|
||||
ellipse(0, 0, width * coreRatio);
|
||||
}
|
||||
|
||||
function drawCoreBlack(ang) {
|
||||
fill(0);
|
||||
stroke(40);
|
||||
ellipse(0, 0, width * coreRatio);
|
||||
}
|
||||
|
||||
function debugText() {
|
||||
fill(0);
|
||||
textAlign(CENTER);
|
||||
text(dbText, 0, height * 0.45);
|
||||
}
|
||||
|
||||
function mouseAngle(ang) {
|
||||
let v = createVector(mouseX - width / 2, mouseY - height / 2);
|
||||
let h = v.heading(); // -PI ~ PI
|
||||
let i = map(h, -PI, PI, 6, 18);
|
||||
// let j = (i - ang);
|
||||
mouseDir = (i > 12) ? i - 12 : i;
|
||||
// dbText = `${h}, ${i}, ${mouseDir}`;
|
||||
|
||||
}
|
||||
|
||||
function rotateGlobal() {
|
||||
acc = (mouseX - width / 2) / width;
|
||||
dbText = acc;
|
||||
if (abs(acc) > 0.4) {
|
||||
vel += acc / 70;
|
||||
vel = constrain(vel, -0.1, 0.1);
|
||||
}
|
||||
|
||||
if (locked) {
|
||||
vel = 0; // friction
|
||||
} else {
|
||||
vel *= 0.9
|
||||
}
|
||||
angle += vel;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
background(95);
|
||||
translate(width / 2, height / 2);
|
||||
mouseAngle(angle);
|
||||
rotateGlobal()
|
||||
highlighted();
|
||||
drawOuter(angle);
|
||||
drawOuterText(angle);
|
||||
drawMajor(angle);
|
||||
drawMajorText(angle);
|
||||
drawMinor(angle);
|
||||
drawMinorText(angle);
|
||||
drawCore(angle);
|
||||
// debugText();
|
||||
}
|
Reference in New Issue
Block a user