Tonejs 音序器无法将变量识别为对象
Tonejs sequencer does not recognise variables into an object
我正在尝试使用 p5.js、p5.sound 库和 tone.js
构建一个包含音序器的对象
问题是我的代码无法识别在一个对象内的一个函数中编写的变量。
class tr909 中的所有其他函数可以识别我在 class 构造函数中声明的变量,但变量 "sequence" 无法识别它们。
正如您在下面看到的,tr909 class 有 sX 和 sY 变量,但是当我在名为 sequence 的函数中(在 tr909 class 内部,在底部),这个函数赢了'不再识别变量。
你知道为什么会这样吗?
谢谢! :)
//object
let tr9091;
let bL9091 = 16; //beat lenght
let posX9091 = 100; //positionX 909
let posY9091 = 220; //positionY 909
let sX9091 = 320; //sizeX of 909
let sY9091 = 60; //sizeY of 909
// var cellWidth = sX9091 / bL9091; //dont know why, if I put it in constructor of 909 object, sequence function does not recognise cellWidth
//Pre-load audio files
let hh909, clp909m, bd909;
let time;
let beatIndex;
var sX;
let sequence;
// var sX = 1;
function preload() {
bd909 = loadSound('assets/bass_sample.mp3');
hh909 = loadSound('assets/hh_sample.mp3');
clp909 = loadSound('assets/clap_sample.mp3');
}
function setup() {
createCanvas(600, 400);
tr9091 = new tr909(bd909, hh909, clp909, bL9091, posX9091, posY9091, sX9091, sY9091);
}
function draw() {
}
function keyPressed() {
if (key === ' ') {
tr9091.clicked();
}
}
function mousePressed() {
tr9091.rectPressed();
}
class tr909 {
constructor(bd, hh, clp, beatLenght, pX, pY, sX, sY) {
//variables
this.bd = bd;
this.hh = hh;
this.clp = clp;
this.beatLenght = beatLenght;
this.pX = pX; //positionX 909
this.pY = pY; //positionY 909
this.sX = sX; //sizeX 909
this.sY = sY; //sizeY 909
this.cellWidth = this.sX / this.beatLenght;
//sequences
this.bdPat = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0];
this.hhPat = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
this.clpPat = [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0];
this.sPat = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
this.cursorPos = 0;
//phrases
this.bdPhrase = new p5.Phrase('bd', (time) => {
this.bd.play(time)
}, this.bdPat);
this.hhPhrase = new p5.Phrase('hh', (time) => {
this.hh.play(time)
}, this.hhPat);
this.clpPhrase = new p5.Phrase('clp', (time) => {
this.clp.play(time)
}, this.clpPat);
//parts
this.drums = new p5.Part();
//adding phrase to parts
this.drums.addPhrase(this.bdPhrase);
this.drums.addPhrase(this.hhPhrase);
this.drums.addPhrase(this.clpPhrase);
this.drums.addPhrase('seq', this.sequence, this.sPat);
//BPM
let bpmCTRL;
this.bpmCTRL = createSlider(30, 120, 120, 1);
this.bpmCTRL.position(pX + 10, pY + 70);
this.bpmCTRL.input(() => {
this.drums.setBPM(this.bpmCTRL.value())
});
this.drums.setBPM('120');
this.drawMatrix();
} //final constructor
clicked() { //play loop
this.drums.loop();
}
rectPressed() {
//Y mouse click inside the object
if ((mouseY > this.pY && mouseY < this.pY + this.sY) && (mouseX > this.pX && mouseX < this.pX + this.sX)) {
this.rowClicked = floor(3 * (mouseY - this.pY) / this.sY);
this.indexClicked = floor(16 * (mouseX - this.pX) / this.sX);
if (this.rowClicked === 0) {
console.log("firstrow " + this.indexClicked);
this.bdPat[this.indexClicked] = +!this.bdPat[this.indexClicked];
} else if (this.rowClicked === 1) {
console.log("secondtrow");
this.hhPat[this.indexClicked] = +!this.hhPat[this.indexClicked];
} else if (this.rowClicked === 2) {
console.log("thrtrow");
this.clpPat[this.indexClicked] = +!this.clpPat[this.indexClicked];
}
this.drawMatrix();
}
}
//visual interface
drawMatrix() {
fill(80);
stroke('gray');
strokeWeight(2);
rect(this.pX, this.pY, this.sX, this.sY);
stroke('gray');
strokeWeight(2);
//vertical lines
for (let i = 0; i < this.beatLenght; i++) {
line(this.pX + i * this.cellWidth, this.pY, this.pX + i * this.cellWidth, this.pY + this.sY);
}
for (let i = 0; i < 4; i++) {
line(this.pX, this.pY + i * this.sY / 3, this.pX + this.sX, this.pY + i * this.sY / 3);
}
//draw circles
for (let i = 0; i < this.beatLenght; i++) {
if (this.bdPat[i] === 1) {
ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY / 6, 10);
}
if (this.hhPat[i] === 1) {
ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY / 2, 10);
}
if (this.clpPat[i] === 1) {
ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY * 5 / 6, 10);
}
}
}
sequence(time, beatIndex) {
this.cellWidth = this.sX / this.beatLenght;
stroke('red');
fill(255, 0, 0, 30);
rect(beatIndex * this.cellWidth, this.sX, this.cellWidth, this.sY);
console.log(beatIndex);
}
} //final object
因为这里:
this.drums = new p5.Part();
//adding phrase to parts
this.drums.addPhrase(this.bdPhrase);
this.drums.addPhrase(this.hhPhrase);
this.drums.addPhrase(this.clpPhrase);
this.drums.addPhrase('seq', this.sequence, this.sPat);
您将其作为回调函数传递。检查此线程中的第一个答案:
How to access the correct `this` inside a callback?
将参数 this.sequence
替换为:
function(){ this.sequence() }.bind( this )
甚至更短:
this.sequence.bind(this);
或者像这样:
()=>{ this.sequence() }
或者,当你想传入参数或return值时:
(...args) => this.sequence(...args)
我正在尝试使用 p5.js、p5.sound 库和 tone.js
构建一个包含音序器的对象问题是我的代码无法识别在一个对象内的一个函数中编写的变量。
class tr909 中的所有其他函数可以识别我在 class 构造函数中声明的变量,但变量 "sequence" 无法识别它们。
正如您在下面看到的,tr909 class 有 sX 和 sY 变量,但是当我在名为 sequence 的函数中(在 tr909 class 内部,在底部),这个函数赢了'不再识别变量。
你知道为什么会这样吗?
谢谢! :)
//object
let tr9091;
let bL9091 = 16; //beat lenght
let posX9091 = 100; //positionX 909
let posY9091 = 220; //positionY 909
let sX9091 = 320; //sizeX of 909
let sY9091 = 60; //sizeY of 909
// var cellWidth = sX9091 / bL9091; //dont know why, if I put it in constructor of 909 object, sequence function does not recognise cellWidth
//Pre-load audio files
let hh909, clp909m, bd909;
let time;
let beatIndex;
var sX;
let sequence;
// var sX = 1;
function preload() {
bd909 = loadSound('assets/bass_sample.mp3');
hh909 = loadSound('assets/hh_sample.mp3');
clp909 = loadSound('assets/clap_sample.mp3');
}
function setup() {
createCanvas(600, 400);
tr9091 = new tr909(bd909, hh909, clp909, bL9091, posX9091, posY9091, sX9091, sY9091);
}
function draw() {
}
function keyPressed() {
if (key === ' ') {
tr9091.clicked();
}
}
function mousePressed() {
tr9091.rectPressed();
}
class tr909 {
constructor(bd, hh, clp, beatLenght, pX, pY, sX, sY) {
//variables
this.bd = bd;
this.hh = hh;
this.clp = clp;
this.beatLenght = beatLenght;
this.pX = pX; //positionX 909
this.pY = pY; //positionY 909
this.sX = sX; //sizeX 909
this.sY = sY; //sizeY 909
this.cellWidth = this.sX / this.beatLenght;
//sequences
this.bdPat = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0];
this.hhPat = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
this.clpPat = [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0];
this.sPat = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
this.cursorPos = 0;
//phrases
this.bdPhrase = new p5.Phrase('bd', (time) => {
this.bd.play(time)
}, this.bdPat);
this.hhPhrase = new p5.Phrase('hh', (time) => {
this.hh.play(time)
}, this.hhPat);
this.clpPhrase = new p5.Phrase('clp', (time) => {
this.clp.play(time)
}, this.clpPat);
//parts
this.drums = new p5.Part();
//adding phrase to parts
this.drums.addPhrase(this.bdPhrase);
this.drums.addPhrase(this.hhPhrase);
this.drums.addPhrase(this.clpPhrase);
this.drums.addPhrase('seq', this.sequence, this.sPat);
//BPM
let bpmCTRL;
this.bpmCTRL = createSlider(30, 120, 120, 1);
this.bpmCTRL.position(pX + 10, pY + 70);
this.bpmCTRL.input(() => {
this.drums.setBPM(this.bpmCTRL.value())
});
this.drums.setBPM('120');
this.drawMatrix();
} //final constructor
clicked() { //play loop
this.drums.loop();
}
rectPressed() {
//Y mouse click inside the object
if ((mouseY > this.pY && mouseY < this.pY + this.sY) && (mouseX > this.pX && mouseX < this.pX + this.sX)) {
this.rowClicked = floor(3 * (mouseY - this.pY) / this.sY);
this.indexClicked = floor(16 * (mouseX - this.pX) / this.sX);
if (this.rowClicked === 0) {
console.log("firstrow " + this.indexClicked);
this.bdPat[this.indexClicked] = +!this.bdPat[this.indexClicked];
} else if (this.rowClicked === 1) {
console.log("secondtrow");
this.hhPat[this.indexClicked] = +!this.hhPat[this.indexClicked];
} else if (this.rowClicked === 2) {
console.log("thrtrow");
this.clpPat[this.indexClicked] = +!this.clpPat[this.indexClicked];
}
this.drawMatrix();
}
}
//visual interface
drawMatrix() {
fill(80);
stroke('gray');
strokeWeight(2);
rect(this.pX, this.pY, this.sX, this.sY);
stroke('gray');
strokeWeight(2);
//vertical lines
for (let i = 0; i < this.beatLenght; i++) {
line(this.pX + i * this.cellWidth, this.pY, this.pX + i * this.cellWidth, this.pY + this.sY);
}
for (let i = 0; i < 4; i++) {
line(this.pX, this.pY + i * this.sY / 3, this.pX + this.sX, this.pY + i * this.sY / 3);
}
//draw circles
for (let i = 0; i < this.beatLenght; i++) {
if (this.bdPat[i] === 1) {
ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY / 6, 10);
}
if (this.hhPat[i] === 1) {
ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY / 2, 10);
}
if (this.clpPat[i] === 1) {
ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY * 5 / 6, 10);
}
}
}
sequence(time, beatIndex) {
this.cellWidth = this.sX / this.beatLenght;
stroke('red');
fill(255, 0, 0, 30);
rect(beatIndex * this.cellWidth, this.sX, this.cellWidth, this.sY);
console.log(beatIndex);
}
} //final object
因为这里:
this.drums = new p5.Part();
//adding phrase to parts
this.drums.addPhrase(this.bdPhrase);
this.drums.addPhrase(this.hhPhrase);
this.drums.addPhrase(this.clpPhrase);
this.drums.addPhrase('seq', this.sequence, this.sPat);
您将其作为回调函数传递。检查此线程中的第一个答案: How to access the correct `this` inside a callback?
将参数 this.sequence
替换为:
function(){ this.sequence() }.bind( this )
甚至更短:
this.sequence.bind(this);
或者像这样:
()=>{ this.sequence() }
或者,当你想传入参数或return值时:
(...args) => this.sequence(...args)