MoreBeerMorePower

Power Platform中心だけど、ノーコード/ローコード系を書いてます。

Power Apps で SVG を使う

はじめに

Power Appsでアプリを装飾したり、業務っぽくないアプリを作るときに画像を利用したり、HTMLを駆使したり、あるいは図形コントロールを駆使します。 その一環でSVGをどのくらい使えるのか試してみたので簡単にまとめます。

Power Apps でSVGを表示する場合の基本

SVGを表示する」と言っているのはSVGマークアップを使って図形などを描画することを指しています。( すでに完成されたSVGファイルではなく )

例えば最も簡単例として、以下のような円を描く場合を考えます。 f:id:mofumofu_dance:20200922140710p:plain

Power Apps でSVGを描くには、Imageコントロールを使います。そのうえで、ImageコントロールのImageプロパティに以下の式を設定してみてください。

"data:image/svg+xml,"& 
EncodeUrl(
    "<svg viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'>       
        <circle cx='50' cy='50' r='50' fill='black'/>
    </svg>"
)

コントロールいっぱいに黒い円が表示されていると思います。上の式ではSVGを画像として表示させるためにdataUriを利用しています。

SVGのいいところは、"data:image/svg+xml," をつけて後ろにSVGのタグをURLエンコードした形でくっつけると、それがdataUriになることです。PNGJPEGにはない特性ですね。

data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20100%20100%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%20%20%20%20%20%20%20%0D%0A%20%20%20%20%20%20%20%20%3Ccircle%20cx%3D%2750%27%20cy%3D%2750%27%20r%3D%2750%27%20fill%3D%27black%27%2F%3E%0D%0A%20%20%20%20%3C%2Fsvg%3E

これゆえ、上式のようにタグを書いていってEncodeUrlで囲んで、コンテンツタイプをつければ画像として描画されます。

これを踏まえて、以下のセットを基本としてSVGの各種タグを利用していってください。

"data:image/svg+xml,"& 
EncodeUrl(
    "<svg viewBox='0 0 "&Self.Width&" "&Self.Height&"' xmlns='http://www.w3.org/2000/svg'>       
       ここに図形いろいろ
    </svg>"
)

ポイント

SVGviewBox は図形内の座標を定義しています。 固定の値にすると座標やサイズの変換を考えなければいけなくなるので、表示するImageコントロールのサイズと揃えておきましょう。

そのための viewBox='0 0 "&Self.Width&" "&Self.Height&"' です。

また、サンプルなどでは " ダブルクォートがよく使われていると思いますが、Power Appsでは文字列を定義するために " が使われるので、メモ帳などで ' シングルクォートに置換しておきましょう。

いろいろな SVG 要素を試してみた

SVG の標準的なドキュメントというと以下の2つかなと思います。

developer.mozilla.org

developer.mozilla.org

要素と属性のリファレンスですね。以後ではここのサンプルをPower Appsで試してみた例を紹介します。

少しいじらないといけないところもあるので、見比べて、実際アプリで見てみてください。

animate

<animate>タグは図形やSVG全体の各種属性を時間で変化させる働きがあります。

"data:image/svg+xml,"& 
EncodeUrl(
    "<svg viewBox='0 0 "&Self.Width&" "&Self.Height&"' xmlns='http://www.w3.org/2000/svg'>       
        <rect x='50' y='50' width='200' height='200'>
            <animate attributeName='rx' values='0;40;0;100;0' dur='3s' repeatCount='indefinite' />
        </rect>
    </svg>"
)

例えばこの例では、長方形 (<rect>) の角の丸み (rx) を、3秒の間に 0→40→0→100→0と変化させます。

f:id:mofumofu_dance:20200922144457g:plain

または最初の例にあった円の半径も、animateで変化させることができます。

"data:image/svg+xml,"& 
EncodeUrl(
    "<svg viewBox='0 0 "&Self.Width&" "&Self.Height&"' xmlns='http://www.w3.org/2000/svg'>       
        <circle cx='100' cy='200' fill='black'>
            <animate attributeName='r' values='0;100;0;200;0' dur='3s' repeatCount='indefinite' />
        </circle>
    </svg>"
)

それぞれどの属性がanimateできるかは属性レファレンスを見るとわかります。

f:id:mofumofu_dance:20200922145043p:plain

clipPath

画像や図形を決まった形にくりぬくことができます。超便利!

<defs>~</defs> (定義用のブロック) 内でくりぬく形を定義して、図形側では clip-path=url(#ID) の形で適用します。

"data:image/svg+xml," &
EncodeUrl("
<svg viewBox='0 0 "&Self.Width&" "&Self.Height&"' xmlns='http://www.w3.org/2000/svg'>>
<defs>
  <clipPath id='myClip'>
    <circle cx='200' cy='200' r='100' />
  </clipPath>
</defs>
   <rect width='500' height='400' clip-path='url(#myClip)'/>
   <rect x='350' width='500' height='400'/>
</svg>")

f:id:mofumofu_dance:20200922153000p:plain

同様に画像でもclipできます。画像を一部分だけ使いたいときに有効ですね。

f:id:mofumofu_dance:20200922153248p:plain

filter

図形や画像にフィルターをかけることができます。 <defs>~</defs> (定義用のブロック) 内で効果とIDを定義しておいて、図形側では filter=url(#ID) の形で適用します。

"data:image/svg+xml,"& 
EncodeUrl(
"<svg viewBox='0 0 "&Self.Width&" "&Self.Height&"' xmlns='http://www.w3.org/2000/svg'>       
<defs>
    <filter id='blurMe'>
        <feGaussianBlur stdDeviation='5'/>
    </filter>
    <filter id='shadow'>
        <feDropShadow dx='10' dy='10' stdDeviation='5'/>
    </filter>
 </defs>
 
 <circle cx='160' cy='110' r='100' fill='green' />
 <circle cx='370' cy='110' r='100' fill='green' filter='url(#blurMe)' />
 <circle cx='580' cy='110' r='100' fill='green' filter='url(#shadow)' />
</svg>"
)

f:id:mofumofu_dance:20200922150858p:plain

図形だけでなく、画像も対象になります。後述する<image>でこのフィルターを適用すると、アプリの装飾の幅がグッと広がるのではないでしょうか。

f:id:mofumofu_dance:20200922151511p:plain

image

SVG内での画像の利用です。ここは少し癖があって、HTMLのように外部/内部の画像URLを参照できません

f:id:mofumofu_dance:20200922153840p:plain

これを回避するためには画像のdataUri (base64) を利用します。

"data:image/svg+xml,"& 
EncodeUrl(
"<svg viewBox='0 0 "&Self.Width&" "&Self.Height&"' xmlns='http://www.w3.org/2000/svg'> 
  <image href='"&b64&"' height='200' width='200'/>
</svg>"
)

ここでは"b64" という変数に画像のdataUriを格納しています。

f:id:mofumofu_dance:20200922154049p:plain

お、これを使うと・・・

カメラコントロールで撮影した画像もSVGに取り込むことができました!

f:id:mofumofu_dance:20200922154643p:plain

さらに、filterを組み合わせると・・・

f:id:mofumofu_dance:20200922154932p:plain

このように、撮影した画像にその場でエフェクトをかけることができます。

前述のとおり、ここで表示しているのSVGのdataUriなので、これをFlowに渡してバイナリに変換して保存することももちろんできます。

mask

マスクは図形や画像の一部にマスクをかけます。

下図の例では、ハートマークのマスク領域を<defs>~</defs>内で定義していて、これをオレンジの円に適用しています。 f:id:mofumofu_dance:20200922160335p:plain

もっと簡単な例では、四角を薄い黒で塗りつぶして、三角の領域をマスクということもできます。

ここでは効果のわかりやすさのために、塗りつぶしを少し透過させて、マスクの後ろにアイコンを置いています。

f:id:mofumofu_dance:20200922160747p:plain

"data:image/svg+xml," &
EncodeUrl(
"<svg viewBox = '0 0 "&Self.Width&" "&Self.Height&"' xmlns='http://www.w3.org/2000/svg'>
  <defs>
    <mask id='loss'>
      <rect width='100%' height='100%' fill='white'/>
     <polygon points='200,100 0,300 400,300' fill='black' />
    </mask>
 </defs>
  <rect x='0' y='0' width='1024' height='766' mask='url(#loss)' fill-opacity='0.8'/>
</svg>"
)

おわり

このように、SVGの基本的なパターンはおおよそPower Appsで直接利用することができます。

注意するのは画像の取り扱いやviewBoxの大きさでしょうか。

今回のSVGの手法を応用すると以下のようなお楽しみアプリを作ることもできます。 ぜひ挑戦してみてください。

なお、今回紹介したサンプルをダウンロードいただけるようにGithubに置きました。ご活用ください。(写真は自分で撮ったものなので適当に二次配布・利用いただいて問題ありません)

github.com