「VexFlow スラー」の版間の差分

提供:yonewiki
(ページの作成:「<yjavascript></script> <script src="https://wiki.yo-net.jp/vexflow/build/cjs/vexflow.js"></script> <script> </yjavascript> VexFlow 使い方に戻る。 == '''概要''' ==  タイは同じ高さの音同士を区切らずに演奏する奏法に使います。   == '''タイ''' == <div id="yonet202403Mid_Output01"></div> <yjavascript></script> <script> (function(){ document.addEventListener("DOMContentLoaded", function () { // VexFlowの初期化…」)
 
 
(同じ利用者による、間の66版が非表示)
5行目: 5行目:
[[VexFlow 使い方]]に戻る。
[[VexFlow 使い方]]に戻る。
== '''概要''' ==
== '''概要''' ==
 タイは同じ高さの音同士を区切らずに演奏する奏法に使います。
 スラーは異なる高さの音同士を区切らずに演奏する奏法に使います。


基本的にはStaveTieタイと同じです。ですが、Curveを使う方法もある感じです。
 
 


== '''タイ''' ==
== '''スラー''' ==
<div id="yonet202403Mid_Output01"></div>
<div id="yonet202403Mid_Output01"></div>
<yjavascript></script>
<yjavascript></script>
<script>
<script>
(function(){
(function(){
    document.addEventListener("DOMContentLoaded", function () {
const {
      // VexFlowの初期化
  Factory,
      const VF = Vex.Flow;
  Stave,
  StaveNote,
  Formatter,
  Voice,
  StaveTie,
  Renderer
} = Vex.Flow;
 
let nscale = 0.68
let nwidth = 1040;
let nheight = 320;
const f = new Factory({
  renderer: { elementId: 'yonet202403Mid_Output01', width: nwidth, height: nheight * nscale }
  });
const ctx = f.getContext();
ctx.scale(nscale, nscale);
 
//ctx.setBackgroundFillStyle('#EEEEEE');
 
const defaultStyle = {
  lineWidth: ctx.lineWidth,
  strokeStyle: ctx.strokeStyle,
};
 
for (let i = 0; i <= nwidth * (1 / nscale); i += 10) {
  ctx.beginPath();
  ctx.moveTo(0 + i, 0);
  ctx.lineTo(0 + i, nheight);
  if (i % 100 === 0){
    ctx.setLineWidth(1); // 線の太さ
    ctx.setStrokeStyle('rgba(200, 200, 200, 0.8)');
  }
  else{
    ctx.setLineWidth(0.5); // 線の太さ
    ctx.setStrokeStyle('rgba(230, 230, 230, 0.8)');
  }
  ctx.stroke();
}


      // 描画コンテキストの設定
for (let i = 0; i <= nheight; i += 10) {
      const div = document.getElementById("Output");
  ctx.beginPath();
      const renderer = new VF.Renderer(div, VF.Renderer.Backends.SVG);
  ctx.moveTo(0, i);
      const context = renderer.getContext();
  ctx.lineTo(nwidth * (1 / nscale), i);
  if (i % 100 === 0){
    ctx.setLineWidth(1); // 線の太さ
    ctx.setStrokeStyle('rgba(200, 200, 200, 0.8)');
  }
  else{
    ctx.setLineWidth(0.5); // 線の太さ
    ctx.setStrokeStyle('rgba(230, 230, 230, 0.8)');
  }
  ctx.stroke();
}


      // 楽譜オブジェクトの作成
// 横線を引く
      const stave = new VF.Stave(10, 40, 500);
//for (let i = stave.y; i <= stave.y + stave.height; i += 10) {
//  ctx.beginPath();
//  ctx.moveTo(stave.x, i);
//  ctx.lineTo(stave.x + stave.width, i);
//  ctx.stroke();
//}


      // ボイスの作成
ctx.lineWidth = defaultStyle.lineWidth;
      const voice = new VF.Voice({ num_beats: 4, beat_value: 4 });
ctx.strokeStyle = defaultStyle.strokeStyle;


      // ノートの作成 (小節をまたぐ場合)
const stave1 = new Stave(10, 50, 350).setContext(ctx);
      const notes1 = [
stave1.addClef("treble").setContext(ctx);
        new VF.StaveNote({
stave1.addTimeSignature('4/4').setContext(ctx);
          keys: ["C/4", "E/4", "G/4"],
          duration: "q",
          auto_stem: true,
        }),
        new VF.StaveNote({
          keys: ["C/5", "E/5", "G/5"],
          duration: "q",
          auto_stem: true,
        }),
      ];


      // ノートの作成 (小節をまたがない場合)
const stave2 = new Stave(stave1.x, stave1.y + 100, 350).setContext(ctx);
      const notes2 = [
stave2.addClef("treble").setContext(ctx);
        new VF.StaveNote({
stave2.addTimeSignature('4/4').setContext(ctx);
          keys: ["B/4", "D/4", "F/4"],
          duration: "h",
          auto_stem: true,
        }),
        new VF.StaveNote({
          keys: ["A/4", "C/5", "E/5"],
          duration: "h",
          auto_stem: true,
        }),
      ];


      // スラーの作成 (小節をまたぐ場合)
const notes1 = [
      const slur1 = new VF.StaveTie({
  new StaveNote({ keys: ["d/5"], duration: "q" }),
        first_note: notes1[0],
  new StaveNote({ keys: ["e/5"], duration: "q" }),
        last_note: notes1[1],
  new StaveNote({ keys: ["f/5"], duration: "q" }),
        first_indices: [0],
  new StaveNote({ keys: ["g/5"], duration: "q" }),
        last_indices: [0],
];
      });


      // スラーの作成 (小節をまたがない場合)
stave1.draw();
      const slur2 = new VF.StaveTie({
        first_note: notes2[0],
        last_note: notes2[1],
        first_indices: [0],
        last_indices: [0],
      });


      // ボイスにノートを追加
const tie1 = new StaveTie({
      voice.addTickables(notes1);
  first_note: notes1[1],
      voice.addTickables(notes2);
  last_note: notes1[2],
  first_indices: [0],
  last_indices: [0],
});


      // 楽譜にボイスを追加
const tie2 = new StaveTie({
      stave.addClef("treble").addTimeSignature("4/4");
  first_note: notes1[2],
      stave.draw(context);
  last_note: notes1[3],
      voice.draw(context, stave);
  first_indices: [0],
      slur1.setContext(context).draw();
  last_indices: [0],
      slur2.setContext(context).draw();
});
    });
 
Formatter.FormatAndDraw(ctx, stave1, notes1);
tie1.setContext(ctx).draw();
tie2.setContext(ctx).draw();
 
stave2.draw();
 
const notes2 = [
  new StaveNote({ keys: ["a/4"], duration: "q" }),
  new StaveNote({ keys: ["b/4"], duration: "q" }),
  new StaveNote({ keys: ["c/5"], duration: "q" }),
  new StaveNote({ keys: ["d/5"], duration: "q" }),
];
 
Formatter.FormatAndDraw(ctx, stave2, notes2);
 
const tie3 = new StaveTie({
  first_note: notes2[1],
  last_note: notes2[2],
  first_indices: [0],
  last_indices: [0],
});
 
const tie4 = new StaveTie({
  first_note: notes2[2],
  last_note: notes2[3],
  first_indices: [0],
  last_indices: [0],
});
 
tie3.setContext(ctx).draw();
tie4.setContext(ctx).draw();
 
const stave3 = new Stave(stave2.width + stave2.x, stave2.y, 350).setContext(ctx);
const notes3 = [
  new StaveNote({ keys: ["e/5"], duration: "q" }),
  new StaveNote({ keys: ["f/5"], duration: "q" }),
  new StaveNote({ keys: ["g/5"], duration: "q" }),
  new StaveNote({ keys: ["a/5"], duration: "q" }),
];
 
stave3.draw();
 
Formatter.FormatAndDraw(ctx, stave3, notes3);
 
const tie5 = new StaveTie({
  first_note: notes2[3],
  last_note: notes3[0],
  first_indices: [0],
  last_indices: [0],
});
 
tie5.setContext(ctx).draw();
 
// 灰色の背景
ctx.setFillStyle('#F5F5F5'); // 灰色に設定
ctx.fillRect(0, 0, f.width, f.height);


})();
})();
const svgElement = document.querySelector('#Output svg');
svgElement.style.backgroundColor = '#F5F5F5';
  const svgNS = 'http://www.w3.org/2000/svg';
  const lineColor = '#EEEEEE';
  //
  // 縦線(10pxごと)
  //for (let x = 10; x < svgElement.getAttribute('width'); x += 10) {
  //  const line = document.createElementNS(svgNS, 'line');
  //  line.setAttribute('x1', x);
  //  line.setAttribute('y1', 0);
  //  line.setAttribute('x2', x);
  //  line.setAttribute('y2', svgElement.getAttribute('height'));
  //  line.setAttribute('stroke', lineColor);
  //  line.setAttribute('stroke-width', '1');
  //  svgElement.appendChild(line);
  //}
  // 横線(10pxごと)
  //for (let y = 10; y < svgElement.getAttribute('height'); y += 10) {
  //  const line = document.createElementNS(svgNS, 'line');
  //  line.setAttribute('x1', 0);
  //  line.setAttribute('y1', y);
  //  line.setAttribute('x2', svgElement.getAttribute('width'));
  //  line.setAttribute('y2', y);
  //  line.setAttribute('stroke', lineColor);
  //  line.setAttribute('stroke-width', '1');
  //  svgElement.appendChild(line);
  //}
 
</yjavascript>
</yjavascript>


91行目: 207行目:


<syntaxhighlight lang="javascript" line start="1">
<syntaxhighlight lang="javascript" line start="1">
<div id="yonet202303Mid_Output01"></div>
<div id="yonet202403Mid_Output01"></div>
<script>
<script>
(function(){
(function(){
  const {
const {
    Factory,
  Factory,
    Stave,
  Stave,
    StaveNote,
  StaveNote,
    GhostNote,
  Formatter,
    Formatter,
  Voice,
    Voice,
  StaveTie,
    Barline,
   Renderer
    Accidental,
} = Vex.Flow;
    Beam,
    StaveTie,
   } = Vex.Flow;


  const f = new Factory({ renderer: { elementId: 'yonet202303Mid_Output01', width: 1500, height: 195 } });
let nscale = 0.5
  const ctx = f.getContext();
let nwidth = 1040;
  const stave1 = new Stave(10, 50, 350).setContext(ctx).draw();
let nheight = 320;
  stave1.addClef("treble").setContext(ctx).draw();
const f = new Factory({  
  stave1.addTimeSignature('C').setContext(ctx).draw();
  renderer: { elementId: 'yonet202403Mid_Output01', width: nwidth, height: nheight * nscale }
  });
const ctx = f.getContext();
ctx.scale(nscale, nscale);


  const notes1 = [
const defaultStyle = {
    new StaveNote({ keys: ["d/5"], duration: "8" }),
  lineWidth: ctx.lineWidth,
    new StaveNote({ keys: ["d/5"], duration: "8" }),
  strokeStyle: ctx.strokeStyle,
    new StaveNote({ keys: ["d/5"], duration: "4" }),
};
    new StaveNote({ keys: ["d/5"], duration: "2" }),
  ];
  Formatter.FormatAndDraw(ctx, stave1, notes1);


const ties1 = [
for (let i = 0; i <= nwidth * (1 / nscale); i += 10) {
    new StaveTie({
  ctx.beginPath();
        first_note: notes1[1],
  ctx.moveTo(0 + i, 0);
        last_note: notes1[2],
  ctx.lineTo(0 + i, nheight);
        first_indices: [0],
  if (i % 100 === 0){
        last_indices: [0],
    ctx.setLineWidth(1); // 線の太さ
    }),
    ctx.setStrokeStyle('rgba(200, 200, 200, 0.8)');
    new StaveTie({
  }
        first_note: notes1[2],
  else{
        last_note: notes1[3],
    ctx.setLineWidth(0.5); // 線の太さ
        first_indices: [0],
    ctx.setStrokeStyle('rgba(230, 230, 230, 0.8)');
        last_indices: [0],
  }
    }),
  ctx.stroke();
}
 
for (let i = 0; i <= nheight; i += 10) {
  ctx.beginPath();
  ctx.moveTo(0, i);
  ctx.lineTo(nwidth * (1 / nscale), i);
  if (i % 100 === 0){
    ctx.setLineWidth(1); // 線の太さ
    ctx.setStrokeStyle('rgba(200, 200, 200, 0.8)');
  }
  else{
    ctx.setLineWidth(0.5); // 線の太さ
    ctx.setStrokeStyle('rgba(230, 230, 230, 0.8)');
  }
  ctx.stroke();
}
 
ctx.lineWidth = defaultStyle.lineWidth;
ctx.strokeStyle = defaultStyle.strokeStyle;
 
const stave1 = new Stave(10, 50, 350).setContext(ctx);
stave1.addClef("treble").setContext(ctx);
stave1.addTimeSignature('4/4').setContext(ctx);
 
const stave2 = new Stave(stave1.x, stave1.y + 100, 350).setContext(ctx);
stave2.addClef("treble").setContext(ctx);
stave2.addTimeSignature('4/4').setContext(ctx);
 
const notes1 = [
  new StaveNote({ keys: ["d/5"], duration: "q" }),
  new StaveNote({ keys: ["e/5"], duration: "q" }),
  new StaveNote({ keys: ["f/5"], duration: "q" }),
  new StaveNote({ keys: ["g/5"], duration: "q" }),
];
 
stave1.draw();
 
const tie1 = new StaveTie({
  first_note: notes1[1],
  last_note: notes1[2],
  first_indices: [0],
  last_indices: [0],
});
 
const tie2 = new StaveTie({
  first_note: notes1[2],
  last_note: notes1[3],
  first_indices: [0],
  last_indices: [0],
});
 
Formatter.FormatAndDraw(ctx, stave1, notes1);
tie1.setContext(ctx).draw();
tie2.setContext(ctx).draw();
 
stave2.draw();
 
const notes2 = [
  new StaveNote({ keys: ["a/4"], duration: "q" }),
  new StaveNote({ keys: ["b/4"], duration: "q" }),
  new StaveNote({ keys: ["c/5"], duration: "q" }),
  new StaveNote({ keys: ["d/5"], duration: "q" }),
];
 
Formatter.FormatAndDraw(ctx, stave2, notes2);
 
const tie3 = new StaveTie({
  first_note: notes2[1],
  last_note: notes2[2],
  first_indices: [0],
  last_indices: [0],
});
 
const tie4 = new StaveTie({
  first_note: notes2[2],
  last_note: notes2[3],
  first_indices: [0],
  last_indices: [0],
});
 
tie3.setContext(ctx).draw();
tie4.setContext(ctx).draw();
 
const stave3 = new Stave(stave2.width + stave2.x, stave2.y, 350).setContext(ctx);
const notes3 = [
  new StaveNote({ keys: ["e/5"], duration: "q" }),
  new StaveNote({ keys: ["f/5"], duration: "q" }),
  new StaveNote({ keys: ["g/5"], duration: "q" }),
  new StaveNote({ keys: ["a/5"], duration: "q" }),
];
];


ties1.forEach((t) => {
stave3.draw();
    t.setContext(ctx).draw();
 
Formatter.FormatAndDraw(ctx, stave3, notes3);
 
const tie5 = new StaveTie({
  first_note: notes2[3],
  last_note: notes3[0],
  first_indices: [0],
  last_indices: [0],
});
});
tie5.setContext(ctx).draw();
// 灰色の背景
ctx.setFillStyle('#F5F5F5'); // 灰色に設定
ctx.fillRect(0, 0, f.width, f.height);


})();
})();
const svgElement = document.querySelector('#Output svg');
svgElement.style.backgroundColor = '#F5F5F5';
const svgNS = 'http://www.w3.org/2000/svg';
const lineColor = '#EEEEEE';
 
</script>
</script>
</syntaxhighlight>
</syntaxhighlight>




 StaveTie というオブジェクトを利用します。
 スラーでもStaveTie というオブジェクトを利用します。




158行目: 379行目:
*first_indices: タイの始まりの音符の和音の番号を設定します。和音になっていない場合は配列番号 0 を指定します。例:[0]
*first_indices: タイの始まりの音符の和音の番号を設定します。和音になっていない場合は配列番号 0 を指定します。例:[0]
*last_indices: タイの終わりの音符の和音の番号を設定します。和音になっていない場合は配列番号 0 を指定します。例:[0]
*last_indices: タイの終わりの音符の和音の番号を設定します。和音になっていない場合は配列番号 0 を指定します。例:[0]


 
 


[[VexFlow 使い方]]に戻る。
[[VexFlow 使い方]]に戻る。

2024年3月11日 (月) 01:10時点における最新版

VexFlow 使い方に戻る。

概要

 スラーは異なる高さの音同士を区切らずに演奏する奏法に使います。


基本的にはStaveTieタイと同じです。ですが、Curveを使う方法もある感じです。  

スラー

 コードは以下のとおりです。

<div id="yonet202403Mid_Output01"></div>
<script>
(function(){
const {
  Factory,
  Stave,
  StaveNote,
  Formatter,
  Voice,
  StaveTie,
  Renderer
} = Vex.Flow;

let nscale = 0.5
let nwidth = 1040;
let nheight = 320;
const f = new Factory({ 
  renderer: { elementId: 'yonet202403Mid_Output01', width: nwidth, height: nheight * nscale }
  });
const ctx = f.getContext();
ctx.scale(nscale, nscale);

const defaultStyle = {
  lineWidth: ctx.lineWidth,
  strokeStyle: ctx.strokeStyle,
};

for (let i = 0; i <= nwidth * (1 / nscale); i += 10) {
  ctx.beginPath();
  ctx.moveTo(0 + i, 0);
  ctx.lineTo(0 + i, nheight);
  if (i % 100 === 0){
    ctx.setLineWidth(1); // 線の太さ
    ctx.setStrokeStyle('rgba(200, 200, 200, 0.8)');
  }
  else{
    ctx.setLineWidth(0.5); // 線の太さ
    ctx.setStrokeStyle('rgba(230, 230, 230, 0.8)');
  }
  ctx.stroke();
}

for (let i = 0; i <= nheight; i += 10) {
  ctx.beginPath();
  ctx.moveTo(0, i);
  ctx.lineTo(nwidth * (1 / nscale), i);
  if (i % 100 === 0){
    ctx.setLineWidth(1); // 線の太さ
    ctx.setStrokeStyle('rgba(200, 200, 200, 0.8)');
  }
  else{
    ctx.setLineWidth(0.5); // 線の太さ
    ctx.setStrokeStyle('rgba(230, 230, 230, 0.8)');
  }
  ctx.stroke();
}

ctx.lineWidth = defaultStyle.lineWidth;
ctx.strokeStyle = defaultStyle.strokeStyle;

const stave1 = new Stave(10, 50, 350).setContext(ctx);
stave1.addClef("treble").setContext(ctx);
stave1.addTimeSignature('4/4').setContext(ctx);

const stave2 = new Stave(stave1.x, stave1.y + 100, 350).setContext(ctx);
stave2.addClef("treble").setContext(ctx);
stave2.addTimeSignature('4/4').setContext(ctx);

const notes1 = [
  new StaveNote({ keys: ["d/5"], duration: "q" }),
  new StaveNote({ keys: ["e/5"], duration: "q" }),
  new StaveNote({ keys: ["f/5"], duration: "q" }),
  new StaveNote({ keys: ["g/5"], duration: "q" }),
];

stave1.draw();

const tie1 = new StaveTie({
  first_note: notes1[1],
  last_note: notes1[2],
  first_indices: [0],
  last_indices: [0],
});

const tie2 = new StaveTie({
  first_note: notes1[2],
  last_note: notes1[3],
  first_indices: [0],
  last_indices: [0],
});

Formatter.FormatAndDraw(ctx, stave1, notes1);
tie1.setContext(ctx).draw();
tie2.setContext(ctx).draw();

stave2.draw();

const notes2 = [
  new StaveNote({ keys: ["a/4"], duration: "q" }),
  new StaveNote({ keys: ["b/4"], duration: "q" }),
  new StaveNote({ keys: ["c/5"], duration: "q" }),
  new StaveNote({ keys: ["d/5"], duration: "q" }),
];

Formatter.FormatAndDraw(ctx, stave2, notes2);

const tie3 = new StaveTie({
  first_note: notes2[1],
  last_note: notes2[2],
  first_indices: [0],
  last_indices: [0],
});

const tie4 = new StaveTie({
  first_note: notes2[2],
  last_note: notes2[3],
  first_indices: [0],
  last_indices: [0],
});

tie3.setContext(ctx).draw();
tie4.setContext(ctx).draw();

const stave3 = new Stave(stave2.width + stave2.x, stave2.y, 350).setContext(ctx);
const notes3 = [
  new StaveNote({ keys: ["e/5"], duration: "q" }),
  new StaveNote({ keys: ["f/5"], duration: "q" }),
  new StaveNote({ keys: ["g/5"], duration: "q" }),
  new StaveNote({ keys: ["a/5"], duration: "q" }),
];

stave3.draw();

Formatter.FormatAndDraw(ctx, stave3, notes3);

const tie5 = new StaveTie({
  first_note: notes2[3],
  last_note: notes3[0],
  first_indices: [0],
  last_indices: [0],
});

tie5.setContext(ctx).draw();

// 灰色の背景
ctx.setFillStyle('#F5F5F5'); // 灰色に設定
ctx.fillRect(0, 0, f.width, f.height);

})();

const svgElement = document.querySelector('#Output svg');
svgElement.style.backgroundColor = '#F5F5F5';
const svgNS = 'http://www.w3.org/2000/svg';
const lineColor = '#EEEEEE';
  
</script>


 スラーでもStaveTie というオブジェクトを利用します。


 配列で [new StaveTie({オブジェクト}), …] という構造のものを用意し、配列を代入した変数を作ります。


 const Ties1 = [new StaveTie({オブジェクト}), new StaveTie({オブジェクト})]; のような形式です。オブジェクトには以下のようなキーと値を設定します。


  • first_note: タイの始まりの音符を設定します。例:notes1[2]
  • last_note: タイの終わりの音符を設定します。例:notes1[3]
  • first_indices: タイの始まりの音符の和音の番号を設定します。和音になっていない場合は配列番号 0 を指定します。例:[0]
  • last_indices: タイの終わりの音符の和音の番号を設定します。和音になっていない場合は配列番号 0 を指定します。例:[0]

 

VexFlow 使い方に戻る。