【问题标题】:Nesting events within Javascript functions在 Javascript 函数中嵌套事件
【发布时间】:2020-07-24 04:45:55
【问题描述】:

我正在使用 ToneJS 的网站上创建多个切换按钮。基本上,我希望不同的按钮播放不同的曲目。

我已经像这样创建了两个相同的按钮。

按钮 1:

function togglePlay() {
  const status = Tone.Transport.state; // Is either 'started', 'stopped' or 'paused'
  const element = document.getElementById("play-stop-toggle");
  if (status == "started") {
    element.innerText = "PLAY";
    Tone.Transport.stop()
  } else {
    element.innerText = "STOP";
    Tone.Transport.start()
  }

  document.querySelector('#status').textContent = status;
}

按钮 2:

function togglePlay2() {
  const status = Tone.Transport.state; // Is either 'started', 'stopped' or 'paused'
  const element = document.getElementById("play-stop-toggle2");
  if (status == "started") {
    element.innerText = "PLAY";
    Tone.Transport.stop()
  } else {
    element.innerText = "STOP";
    Tone.Transport.start()
  }

  document.querySelector('#status').textContent = status;
}

目前他们正在播放相同的循环,因为下面的代码是全局定义的:

var filter = new Tone.Filter({
  type: 'lowpass',
  Q: 12
}).toMaster()


var synth = new Tone.MembraneSynth().toMaster()

//create a loop
var loop = new Tone.Loop(function(time){
    synth.triggerAttackRelease("A1", "8n", time)
}, "2n")


//play the loop between 0-2m on the transport
loop.start(0)
// loop.start(0).stop('2m')

如何将filter、synth 和loop 嵌套在每个function togglePlay() 中,以便根据切换的按钮定义不同的声音?

【问题讨论】:

  • 也许我没有正确理解您的问题,但如果 filter、synth 和 loop 是全局定义的,那么您的函数 togglePlay() 和 togglePlay2() 都可以访问他们。您可以在全局范围内定义任意数量的过滤器、循环等,并且每个按钮的功能都可以调用您想要与之关联的功能。有什么问题?
  • @EvanMorrison - 对。我的问题是超级基本的。我在问一个非常简单的问题,即如何——作为语法级别——将它们从全局上下文中删除并将它们嵌套在函数中。
  • 啊,好吧,那么你能不能不把全局代码放在切换函数中,每个函数都有不同的选项?它们会以某种方式发生冲突吗?我对 Tone 的 API 一无所知。你试过什么?

标签: javascript tone.js


【解决方案1】:

这样做有什么问题吗?

function togglePlay() {
  const status = Tone.Transport.state; // Is either 'started', 'stopped' or 'paused'
  const element = document.getElementById("play-stop-toggle");
  if (status == "started") {
    element.innerText = "PLAY";
    Tone.Transport.stop()
  } else {
    element.innerText = "STOP";
    var filter = new Tone.Filter({
       type: 'lowpass',
       Q: 12
    }).toMaster()

    var synth = new Tone.MembraneSynth().toMaster()

    //create a loop
    var loop = new Tone.Loop(function(time){
        synth.triggerAttackRelease("A1", "8n", time)
    }, "2n")

    //play the loop between 0-2m on the transport
    loop.start(0)
    // loop.start(0).stop('2m')
    Tone.Transport.start()
  }

  document.querySelector('#status').textContent = status;
}

【讨论】:

    【解决方案2】:

    这是一种同时允许多种音调的解决方案。如果您希望一种音调开始停止当前正在运行的任何其他音调,则必须进行更多的状态管理。此代码让您了解如何将特定于上下文的配置绑定到单击处理程序以专门处理按钮的行为。

    不过,我不知道 Tone,而且您的代码没有完整的设置,所以您可能需要做更多的事情来为每个处理程序提供自己的 Tone 实例。 p>

    function createTogglePlayClickhandler(config) {
        var filter = new Tone.Filter(config.filter).toMaster()
        var synth = config.synth
          //create a loop
        var loop = config.loop
        const element = document.getElementById(elementId);
    
        return function togglePlay() {
            const status = Tone.Transport.state; // Is either 'started', 'stopped' or 'paused'
            
            if (status == "started") {
            element.innerText = "PLAY";
            Tone.Transport.stop()
            } else {
            element.innerText = "STOP";
            Tone.Transport.start()
            }
        
            document.querySelector('#status').textContent = status;
        }
    }
    
    // Generate click handlers
    createTogglePlayClickhandler({ 
        elementId: "play-stop-toggle",
        filter: {
            type: 'lowpass',
            Q: 12
          },
        synth: new Tone.MembraneSynth().toMaster(),
        loop: new Tone.Loop(function(time){
            synth.triggerAttackRelease("A1", "8n", time)
        }, "2n")
    });
    createTogglePlayClickhandler({ 
        elementId: "play-stop-toggle2",
        filter: {
            type: 'lowpass',
            Q: 12
          },
        synth: new Tone.MembraneSynth().toMaster(),
        loop: new Tone.Loop(function(time){
            synth.triggerAttackRelease("A1", "8n", time)
        }, "2n")
    });
    

    看起来你只有一个状态元素,所以我认为你想要的行为是一次一个音调?所以如果我点击 Tone A,然后点击 Tone B,Tone B 应该开始,而 Tone A 应该停止?

    或者你想要多音色?

    【讨论】:

    • 我正在尝试实现您建议的第一件事——即如果激活了 Tone B,则 Tone A 应该停止。
    猜你喜欢
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-21
    • 1970-01-01
    • 2019-09-16
    相关资源
    最近更新 更多