【SVGフィルタ講座③】feMorphologyを使ってテキストを縁取りする/中抜きする

bird-GIF-svg
DESIGNER

SVGフィルタシリーズ第1回では、SVGフィルタの作り方・使い方などの基本について、第2回では<feMorphology>を使って画像のピクセル変形について学びました。

第3回の本記事では、<feMorphology>を使ってテキストを縁取りする方法をご紹介します。第2回の応用編(テキスト編)です。

<feMorphology>を使ってテキストを縁取りする

stroke属性を使って、SVGでテキストを縁取ることができます。

<!-- strokeを使ってSVGのテキストを縁取る -->
<text font-size="80px" dx="100" dy="200" font-weight="700" stroke="deepPink" stroke-width="3px">Stroked Text</text>

stroke属性を加えると、ストロークはテキストオブジェクトの中央にくるため、その幅の半分がテキスト自体と重複し、テキストの幅が小さくなってしまいます。なお、この現象は起こって欲しくない時にも起こってしまいます。そのため縁取りするテキストの幅が小さくなる代わりに、テキストを膨張(または縮小)させて縁またはストロークの厚みをテキスト加える必要があります。そこで<feMorphology>の出番です。

スタイル指定がない限り、テキストは単一色で表示されます。そのため<feMorphology>がテキストに適用されたばあい、テキストは縮小または膨張します。<feMorphology>を使ってテキストの幅を太くしたら、そのテキストはその他のフィルタプリミティブへのインプットとして使用可能です。それにより、思いどおりにテキストを縁取りできるようになります。

まずは詳しく解説する前に、ストロークで縁取りしたテキストと、<feMorphology>を使って縁取りしたしたテキストを見比べてみましょう。

▲上部のテキスト:オリジナルのもの 中央のテキスト:Stroke属性で縁取りされたもの 下部のテキスト:<feMorphology>を使って膨張させたもの

では、実際にテキストを色付きで縁取りしてみましょう。

今回は以下のテキストを縁取りしていきたいと思います。

以下の画像のような仕上がりを目標に、ステップごとに解説していきます。

まずはテキストを含むSVGと、膨張操作を行うフィルタから始めましょう。

テキストが膨張する量は、設定する縁の幅によって変わります。

<svg width="900" height="200" viewBox="100 0 900 200">
<filter id="outline">
<feMorphology in="SourceAlpha" result="DILATED" operator="dilate" radius="4"></feMorphology>
</filter>
<!-- 膨張したテキスト -->
<text font-size="85px" dx="125" dy="130" font-weight="700" filter="url(#outline)">upgrade yourself</text>
</svg>

上記のコードは、テキストのアルファチャネル(黒色のテキスト)を取得し、幅を4px太くするものです。

この時点で、テキストは以下のような見た目になります。ネイビーブルーのオリジナルテキストと比べると、違いは一目瞭然ですね。

縁取り効果を出すため、膨張したテキストの上に元のテキストを重ねます。そうすることで膨張したテキストの縁(4px大きくした分)のみが元のテキストの背後から見えることになり、縁取りされているように見えるのです。<feMerge>を使い、縁(膨張したテキスト)の上にテキストを重ねましょう。(<feMerge>については第1回の記事で取り上げました)

しかしその前にやっておきたいのが「縁の色付け」です。フィルタ領域を任意の色で塗りつぶし、inオペレータを使って色レイヤーと膨張したテキストレイヤー(縁となる部分)を統合しましょう。結果として、膨張したテキストレイヤーと重なる色レイヤーのみがレンダリングされ、それによりテキストが着色されます。最後に、膨張したテキストレイヤーをオリジナルテキストと合わせると、意図した仕上がりが完成します。以下はサンプルコードです。

<svg width="900" height="200" viewBox="100 0 900 200">
<filter id="outline">
<feMorphology in="SourceAlpha" result="DILATED" operator="dilate" radius="4"></feMorphology>
<feFlood flood-color="#32DFEC" flood-opacity="1" result="PINK"></feFlood>
<feComposite in="PINK" in2="DILATED" operator="in" result="OUTLINE"></feComposite><feMerge>
<feMergeNode in="OUTLINE" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
<!-- 膨張したテキスト -->
<text font-size="85px" dx="125" dy="130" font-weight="700" filter="url(#outline)">upgrade yourself</text>
</svg>

これにて完成です。

なおオリジナルテキストの塗りつぶし色は、CSSまたはfill属性を使ったtext要素で指定できます。縁の色は<feFlood>プリミティブのflood-color属性で指定しましょう。

SVGでのフィルタ効果作成に必要なことは、以下の3つです。ぜひ意識してみてください。

  • 小さな操作の視点から最終的なアウトプットを考えること
  • ひとつの操作の結果を他の操作のインプットに使うこと
  • 用意したレイヤーを合わせて最終的な結果を創り上げること

<feMorphology>を使ってテキストを中抜きする

テキストを縁取りするだけでなく、縁のみ(中抜き)のテキストも作成できます。

テキストの内部がくり抜かれており、縁から背景が透けて見えるテキストです。以下のGIF画像の例のように、背景色が変わるのがテキスト越しに確認できます。このセクションでは、このようなテキストを作成してみましょう。

この効果は、縁取りテキストよりも簡単に作成できます。縁取りテキストではオリジナルテキストを膨張したテキストの上に重ねましたが、中抜きテキストではオリジナルテキストを膨張させたものを生成し、その中身をくり抜く手法をとります。つまり膨張したテキストに追加した分の幅だけを残すのです。

まずはオリジナルテキスト前面に、膨張したテキストを背面に配置し、統合します。その際にout統合オペレータを使うことで、元のテキストと被らない背景部分だけ、つまりは縁のみがレンダリングされます。

<svg width="900" height="450" viewBox="0 0 900 450">
<filter id="outliner">
<!-- まずはテキストのアルファチャンネルを取得し、膨張させる -->
<feMorphology operator="dilate" radius="8" in="SourceAlpha" result="THICKNESS" />
<!-- 次に、元のテキスト(SourceGraphic)を取得し、膨張したテキストの中身を切り抜くのに使用する -->
<feComposite operator="out" in="THICKNESS" in2="SourceGraphic"></feComposite>
</filter><text dx="100" dy="300" filter="url(#outliner)" letter-spacing="10px">SVG Rocks</text>
</svg>

以下がこのコードのデモです。今回はポップなフォントを使ってみました。

おしゃれな中抜きテキストができましたね! では、縁の色を変えたいときはどうすれば良いのでしょうか?

縁の色を変えるには、<feFlood>プリミティブを再度使って塗りつぶし色と縁を統合する方法があります。縁の色を変えるには毎回これを行う必要がありますが、正直とても退屈な作業ですよね……。でも安心してください。実はもっと簡単な方法があります。

テキストのアルファチャンネル(黒色のテキスト)を取得して膨張させる代わりに、オリジナルテキスト自体(あらゆる色が可能)を取得して膨張させるのです。そしてオリジナルテキストを再利用し、膨張したテキストの中身を切り抜きます。こうすることで、オリジナルテキスト自体を使った縁ができます。またCSSでオリジナルテキストの色を定義できるため、自身のスタイルとは別の縁のテキストを作成可能です(関心の分離が実践できるのです!)。またそのフィルタはどのテキストにも適用でき、そのテキストの色はフィルタのコードをいじることなく、いつでもCSSで変えられます。

こうして改善されたコードが、以下のとおりです。

<svg width="900" height="450" viewBox="0 0 900 450">
<filter id="outliner">
<!-- まずはsource graphic(テキスト)を取得し、膨張させる -->
<feMorphology operator="dilate" radius="8" in="SourceGraphic" result="THICKNESS" />
<!-- 次に、そのテキスト(SourceGraphic)を再利用し、膨張したテキストの中身を切り抜くのに使用する -->
<feComposite operator="out" in="THICKNESS" in2="SourceGraphic"></feComposite>
</filter>
<text dx="100" dy="300" filter="url(#outliner)" letter-spacing="10px">SVG Rocks</text>
</svg>

このスタイルシートでは、縁の色とSVGの背景色が選べます。また、SVGの中のテキストの後ろに画像の配置もできます。

以下のコードでは、背景色を変えてかっこよく見せるために、CSSアニメーションを使用しています。


svg text {
font-family: 'Bangers', cursive;
font-size: 150px;
letter-spacing: 13px;
fill: #000; /* この塗りつぶし色が縁の色を決定する */
}
svg {
background-color: gold;
animation: colorsssss 2s linear infinite;
animation-delay: 3s;
}
@keyframes colorsssss {
50% {
background-color: deepPink;
}
}

上記のSVGフィルタはSVGのほか、HTMLでも使用できます。

HTML要素に適用するには、filterプロパティを使ってHTMLでフィルタを設置し、CSSで「呼び出す」だけです。


h2 {
filter: url(#outliner);
/* 見出しの色を変えることで縁の色が変えられます。 */
color: deepPink;
}

こちらでは、フィルタが適用されたHTMLの見出しを含んだ完成版デモを確認できます)

私がこのフィルタを気に入っているのは、あくまで視覚的な補助として活用できるところです。

仮にブラウザがSVGフィルタやCSSフィルタをサポートしていないばあい、またはSVGフィルタのHTML要素への適用をサポートしていないばあいでも、縁取りや中抜き効果が適用されていないオリジナルテキストがユーザーに表示されます。さらに、SVGとHTMLテキストはどちらも完全にアクセス・検索・選択が可能です。

SVGは、プログレッシブエンハンスメントの理念が反映されているのです。

まとめ

SVGでわずか2つのフィルタ操作を行うことで、SVGまたはHTMLのテキストコンテンツに縁取り効果を与えられます。

このフィルタをHTMLに配置し、あとは必要に応じて再利用してみてください!

(原文:Sara Soueidan 翻訳:Yui Tamura 編集:Workship MAGAZINE編集部)

SHARE

  • 広告主募集
  • ライター・編集者募集
  • WorkshipSPACE
デザイナー副業案件
Workship