はじめに
先週YouTuberの記事を書きましたが、その中で紹介したJavier Suárezさんが作ったFigmaのデザインをそのまま.NET MAUIに持ってくるツールを使ってみたので、その紹介をします。
他の記事で導入方法については書いていますので、ここではインストール後からお話できればと思います。
Figma Design to .NET MAUI
さて、ここからが本題になります。
まず、インストールしたFigma.Maui.Graphics.Sampleを開きます。
ここに赤の線のところにコピーしたFigmaのアクセストークンを貼り付けます。
そして黄色いところにはデザインを持っていきたいFigmaFileのURLのFileID部分をコピペします。
「Generate」を押すとC#のコードが作成されるので「Export」して保存してください。
.NET MAUIで実装
新規作成をして生成したコードを表示するGraphicsViewを作成します。
MAUIのテンプレートを新規作成して「MainPage.xaml」を以下のように書き換えます。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FigmaApps.MainPage">
<ScrollView>
<GraphicsView //GraphicsViewの追加
x:Name="figmaSample"/>
</ScrollView>
</ContentPage>
そして「MainPage.xaml.cs」は以下のように書き換えます。
namespace FigmaApps;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
figmaSample.Drawable = new Drawable();//x:Nameと名前をあわせること
}
class Drawable:IDrawable //IDrawblewを継承したDrawbleクラスを実装
{
public void Draw(ICanvas canvas, RectF dirtyRect)
{
//ここに生成したコードをコピペする ここに書いてあるコードをどう編集していいかはさすがにわかってると思うので割愛
/////////////////////////////////////////////////////////////////////////////////
// View: rectangleView
// NodeName: Rectangle 1
// NodeType: RECTANGLE
// NodeId: 1:4
canvas.SaveState();
canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(234, 234, 234, 255)), new PaintGradientStop(1, new Color(234, 234, 234, 130)), } }, new RectF(0f, 0f, 350f, 500f));
canvas.FillRoundedRectangle(0f, 0f, 350f, 500f, 10f);
canvas.StrokeColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.StrokeSize = 1;
canvas.DrawRoundedRectangle(0f, 0f, 350f, 500f, 10f);
canvas.RestoreState();
// View: rectangleView1
// NodeName: Rectangle 2
// NodeType: RECTANGLE
// NodeId: 1:5
canvas.SaveState();
canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(43, 151, 212, 41)), } }, new RectF(0f, 430f, 350f, 5f));
canvas.FillRoundedRectangle(0f, 430f, 350f, 5f, 0f);
canvas.RestoreState();
// View: rectangleView2
// NodeName: Rectangle 3
// NodeType: RECTANGLE
// NodeId: 1:7
canvas.SaveState();
canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(81, 43, 212, 89)), } }, new RectF(14f, 446f, 325f, 41f));
canvas.FillRoundedRectangle(14f, 446f, 325f, 41f, 20f);
canvas.RestoreState();
// View: elipseView
// NodeName: Ellipse 1
// NodeType: ELLIPSE
// NodeId: 1:8
canvas.SaveState();
canvas.SetFillPaint(new LinearGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(43, 151, 212, 41)), } }, new RectF(19f, 28f, 116f, 116f));
canvas.StrokeSize = 5;
canvas.DrawEllipse(19f, 28f, 116f, 116f);
canvas.RestoreState();
// View: textView
// NodeName: Name
// NodeType: TEXT
// NodeId: 1:9
canvas.SaveState();
canvas.FontColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
canvas.FontSize = 16f;
canvas.DrawString(@"Name", 175f, 28f, 63f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.RestoreState();
// View: rectangleView3
// NodeName: Rectangle 4
// NodeType: RECTANGLE
// NodeId: 1:10
canvas.SaveState();
canvas.SetFillPaint(new RadialGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(81, 43, 212, 255)), new PaintGradientStop(1, new Color(139, 117, 214, 255)), new PaintGradientStop(1, new Color(217, 217, 217, 255)), } }, new RectF(30f, 200f, 50f, 50f));
canvas.FillRoundedRectangle(30f, 200f, 50f, 50f, 10f);
canvas.RestoreState();
// View: rectangleView4
// NodeName: Rectangle 5
// NodeType: RECTANGLE
// NodeId: 1:11
canvas.SaveState();
canvas.SetFillPaint(new RadialGradientPaint { GradientStops = new PaintGradientStop[] { new PaintGradientStop(0, new Color(43, 151, 212, 255)), new PaintGradientStop(1, new Color(43, 151, 212, 0)), } }, new RectF(30f, 270f, 50f, 50f));
canvas.FillRoundedRectangle(30f, 270f, 50f, 50f, 10f);
canvas.RestoreState();
// View: rectangleView5
// NodeName: Rectangle 6
// NodeType: RECTANGLE
// NodeId: 1:12
canvas.SaveState();
canvas.FillColor = Color.FromRgb(163, 242, 143);
canvas.Alpha = 1;
canvas.FillRoundedRectangle(30f, 340f, 50f, 50f, 10f);
canvas.RestoreState();
// View: imageView
// NodeName: Vector 1
// NodeType: VECTOR
// NodeId: 1:16
// View: textView1
// NodeName: MAUI
// NodeType: TEXT
// NodeId: 1:17
canvas.SaveState();
canvas.FontColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
canvas.FontSize = 16f;
canvas.DrawString(@"MAUI", 88f, 184f, 47f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.RestoreState();
// View: textView2
// NodeName: .Net MAUI High School
// NodeType: TEXT
// NodeId: 1:22
canvas.SaveState();
canvas.FontColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.Font = new Microsoft.Maui.Graphics.Font("Rakkas-Regular", 400, FontStyleType.Normal);
canvas.FontSize = 16f;
canvas.DrawString(@".Net MAUI High School", 96f, 213f, 153f, 24f, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.RestoreState();
// View: textView3
// NodeName: TwitterAccount
// NodeType: TEXT
// NodeId: 1:24
canvas.SaveState();
canvas.FontColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.Font = new Microsoft.Maui.Graphics.Font("Rakkas-Regular", 400, FontStyleType.Normal);
canvas.FontSize = 16f;
canvas.DrawString(@"TwitterAccount", 96f, 289f, 103f, 24f, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.RestoreState();
// View: textView4
// NodeName: QiitaAccount
// NodeType: TEXT
// NodeId: 1:25
canvas.SaveState();
canvas.FontColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.Font = new Microsoft.Maui.Graphics.Font("Rakkas-Regular", 400, FontStyleType.Normal);
canvas.FontSize = 16f;
canvas.DrawString(@"QiitaAccount", 96f, 358f, 87f, 24f, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.RestoreState();
// View: textView5
// NodeName: Twitter
// NodeType: TEXT
// NodeId: 1:18
canvas.SaveState();
canvas.FontColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
canvas.FontSize = 16f;
canvas.DrawString(@"Twitter", 88f, 254f, 64f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.RestoreState();
// View: textView6
// NodeName: Qiita
// NodeType: TEXT
// NodeId: 1:20
canvas.SaveState();
canvas.FontColor = Color.FromRgb(0, 0, 0);
canvas.Alpha = 1;
canvas.Font = new Microsoft.Maui.Graphics.Font("Shrikhand-Regular", 400, FontStyleType.Normal);
canvas.FontSize = 16f;
canvas.DrawString(@"Qiita", 88f, 324f, 41f, 23f, HorizontalAlignment.Left, VerticalAlignment.Top);
canvas.RestoreState();
}
}
}
これで完了になります。
Visual StudioはIDEでありTeacherです。
影がないなと思ったらつければいいのです。
shadowをつけようと思ったら勝手にSetShadowが出てきてその引数が何のかさえ教えてくれます。
こんな感じでVisual Studioをうまく使っていきましょう。先生最高!!
不具合など
見たらわかると思いますが、変換がうまくいってない箇所が多少見受けられます。
それらの理由や対処法などご紹介できればと思います。
・Elipeseのグラデーションができない。→ソフト的には未対応。しかしコードを書き替えることによって対応は可能
・ドロップシャドウがついてない→ソフト的には未対応。しかしコードを付け足すことによって対応は可能(canvas.SetShadow())
・パスが描かれない→ソフト的に未対応詳細はこちら(https://github.com/jsuarezruiz/figma-to-maui-graphics#known-limitations-or-issues)
・不具合ではないですがコンポーネントのX,Yの値を0にそろえていないとうまく変換されないようです。↑参照
・フォントが変わっていない→.NET MAUIプロジェクトに対応するフォントを入れ込めば反映可能
・3つボタンの上2つがうまく変換できていない→下の図のように決められたサイズの枠からはみ出してコンポーネントを作ったための不具合。きちんとルールにのっとれば可能
さいごに
以上がFigmaのデザインを.NET MAUIへ持ってくる方法の紹介となりました。
多少の不具合はありますがこんなに簡単にFigmaで作ったデザインをモバイルアプリのUIを構築できる方法は今のところないと思います。
(あっても多少のお金がかかったり、操作が大変であったり)
今回私が自作したデザインで試しましたが、ほかのFigmaユーザーが作成したデザインであってもコピーを取得し、URLさえ入手できればどのものでも生成が可能です。
UIコンポーネントくらいならかなり良い感じで爆速で生成ができますね。