質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.34%
SVG

SVGは、XMLを基盤とした2Dベクター画像記述言語。画像を線・面といった図形の集合体として扱うベクター画像のため、環境に適した表示が可能です。アニメーション機能もサポートされており、簡単なインタラクティブコンテンツ作成もできます。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

1回答

164閲覧

javascript vexFlowで作成したSVG楽譜データをPDFにしたい

tossyk

総合スコア3

SVG

SVGは、XMLを基盤とした2Dベクター画像記述言語。画像を線・面といった図形の集合体として扱うベクター画像のため、環境に適した表示が可能です。アニメーション機能もサポートされており、簡単なインタラクティブコンテンツ作成もできます。

PDF

PDF(Portable Document Format)とはISOによって国際標準として制定されている電子ドキュメント用の拡張子です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2024/12/30 04:09

編集2024/12/30 04:11

イメージ説明### 実現したいこと
javascript vexFlowで作成したSVGデータをPDFにできること

発生している問題・分からないこと

PDFとして出力するところまではできたが、上記添付画像のように楽譜の表記が崩れる

該当のソースコード

javascript

1// vexFlowで五線譜作成 2const stave = new Stave(10, 40, 500); 3 4const renderer = new Renderer(div, Renderer.Backends.SVG); 5renderer.resize(600, 200); 6const context = renderer.getContext(); 7 8stave.addClef("treble").addTimeSignature("4/4"); 9 10stave.setContext(context).draw(); 11 12const notes = [ 13 new StaveNote({ keys: ["c/5"], duration: "q" }), 14 new StaveNote({ keys: ["d/4"], duration: "q" }), 15 new StaveNote({ keys: ["b/4"], duration: "qr" }), 16 new StaveNote({ keys: ["c/4", "e/4", "g/4"], duration: "q" }), 17] 18 19const notes2 = [ 20 new StaveNote({ keys: ["c/4"], duration: "w" }) 21] 22 23const voice1 = new Voice({ num_beats: 4, beat_value: 4 }) 24const voice2 = new Voice({ num_beats: 4, beat_value: 4 }) 25 26const voices = [ 27 voice1.addTickables(notes), 28 voice2.addTickables(notes2) 29] 30new Formatter().joinVoices(voices).format(voices, 350) 31 32voices.forEach(function (v) { 33 v.draw(context, stave) 34}); 35 36// ボタンをクリックしたら、PDFとしてダウンロードする 37document.getElementById('pdf').addEventListener('click', async () => { 38 const svgElement = div.querySelector("svg"); 39 svgElement.setAttribute("viewBox", `0 0 ${svgElement.getBBox().width} ${svgElement.getBBox().height}`); 40 svgElement.setAttribute("width", svgElement.width.animVal.valueAsString); 41 svgElement.setAttribute("height", svgElement.height.animVal.valueAsString); 42 const svgData = new XMLSerializer().serializeToString(svgElement); 43 44 const pdfDoc = await PDFDocument.create(); 45 const page = pdfDoc.addPage([1000, 1000]); 46 page.drawSvgPath(svgData, { x: 10, y: 900, color: rgb(0, 0, 0), scale: 1.0, }); 47 const pdfBytes = await pdfDoc.save(); 48 const blob = new Blob([pdfBytes], { type: "application/pdf" }); 49 const url = URL.createObjectURL(blob); 50 const a = document.createElement("a"); 51 a.href = url; 52 a.download = "sheet_music.pdf"; 53 a.click(); 54});

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

X軸やY軸の数字を修正して試してみましたが改善されませんでした。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

Chat GPTに回答してもらいました

html

1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>VexFlow Example</title> 7 <script src="https://cdn.jsdelivr.net/npm/vexflow@4.2.2/build/cjs/vexflow.js"></script> 8 <script src="https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.min.js"></script> 9 <style> 10 #svg { 11 width: 600px; 12 height: auto; 13 } 14 #downloadBtn { 15 margin-top: 20px; 16 padding: 10px 20px; 17 background-color: #4CAF50; 18 color: white; 19 border: none; 20 cursor: pointer; 21 font-size: 16px; 22 } 23 #downloadBtn:hover { 24 background-color: #45a049; 25 } 26 </style> 27</head> 28<body> 29 <div id="pdf"> 30 <div id="svg"></div> 31 </div> 32 33 <button id="downloadBtn">Download PDF</button> 34 35 <script> 36 const { Renderer, Stave, StaveNote, Voice, Formatter } = Vex.Flow; 37 38 // HTML内の要素を取得 39 const div = document.getElementById('svg'); 40 41 // Rendererの初期化 42 const renderer = new Renderer(div, Renderer.Backends.SVG); 43 renderer.resize(600, 300); // サイズ設定 44 const context = renderer.getContext(); 45 46 // 五線譜の作成 47 const stave = new Stave(10, 40, 500); 48 stave.addClef('treble').addTimeSignature('4/4'); 49 stave.setContext(context).draw(); 50 51 // 音符を追加 52 const notes = [ 53 new StaveNote({ keys: ["c/5"], duration: "q" }), 54 new StaveNote({ keys: ["d/4"], duration: "q" }), 55 new StaveNote({ keys: ["b/4"], duration: "qr" }), 56 new StaveNote({ keys: ["c/4", "e/4", "g/4"], duration: "q" }) 57 ]; 58 59 const notes2 = [ 60 new StaveNote({ keys: ["c/4"], duration: "w" }) 61 ]; 62 63 const voice1 = new Voice({ num_beats: 4, beat_value: 4 }); 64 const voice2 = new Voice({ num_beats: 4, beat_value: 4 }); 65 66 const voices = [ 67 voice1.addTickables(notes), 68 voice2.addTickables(notes2) 69 ]; 70 new Formatter().joinVoices(voices).format(voices, 350); 71 72 voices.forEach(function(v) { 73 v.draw(context, stave); 74 }); 75 76 // PDF作成とダウンロード 77 document.getElementById('downloadBtn').addEventListener('click', async () => { 78 const svgElement = div.querySelector("svg"); 79 svgElement.setAttribute("viewBox", `0 0 ${svgElement.getBBox().width} ${svgElement.getBBox().height}`); 80 svgElement.setAttribute("width", svgElement.width.animVal.valueAsString); 81 svgElement.setAttribute("height", svgElement.height.animVal.valueAsString); 82 const svgData = new XMLSerializer().serializeToString(svgElement); 83 84 // SVGをcanvasに描画してPNGに変換 85 const canvas = document.createElement("canvas"); 86 const ctx = canvas.getContext("2d"); 87 88 const img = new Image(); 89 const svgBlob = new Blob([svgData], { type: "image/svg+xml" }); 90 const url = URL.createObjectURL(svgBlob); 91 92 img.onload = async () => { 93 // canvasにSVGを描画 94 canvas.width = img.width; 95 canvas.height = img.height; 96 ctx.drawImage(img, 0, 0); 97 98 // PNGに変換 99 const pngDataUrl = canvas.toDataURL("image/png"); 100 101 // PDF作成 102 const pdfDoc = await PDFLib.PDFDocument.create(); 103 104 // PDFのページサイズを画像のサイズに合わせる 105 const pdfWidth = img.width; 106 const pdfHeight = img.height; 107 const page = pdfDoc.addPage([pdfWidth, pdfHeight]); 108 109 // 画像をPDFに埋め込む 110 const pngImage = await pdfDoc.embedPng(pngDataUrl); 111 page.drawImage(pngImage, { x: 0, y: 0, width: pdfWidth, height: pdfHeight }); 112 113 // PDFを保存 114 const pdfBytes = await pdfDoc.save(); 115 const blob = new Blob([pdfBytes], { type: "application/pdf" }); 116 const pdfUrl = URL.createObjectURL(blob); 117 const a = document.createElement("a"); 118 a.href = pdfUrl; 119 a.download = "sheet_music.pdf"; 120 a.click(); 121 }; 122 123 img.src = url; 124 }); 125 </script> 126</body> 127</html> 128

投稿2025/01/01 02:52

takashikawai

総合スコア195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.34%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問