使用javascript或jquery转置音乐

时间:2011-09-28 20:43:35

标签: javascript jquery

我有一个我编写的和弦图应用程序,我想允许用户使用onClick处理程序转置图表的键。

我的图表看起来像这样

{C}My name is Blanket, {F}And I can run fast

括号内的和弦出现在它前面的字母上方。

我想使用javascript或jquery来执行此操作。我该如何创建这个转置按钮?任何帮助表示赞赏。提前谢谢。

修改

所以这就是我想出来的......

$('.transposeUp').click(function(){
    $('.chord').each(function(){
        var currentChord = $(this).text(); // gathers the chord being used
        if(currentChord == $(this).text()){
        var chord = $(this).text().replace("F#", "G")
        }
        //... the if statements continue though every chord
        //but I didn't place them here to save space
    });
});

所以这就是问题......

我在混音中有一个斜线和弦(G / B),它改变了转置,但因为它改变了“B”,现在和弦(G / C)与“currentChord”不同所以当它到达各自的if条件时它不会改变G.直到我在Chord最终(G / G)的位置进行了足够的转置,然后第一个“G”开始转置,使最后一个“G”保持相同。有任何想法吗?非常感谢您的知识和帮助。提前谢谢。

3 个答案:

答案 0 :(得分:3)

使用jQuery,您可以选择绑定点击处理程序。有.click(),. delegate(),。live()等等。重现API已经告诉你的内容是没有意义的,但我可以这样说:学习如何绑定点击是整个问题的最小部分,甚至用.text()捕获和弦名称也是如此一旦你看了jQuery API,就会变得微不足道。

棘手的部分将是转置自身的逻辑。您需要掌握已有的知识(例如,从E到F只有半步;没有E#或Fb)并使其作为代码工作。

我对一般建议而不是代码示例表示道歉,但我的建议是有两个数组,一个包含锐利方面的所有和弦,一个包含所有和弦的和弦。

你也可以做一些作弊:而不是将逻辑包裹到开头(比如说,位置0中的C),只需重复你的数组:

[ “C”, “C#”, “d”, “d#”, “E”, “F”, “F#”, “G”, “G#”, “A”, “B”,“C ”, “C#”, “d”, “d#”, “E”, “F”, “F#”, “G”, “G#”, “A”, “B”]

然后找到第一个出现的和弦名称,向前移动所需的停止次数,你仍然会有正确的字符串。

答案 1 :(得分:3)

您需要按顺序匹配和弦,以便一次更新一个。如果你试图一次匹配所有内容,你会遇到像你所描述的问题,因为你一遍又一遍地匹配相同的和弦。

实现此目的的一个好方法是使用正则表达式来解析和分割和弦。获得匹配的和弦值后,使用和弦数组找到要转置的下一个/上一个和弦。以下是我作为演示开发的一些示例代码:

<p><span class="chord">{C}</span>My name is Blanket,</p>
<p><span class="chord">{G / B}</span>And I can run fast</p>

<p>
<input id="transposeDown" type="button" value="Down" /> |
<input id="transposeUp" type="button" value="Up" />
</p>

var match;
var chords =
    ['C','C#','D','Eb','E','F','F#','G','Ab','A','Bb','B','C',
     'Db','D','D#','E','F','Gb','G','G#','A','A#','C'];
var chordRegex = /C#|D#|F#|G#|A#|Db|Eb|Gb|Ab|Bb|C|D|E|F|G|A|B/g;

$('#transposeUp').click(function() {
    $('.chord').each(function() {
        var currentChord = $(this).text();
        var output = "";
        var parts = currentChord.split(chordRegex);
        var index = 0;
        while (match = chordRegex.exec(currentChord))
        {
            var chordIndex = chords.indexOf(match[0]);
            output += parts[index++] + chords[chordIndex+1];
        }
        output += parts[index];
        $(this).text(output);
    });
});

$('#transposeDown').click(function() {
    $('.chord').each(function() {
        var currentChord = $(this).text();
        var output = "";
        var parts = currentChord.split(chordRegex);
        var index = 0;
        while (match = chordRegex.exec(currentChord))
        {
            var chordIndex = chords.indexOf(match[0],1);
            output += parts[index++] + chords[chordIndex-1];
        }
        output += parts[index];
        $(this).text(output);
    });
});

示例演示: http://jsfiddle.net/4kYQZ/2/

有几点需要注意:

  1. 我采用了@ gregp的想法,即拥有密钥列表的多个副本,以便我可以处理锐利和平面。第一个音阶包括在移调期间使用的首选#/ b。第二个音阶包括其他格式,以便如果音乐包含它们,它们将正确转置。例如,因为Eb是第一个比例,所以当你上下移调时,它将被用来代替D#;但是,如果音乐开头有D#,它将正确移动到D / E(需要注意的是,如果你向后移动,它将再次成为Eb)。随意修改首选音阶 - 我根据个人音乐经验使用了我受过教育的判断。
  2. 正则表达式必须首先使用锐化/扁平化键,否则C#C匹配时不匹配。
  3. 我在数组的开头和结尾有C,这样我就可以从任何位置开始并移动两个方向而不通过数组的末尾。为了实现这一点,transposeDown代码在调用chords.indexOf时有一个额外的参数从位置1开始,因此它匹配数组中的最后一个C而不是第一个C 。然后,当它试图移动到前一个元素时,它不会传递数组的开头。
  4. 我正在使用正则表达式来分割和弦,这是多余的,但是通过将原始字符串部分与更新的和弦键交错,可以非常容易地将最终字符串重新组合在一起(不要忘了最后一块!)。
  5. 我正在使用元素而不是按钮的类。
  6. 希望这有帮助!


    更新1:根据OP的评论,pre-ie9不支持在数组上使用indexOf。这可以通过使用执行相同操作的辅助函数来解决:

    function arrayIndexOf(arr, match)
    {
        for (var i = 0; i < arr.length; i++)
            if (arr[i] == match)
                return i;
        return -1;
    }
    

    这一行

    var chordIndex = chords.indexOf(match[0]);
    

    将替换为:

    var chordIndex = arrayIndexOf(chords, match[0]);
    

    请参阅更新的示例演示:http://jsfiddle.net/4kYQZ/11/

答案 2 :(得分:1)

调用函数转置为up:

text = transpose(text, 1);

调用功能转置为down:

text = transpose(text, -1);

功能:

function transpose(text, amount){
   var lines = new Array();
   var chord = new Array();
   var scale =  ["C","Cb","C#","D","Db","D#","E","Eb","E#","F","Fb","F#","G","Gb","G#",
                 "A","Ab","A#","B","Bb","B#"];
   var transp = ["Cb","C","C#","Bb","Cb","C","C","C#","D","Db","D","D#","C","Db","D",
                 "D","D#","E","Eb","E","F","D","Eb","E","E","E#","F#","E","F","F#", 
                 "Eb","Fb","F","F","F#","G","Gb","G","G#","F","Gb","G","G","G#","A", 
                 "Ab","A","A#", "G","Ab","A","A","A#","B","Bb","B","C","A","Bb","B",
                 "B","B#","C#"];
  var inter = '';
  var mat = '';
  lines = text.split("\n");
  for(var i in lines){
      if(i%2===0){
         chord = lines[i].split(" ");
         for(var x in chord){
             if(chord[x]!==""){
               inter = chord[x];
               var subst = inter.match(/[^b#][#b]?/g);
               for(var ax in subst){
                   if(scale.indexOf(subst[ax])!==-1){
                      if(amount>0){
                         for(ix=0;ix<amount;ix++){
                             var pos = scale.indexOf(subst[ax]);
                             var transpos = 3*pos-2+3;
                             subst[ax] = transp[transpos+1];
                         }
                      }
                      if(amount<0){
                         for(ix=0;ix>amount;ix--){
                             var pos = scale.indexOf(subst[ax]);
                             var transpos = 3*pos-2+3;
                             subst[ax] = transp[transpos-1];
                            }
                     }
                  } 
               }
               chord[x]=subst.join("");
           }
        }
       lines[i] = chord.join(" ");
    }
  }
  return lines.join("\n");
}

第一行是转置,第二行不是,顺序。