SVGでレイティングに使用するスター(星形)を実装するテクニックを解説

Webページやスマホアプリで見かけるレイティングに使用するスター(星形)を実装するSVGのテクニックを紹介します。

一口にスターといってもさまざまな状態があり、オン・オフ、半分、アウトライン、サイズ変更など、さまざまな実装テクニックが解説されています。

スター(星形)を実装するSVGのテクニック

Star Rating: An SVG Solution
by Ahmad Shadeed

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

はじめに

ユーザーにコンテンツやレビューを提供するWebサイトやプラットフォームでは、星(スター)による評価を提供することが重要です。私は最近、プロジェクトで星評価(スターレーティング)のコンポーネントを実装する必要がありました。
要件は下記の通りです。

  • パフォーマンス(画像は含まれません)
  • サイズ変更可能
  • アクセシブル
  • 部分的な評価(3.5や3.2など)を動的に表示
  • CSSでメンテナンスが簡単

スターをSVGで実装したところ、期待通りに機能しました。この記事では、星評価(スターレーティング)のコンポーネントを実装する方法、さまざまなシナリオでどのように機能するかについて解説します。

もしSVG以外の解決策を探しているのであれば、CSS Tricksの記事を読むことをお勧めします。

実装の要件

本題に入る前にコンテキストを整理して、要件と考慮しなければならないすべてのケースをお見せしたいと思います。

実装の要件

実装の要件

今回の要件は、塗りつぶしやストロークの変更、サイズの変更、ハーフスターの表示など、カスタマイズ可能な星を作ることに重点を置きます。

それでは、始めましょう!

スターを実装する基本のHTML

まず、ブラウザで使用できるように、スターの形を選択してSVGとして保存します。

このHTMLで、ブラウザに幅と高さのサイズが32pxのブラックのスターが表示されます。いい感じですね。

アクセシビリティ

スクリーンリーダーを使用するユーザーがこの情報にアクセスできるように、aria-label属性に評価に関する情報を含めます。

SVGを再利用する方法

スターは5個必要なので、上記のコードを5回コピーして使用することもできますが、こここではパスデータを抽出して保存しコードを重複させずに再利用します。それでは実際にやってみましょう。

まず、幅と高さが0のSVGを作成します。これはスペースを確保しないためです。

SVG内で、パスのデータを<symbol>要素内に含める必要があります。
MDNによると、

symbol要素は、<use>要素によってインスタンス化されるグラフィカルなテンプレートのオブジェクトを定義するために使用されます。

<symbol>要素内にあるのは、アイコンと同じコンテンツです。また、後でそのシンボルを参照できるようにidを加えておくことも重要です。

これで、<use>要素を使ってスターのシンボルを再利用できるようになりました。考え方としては、href属性の値としてidを使う必要があるということです。

スターのスタイル

5個のスターを実装できたので、CSSの部分に入りましょう。

スターのカラーにはイエローとグレーを定義しました。

上記のHTMLとCSSで、下記のように表示されます。

スターのスタイル

スターにカラーを定義

部分的なスターを実装する

.5などの評価に使用する部分的なスターを実装するには、ありがたいことにSVGでは2つの優れたソリューションがあります。1つ目は<mask>を使用、2つ目はSVGグラデーションを使用します。

1. SVGのmaskを使用した実装

<mask>を使用する目的は、スターの一部を消して、残りを半透明のカラーでペイントする効果をエミュレートすることです。そのためには、SVGの<mask>の力を借りなければなりません。

SVGのmaskを使用した実装方法

<mask>でスターの一部を消して、残りを半透明のカラーでペイント

上の図では、スター形と矩形があります。必要なのはそれらの交点で、交点によりスターを半分にします。

仕組みが分かったので、実装コードを見てましょう。

  1. 再利用可能なSVGのテンプレートを作成する。
  2. x=50%に配置された矩形の<mask>要素を追加する。
  3. スター形にマスクを適用する。

結果は前述のように、スターが半分になります。

あとは、マスクされているときに半透明のスターを表示するにはどうすればよいかということです。SVGのおかげで<mask>の中に複数の要素を含めることができます。

別の要素を含めると、SVGの<mask>は下記のようになります。

マスクは、白い要素が見せたいもの、黒い要素が隠したいものを表します。これを組み合わせることで、カットアウトの効果を生み出すことができます。
参考: 画像の一部を切り取るカットアウトを実装するCSSとSVGのテクニック

マスクの各要素を視覚的に説明した図をご覧ください。

マスクの各要素を視覚的に説明

白い矩形と黒い矩形に注目

白い矩形は0,0に配置され、黒の矩形は50,0に配置されていることに注目してください。視覚的には下記のようになります。

マスクの各要素を視覚的に説明

斜線の部分が表示される

何が起きているか分かりますか? 斜線の部分は、最終的にスターを半分にします。ここでもうひとつの半透明のスターを追加して、よりはっきりさせることができないかと考えているかもしれません。

ピュアブラックではなく明るい色を使用することで、半透明の効果が得られます。つまり、現在隠されている部分には、スターの色の明るい色合いになります。

マスクの各要素を視覚的に説明

明るい色を使用すると、半透明の効果が得られる

SVGのマークアップの完全版は下記のとおりです。

これで、部分的に塗りつぶされたスターが実装できました。このソリューションの素晴らしいところは、2つの色合いを用意する必要がないことです。マスクがその役割を果たしてくれます。

SVGのmaskを使用した実装方法

デモページ

2. SVGグラデーションを使用した実装

それでは、2つ目の実装方法を解説します。
これはStackoverflowでの回答にインスパイアされました。

マスクと同様に、<defs>要素にグラデーションを定義する必要があります。

カラーストップが2つあることに注目してください。1つ目のストップは前半を、2つ目のストップは明るい色合いを表しています。このソリューションでは、2つの色を手動で用意する必要があります。

マスクの各要素を視覚的に説明

1つ目は前半、2つ目は明るい色合いに

グラデーションの使い方は次のとおりです。

デモページ

アウトラインスタイルのスターを実装する

アウトラインのスターも含めるようにカスタマイズできるバリエーションが必要です。一見、簡単そうに見えますね。では、実装方法を解説します。

アウトラインのスター

アウトラインのスター

1. SVGのmaskを使用した実装

アウトラインのストロークを追加するには、SVG要素にstrokeを追加するだけです。これは、スターの完全形ではうまくいきます。しかし、部分的なスターでは、マスクのためにカットされてしまいます。

SVGのmaskを使用した実装

部分的なスターにもアウトラインのストロークを適用させたい

これを実現するには、アウトライン用に別のスター形を用意する必要があります。そのためには、<use>要素を複製して、マスクを除去します。

<use>要素が2つあることに注目してください。マスクを使用したものとストロークのみのものです。これが、SVGのmaskを使用した実装です。

デモページ

2. SVGグラデーションを使用した実装

グラデーションの場合は、マスクがないため、アイコンを複製する必要はありません。SVG要素にstrokeを追加するだけで完了です。

デモページ

スターのサイズ変更

SVGにviewBox属性を正しく定義していれば、CSSの変数を使用して簡単にサイズを変更できます。

終わりに

この記事があなたのお役に立てれば幸いです。
コメントや提案があれば、@shadeed9までお願いします。

sponsors

top of page

©2021 coliss