9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScriptAdvent Calendar 2021

Day 14

SVG.jsのテキストについて詳しく調べてみる

Last updated at Posted at 2021-12-13

SVG.jsのライブラリのテキスト関係の仕様について色々コードを書いて試しつつ確認していくための記事です。

使うもの

前提

SVGの仕様上、普通のHTMLのテキストでさくっとできることができないケースが結構あります(固定幅によるテキストの折り返しなど)。一方で複雑なアニメーションなどでSVGのテキストの方が自由度が高いケースがある・・・といった感じのようです。SVGで大半のことができる・・・というわけではないので使い分けが必要そうです。

Textクラス

以降の節でテキストを扱う基本のクラスとなるTextクラスについて触れていきます。

インスタンスの作り方

textメソッドで引数に文字列を指定することで作成できるようです。

var draw = SVG().addTo('body').size(500, 300);

var text = draw.text(
  'Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
text.move(20, 20);

image.png

もしくは関数を指定して、その中でtspanメソッドでテキスト要素を追加するということもできるようです(個別の設定などができるようになります)。

var draw = SVG().addTo('body').size(500, 300);

var text = draw.text(function(add) {
  add.tspan('Lorem ipsum dolor sit amet, \n');
  add.tspan('consectetur adipiscing elit.').fill('#0af');
});
text.move(20, 20);

image.png

textメソッド

textメソッドではTextインスタンスに設定されているテキスト内容の取得や更新を行うことができます。

var draw = SVG().addTo('body').size(500, 300);

var text = draw.text('Lorem ipsum dolor sit amet, ');
text.move(20, 20);
text.text('consectetur adipiscing elit.');

image.png

fontメソッド

fontメソッドではフォントの種類や文字のスタイル(サイズなど)を指定したり取得することができるようです。

設定は以下のように複数の値を辞書でまとめて行えます。

var draw = SVG().addTo('body').size(500, 300);

var text_1 = draw.text('吾輩は猫である。');
text_1.move(20, 20);
text_1.font({
  family: 'MS Gothic',
  size: 16
});

var text_2 = draw.text('吾輩は猫である。');
text_2.move(20, 50);
text_2.font({
  family: 'メイリオ',
  size: 20
});

image.png

もしくは第一引数にキー、第二引数に値という形で個別に設定することも可能です。

var draw = SVG().addTo('body').size(500, 300);

var text = draw.text('吾輩は猫である。');
text.move(20, 20);
text.font('family', 'メイリオ');
text.font('size', 25);

image.png

fontメソッドで設定できる各属性

fontメソッドで設定できる各属性についてベーシックなものについて以降の節で触れていきます。svg.jsのドキュメントに加えて以下のW3Cの資料もある程度確認しつつ進めます。

family属性

family属性はフォントの種類を指定したり取得したりすることができます。

var draw = SVG().addTo('body').size(500, 300);

var text = draw.text('吾輩は猫である。');
text.move(20, 20);
text.font('size', 25);
text.font('family', 'メイリオ');

image.png

複数のフォント指定はコンマ区切りなどで行えます。

var draw = SVG().addTo('body').size(500, 300);

var text = draw.text('吾輩は猫である。');
text.move(20, 20);
text.font('size', 25);
text.font('family', 'Helvetica, メイリオ');

size属性

size属性ではテキストのサイズの変更や取得を行うことができます。

var draw = SVG().addTo('body').size(500, 300);

var text_1 = draw.text('吾輩は猫である。');
text_1.move(20, 20);
text_1.font('size', 12);

var text_2 = draw.text('吾輩は猫である。');
text_2.move(20, 50);
text_2.font('size', 18);

var text_3 = draw.text('吾輩は猫である。');
text_3.move(20, 80);
text_3.font('size', 24);

image.png

leading属性

leading属性では行間の設定や取得を行うことができます。

以下のサンプルでは上の方のテキストには1.5、下の方には2.0の行間を設定しています。

var draw = SVG().addTo('body').size(600, 300);

var text_1 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam, \nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ');
text_1.move(20, 20);
text_1.font('size', 14);
text_1.font('leading', 1.5);

var text_2 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam, \nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ');
text_2.move(20, 170);
text_2.font('size', 14);
text_2.font('leading', 2.0);

image.png

anchor属性

anchor属性はテキストの基準点を設定することができます。start, middle, endのどれかの値を設定することができます。デフォルトはstartです。それぞれ基準点がテキストの左端、中央、右端となります。行揃えもそれぞれ左揃え、中央揃え、右揃えとなります。

以下のコードでは上から順番にstart, middle, endと設定していっています。

var draw = SVG().addTo('body').size(600, 600);

var text_1 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_1.move(20, 20);
text_1.font('size', 14);

var text_2 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_2.move(300, 120);
text_2.font('size', 14);
text_2.font('anchor', 'middle');

var text_3 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam ');
text_3.move(600, 220);
text_3.font('size', 14);
text_3.font('anchor', 'end');

image.png

注意点として基準位置が変わるためX座標も調整が必要になります。例えばmiddleであればx=0の位置がテキストの中央位置になります。以下はmiddleとx=0を指定していますがテキストの半分しか表示されないことが確認できます。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text.move(0, 20);
text.font('size', 14);
text.font('anchor', 'middle');

image.png

style属性

style属性では文字の斜体設定などを行うことができます。normal(デフォルト), italic, obliqueの設定があります。obliqueってなんだ・・・?と思いましたが、どうやらイタリック体と斜体という違いで一部のフォントで表示が変わるようです。対応していなければ両方とも同じように斜体となります。

欧文フォントの中には、「イタリック体」と「斜体」用にそれぞれ専用にデザインされたフォントが用意されているものがあるようです。イタリック体は筆記体っぽくデザインされたもので、斜体は単純に斜めに倒しただけのような形です。

以下の例では上がデフォルトのnormal, 2番目にitalicを設定してあります。

var draw = SVG().addTo('body').size(600, 600);

var text_1 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_1.move(20, 20);
text_1.font('size', 14);

var text_2 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_2.move(20, 120);
text_2.font('size', 14);
text_2.font('style', 'italic');

image.png

weight属性

weight属性では文字の太さを設定することができます。

normal(デフォルト), bold(太字), bolder, lighter, 100, 200, 300, 400, 500, 600, 700, 800, 900といった値となります。色々ありますが大体使うのはnormalboldかな・・・という所感です。

bolderは現在の属性の継承値よりも太い設定が可能であれば太い表示にし、lighterは逆に属性の継承値よりも細い設定が可能であれば細い表示にします。

100900の値は細かい太さ指定です。数字が大きいほど太い表示となります。400normal相当、700bold相当になります。400よりも小さい値を設定したり700よりも大きい値を設定したとしてもフォント側がそれらの太さに対応していない場合には表示は400700などの時点のもので止まります(細かい指定に対応していないフォントも多いと思います)。

以下のコードでは上からデフォルトの設定、boldによる太字設定、700による設定をそれぞれ行っています。

var draw = SVG().addTo('body').size(600, 600);

var text_1 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_1.move(20, 20);
text_1.font('size', 14);

var text_2 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_2.move(20, 120);
text_2.font('size', 14);
text_2.font('weight', 'bold');

var text_3 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_3.move(20, 220);
text_3.font('size', 14);
text_3.font('weight', '700');

image.png

leadingメソッド

leadingメソッドでは行間をダイレクトに設定できるようです。fontメソッドでも設定できましたが、行間を設定したいだけであればこちらを使う形でもシンプルに設定することができます。

以下は2つのテキストに行間1.5と2.0をそれぞれ設定しています。

var draw = SVG().addTo('body').size(600, 600);

var text_1 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_1.move(20, 20);
text_1.leading(1.5);

var text_2 = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text_2.move(20, 160);
text_2.leading(2.0);

image.png

tspanメソッド

tspanメソッドではテキストインスタンスの内容に指定された1つのtspan要素を設定します。他のテキストなどが設定されている場合には内容が上書きされるので注意してください。tspanに関しては後の節でも詳しく触れますが、特定の表示設定などを行うことができるspan要素的なもののようです。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text('Lorem ipsum dolor sit amet, ');
text.move(20, 20);
text.tspan('\nconsectetur adipiscing elit,');

image.png

lengthメソッド

lengthメソッドではテキストインスタンスの幅(横の長さ)を取得することができます。Pythonとかに慣れ親しんでいる影響か初見の時には文字数取得のメソッドかな?と思いましたが違うようです。なお、後々触れるテキストパスなどを設定した場合でも数値は変動しないようです(見かけ上の幅とはずれうる値となります)。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text('Lorem ipsum');
text.move(20, 20);
console.log(text.length());
102.046875

pathメソッド

pathメソッドではテキストにパス設定を行い、TextPathクラスのインスタンスを返却します(テキストが指定されたパスに沿う形になります)。

パス指定に関しては別途記事にしたためこちらをご確認ください。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text('Lorem ipsum');
text.move(20, 20);
var path = 'M 50 100 Q 100 20 150 100 T 250 100';
var textPath = text.path(path);

image.png

テキストがパスに沿って配置されるようになりました。パスの長さが足りない分のテキストは非表示になります。

textPathメソッド

textPathメソッドでは設定されているパスのTextPathインスタンスを返却します。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text('Lorem ipsum');
text.move(20, 20);
var path = 'M 50 100 Q 100 20 150 100 T 250 100';
text.path(path);
var textPath = text.textPath();

clearメソッド

clearメソッドでは設定されているテキスト内容のリセットを行います。呼び出した後は新たに設定などをしないと何も表示されなくなります。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text('Lorem ipsum');
text.move(20, 20);
text.clear();

その他の共通設定

他のSVGの四角などの図形などと同じように各インターフェイスで塗り(fill)や線(stroke)の設定も行うことができます(ただし現状SVGで線を外側に配置したりができないので線の設定はそこまで利用する機会がないかもしれません・・・)。テキスト固有の設定ではないため今回の記事ではあまり触れずにスキップします。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text('Lorem ipsum dolor sit amet, \nconsectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam');
text.move(20, 20);
text.leading(1.5);
text.fill('#fff');
text.attr({'stroke-width': 0.4, stroke: '#0af'});

image.png

TextPathクラス

Textクラスでもちらっと出てきましたが以降の節ではTextPathクラスについて色々触れていきます。

インスタンスの作り方

TextPathのインスタンスはTextクラスのtextPathメソッドなどで作成する他にもSVGのインスタンスのtextPathメソッドでも作成することができます。第一引数に設定するテキストの文字列、第二引数にパスの指定が必要になります。

var draw = SVG().addTo('body').size(600, 600);

var textPath = draw.textPath(
  'Lorem ipsum dolor sit amet, consectetur',
  'M 50 100 Q 100 20 150 100 T 250 100');

なお、TextPathクラス自体はTextクラスのサブクラスになっているようで、Textクラスのようにテキストが表示されます。

image.png

サブクラスになっているのでTextで使えたような各インターフェイスはそのまま利用できます。

var draw = SVG().addTo('body').size(600, 600);

var textPath = draw.textPath(
  'Lorem ipsum dolor sit amet, consectetur',
  'M 50 100 Q 100 20 150 100 T 250 100');
textPath.fill('#0af');

image.png

arrayメソッド

arrayメソッドでは設定のグループごと(MやTなどの指定ごと)のデータを2次元配列で取得することができます。2次元目の先頭のインデックスは対象のグループの文字になります。

var draw = SVG().addTo('body').size(600, 600);

var textPath = draw.textPath(
  'Lorem ipsum dolor sit amet, consectetur',
  'M 50 100 Q 100 20 150 100 T 250 100');
console.log(textPath.array());
[["M", 50, 100], ["Q", 100, 20, 150, 100], ["T", 250, 100]]

plotメソッド

plotメソッドを使うことでパスの設定を途中で変更することができます。

以下のコードでは途中で縦方向にパスを変更しています。

var draw = SVG().addTo('body').size(600, 600);

var textPath = draw.textPath(
  'Lorem ipsum dolor sit amet, consectetur',
  'M 50 100 Q 100 20 150 100 T 250 100');
textPath.plot('M 50 50 V 300');

image.png

Tspanクラス

Textクラスでも少し出てきましたがHTMLタグのspanタグのようにテキスト内で一部だけスタイルを変更したり・・・といった場合のためのクラスとしてTspanクラスがあります。こちらもTextクラスのサブクラスとなっているようで各種スタイルなどのインターフェイスを利用できるようです。

インスタンスの作り方

Tspanクラスのインスタンスは基本的にTextクラスもしくはTspanクラス内に格納する形で利用されるため、生成処理などはTextクラスなどと一緒に利用します(TextクラスやTspanクラスが生成用のtspanメソッドを持っています)。

いくつかtspan関係のインターフェイスはありますが、一例として以下のようにTextクラス関係の記述と一緒に使います。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  add.tspan('Lorem ipsum dolor sit amet, ');
  add.tspan('consectetur adipiscing elit.').fill('#0af');
});
text.move(20, 20);

image.png

textメソッド

textメソッドで特定のTspanインスタンスのテキスト(テキスト内で特定部分のみのテキスト)を更新することができます。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  var tspan1 = add.tspan('Lorem ');
  var tspan2 = add.tspan('ipsum').fill('#0af');
  tspan1.text('dolor ');
});
text.move(20, 20);

image.png

dxメソッド

dxメソッドは対象のTspanインスタンスと直前のテキスト要素の間にX方向の座標の調整値を設定します。先頭のテキスト部分に設定しても反映されません。2番目以降のテキストで使用する必要があります。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  add.tspan('Lorem ipsum dolor sit amet, ');
  add.tspan('consectetur adipiscing elit.').fill('#0af').dx(100);
});
text.move(20, 20);

image.png

dyメソッド

dyメソッドはdxメソッドのY方向版です。Y方向に対して座標の調整値を設定できます。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  add.tspan('Lorem ipsum dolor sit amet, ');
  add.tspan('consectetur adipiscing elit.').fill('#0af').dy(30);
});
text.move(20, 20);

image.png

lengthメソッド

TextクラスのようにTspanクラスもlengthメソッドを持っています。該当のTspanの幅のサイズを取ることができます(文字数などではありません)。

改行などの無い基本的なテキストであれば各Tspanのlengthメソッドの返却値の合算値と親となるTextのlengthメソッドの返却値は一致するようです。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  var tspan1 = add.tspan('Lorem ipsum dolor sit amet, ');
  var tspan2 = add.tspan('consectetur adipiscing elit.').fill('#0af');
  console.log('tspan1 length:', tspan1.length());
  console.log('tspan2 length:', tspan2.length());
});
text.move(20, 20);
console.log('text length:', text.length());
"tspan1 length:", 226.8125
"tspan2 length:", 207.171875
"text length:", 433.984375

newLineメソッド

newLineメソッドはTspanクラスの要素に改行を加えます。Textクラスみたく\nとかでは駄目なのか?と思い試してみたのですが、どうやらTspanクラスではテキストに\nなどの改行の指定があっても反映されないようです。

以下のようにテキスト内に\nの改行を入れてみても反映されていません。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  add.tspan('Lorem \nipsum \ndolor \nsit amet, ');
  add.tspan('consectetur adipiscing elit.').fill('#0af');
});
text.move(20, 20);

image.png

代わりに以下のようにnewLineメソッドを追加すると改行が追加されます。ちなみにテキストの最後に改行が付くのではなく、対象のTspan要素の配置位置の直前で改行が加わる形となります(メソッド呼び出し位置的に初見の時に末尾に改行が加わるのか・・・と思いましたがそうではないようです)。先頭のTspan要素でnewLineの呼び出しを行っても表示は変わりません。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  add.tspan('Lorem ipsum dolor sit amet, ');
  add.tspan('consectetur adipiscing elit.').newLine().fill('#0af');
});
text.move(20, 20);

image.png

clearメソッド

clearメソッドはTextクラスと同様に対象のTspan要素のリセットを行います。

以下のコードでは2つのTspanインスタンスを生成していますが、先頭の方のTspanではclearメソッドでリセットを行っているため2つ目の水色のテキストのみが残ります。最初のテキストが消えた分の位置の調整なども実行されるようです。

var draw = SVG().addTo('body').size(600, 600);

var text = draw.text(function(add) {
  var tspan1 = add.tspan('Lorem ipsum dolor sit amet, ');
  var tspan2 = add.tspan('consectetur adipiscing elit.').fill('#0af');
  tspan1.clear();
});
text.move(20, 20);

参考文献・参考サイトまとめ

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?