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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

SVG

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

JavaScript

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

Q&A

解決済

2回答

1212閲覧

【JavaScript】SVGをcanvasへ変換したときに画像が透明にならないようにしたい

lookman

総合スコア4

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

SVG

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

JavaScript

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

0グッド

1クリップ

投稿2023/01/18 04:51

編集2023/01/18 05:20

目的と実現方法

JavaScriptのみで、dot言語をpng画像に変換し、HTML上に出力したいです。そのために「dot言語→SVG→canvas→png画像」の順で変換することにしました。

発生している問題

Viz.jsによって「dot言語→SVG」の変換はできています。しかし「SVG→canvas」の箇所で、画像が透明になって出力されてしまいます。
つまり、下記の"dotToSVGElement"関数は正常に動いていますが、"SVGElementToPng"関数で不具合が発生しています。
出力結果の画像は、ブラウザの開発者ツール(F12)にあるApplicationタブから、確認しています。使用ブラウザはChromeです。

該当のソースコード

HTML

1<body> 2<img id="graph"> 3<script type="text/javascript" src="https://unpkg.com/viz.js@1.8.0"></script> 4</body>

JavaScript

1const dot = `graph G {A--B; B--C;}`; 2 3function dotToPng(dot) { 4 const output = document.getElementById("graph");// img 5 const svg = dotToSVGElement(dot); 6 SVGElementToPng(output, svg); 7 document.getElementById("svg").appendChild(svg); 8 console.log(dot, svg); 9} 10 11function dotToSVGElement(dot) { 12 const container = document.createElement("div"); 13 container.innerHTML = Viz(dot, {format: "svg"}); 14 return container.querySelector("svg"); 15} 16 17function SVGElementToPng(output, svg) { 18 const image = new Image(); 19 image.addEventListener("load", () => { 20 const width = svg.getAttribute("width"); 21 const height = svg.getAttribute("height"); 22 const canvas = document.createElement("canvas"); 23 24 canvas.setAttribute("width", width); 25 canvas.setAttribute("height", height); 26 27 const context = canvas.getContext("2d"); 28 context.drawImage(image, 0, 0, width, height); 29 30 const dataUrl = canvas.toDataURL("image/png"); 31 output.src = dataUrl; 32 }); 33 34 const svgData = new XMLSerializer().serializeToString(svg); 35 const svgDataBase64 = btoa(unescape(encodeURIComponent(svgData))); 36 const svgDataUrl = `data:image/svg+xml;charset=utf-8;base64,${svgDataBase64}`; 37 38 image.src = svgDataUrl; 39} 40 41dotToPng(dot);

知りたいこと

SVGをcanvasに変換したときに、透明にならないようにするためには、どのようにソースを変更すればよいのでしょうか?

参考にしたサイト

https://zenn.dev/tatsuyasusukida/articles/javascript-svg-png
https://qiita.com/basho/items/431af27b2fc6e90c9469

【追記】変数svgDataUrlのアドレス

data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iNjJwdCIgaGVpZ2h0PSIxODhwdCIgdmlld0JveD0iMC4wMCAwLjAwIDYyLjAwIDE4OC4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAxODQpIj4KPHRpdGxlPkc8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjZmZmZmZmIiBzdHJva2U9InRyYW5zcGFyZW50IiBwb2ludHM9Ii00LDQgLTQsLTE4NCA1OCwtMTg0IDU4LDQgLTQsNCIvPgo8IS0tIEEgLS0+CjxnIGlkPSJub2RlMSIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+QTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzY5Njk2OSIgcG9pbnRzPSI1NCwtMTgwIDAsLTE4MCAwLC0xNDQgNTQsLTE0NCA1NCwtMTgwIi8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjI3IiB5PSItMTU3LjgiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0LjAwIiBmaWxsPSIjNjk2OTY5Ij5BPC90ZXh0Pgo8L2c+CjwhLS0gQiAtLT4KPGcgaWQ9Im5vZGUyIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT5CPC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjk2OTY5IiBwb2ludHM9IjU0LC0xMDggMCwtMTA4IDAsLTcyIDU0LC03MiA1NCwtMTA4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjI3IiB5PSItODUuOCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM2OTY5NjkiPkI8L3RleHQ+CjwvZz4KPCEtLSBBJiM0NTsmIzQ1O0IgLS0+CjxnIGlkPSJlZGdlMSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+QS0tQjwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzY5Njk2OSIgZD0iTTI3LC0xNDMuODMxNEMyNywtMTMzIDI3LC0xMTkuMjg3NiAyNywtMTA4LjQxMzMiLz4KPC9nPgo8IS0tIEMgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+QzwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzY5Njk2OSIgcG9pbnRzPSI1NCwtMzYgMCwtMzYgMCwwIDU0LDAgNTQsLTM2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjI3IiB5PSItMTMuOCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiIGZpbGw9IiM2OTY5NjkiPkM8L3RleHQ+CjwvZz4KPCEtLSBCJiM0NTsmIzQ1O0MgLS0+CjxnIGlkPSJlZGdlMiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+Qi0tQzwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzY5Njk2OSIgZD0iTTI3LC03MS44MzE0QzI3LC02MSAyNywtNDcuMjg3NiAyNywtMzYuNDEzMyIvPgo8L2c+CjwvZz4KPC9zdmc+

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

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

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

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

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

miyabi_takatsuk

2023/01/18 05:01

loadイベント内で取得した画像の、widthとheightは取得できていますか? なんとなくですが、SVGの場合、大きさが明記されてないと、大きさが自動で決まることがないので、 それが原因な気がします。
int32_t

2023/01/18 05:05

変数 svgDataUrl の内容をブラウザのアドレスバーに入れると期待通りのものが表示されますか?
lookman

2023/01/18 05:20

@miyabi_takatsuk さん はい。widthとheightは、取得できているようです。 20,21行目で定義した「width,height」の値は「62pt,188pt」でした。これらはconsole.logで確認しましたが、この値はApplicationタブから確認した画像サイズとも一致しています。 ちなみに、SVG画像の方は「83×251」で、pngとはズレています。 @int32_t さん はい。ご指摘いただいた方法で確認したところ、意図通りの画像が表示されました。長かったので、当該アドレスはこちらではなく本文に追記しました。
int32_t

2023/01/18 05:27

「context.drawImage(image, 0, 0, "62pt", "188pt");」だと失敗するかもですね。
lookman

2023/01/18 05:51

質問および回答をくださった皆さま、無事に不具合が解決しました。こちらでも重ねてお礼申し上げます。
guest

回答2

0

javascript

1function SVGElementToPng(output, svg) { 2 const src = "data:image/svg+xml;charset=utf-8;base64," + btoa(new XMLSerializer().serializeToString(svg)); 3 const canvas = Object.assign(document.createElement("canvas"),{width:svg.width.baseVal.value,height:svg.height.baseVal.value}); 4 const ctx = canvas.getContext("2d"); 5 const image = new Image; 6 image.addEventListener('load',()=>{ 7 ctx.drawImage( image, 0, 0 ); 8 output.src=canvas.toDataURL("image/png"); 9 }); 10 image.src = src; 11} 12

投稿2023/01/18 05:38

編集2023/01/18 05:39
yambejp

総合スコア114896

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

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

lookman

2023/01/18 05:49

@yambejp さん 3行目の"Object.assign"を用いた変数定義の仕方は知りませんでした! ベストアンサーは他の方にお譲りしましたが、こちらを参考にソースの修正をさせていただきます。 行数削減は嬉しいですからね。回答ありがとうございました。
guest

0

ベストアンサー

js

1 canvas.setAttribute("width", width); 2 canvas.setAttribute("height", height); 3 4 const context = canvas.getContext("2d"); 5 context.drawImage(image, 0, 0, width, height);

<canvas>width height 属性は整数のみ受け付けます。62pt のような文字列は不正です。
imagenaturalWidth naturalHeight を利用するのはいかがでしょうか。

js

1 canvas.width = image.naturalWidth; 2 canvas.height = image.naturalHeight; 3 4 const context = canvas.getContext("2d"); 5 context.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight);

投稿2023/01/18 05:33

編集2023/01/18 05:35
int32_t

総合スコア20925

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

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

lookman

2023/01/18 05:46

@int32_t さん ご指摘の通りに変更したところ、正常に動くようになりました。 最速かつ正確な回答、ありがとうございます。文句なしでベストアンサーです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問