XAMLでズルいデザイン~その4・ズルいグラデーション・配色~
今度はグラデーションと配色についてです。
ズルいグラデーション
ズルいグラデーションと説明されている、うっすらとしたグラデーションを作成するマークアップ拡張を作りました。
コードは以下の通り。
[MarkupExtensionReturnType(typeof(LinearGradientBrush))] public class ZuruiGradientBrushExtension : MarkupExtension { public ZuruiGradientBrushExtension() : this(Colors.Transparent, 0.95f, 90) { } public ZuruiGradientBrushExtension(Color baseColor, float diff, double angle) { BaseColor = baseColor; Diff = diff; Angle = angle; } public Color BaseColor { get; set; } public float Diff { get; set; } public double Angle { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { var grad = BaseColor.ToHSV(); grad.V *= Diff; return new LinearGradientBrush(BaseColor, grad.ToRGB(), Angle); } }
グラデーションを作るときに、基準色から明度を変化させた色を作成します。
その際に、RGBではなく、HSVで色を扱いたかったので、以前↓の記事で書いたHSVColorクラスを使っています。
RGB⇔HSVの変換をするクラス - SourceChord
使い方
プロパティ | 説明 |
---|---|
BaseColor | グラデーションの基準となる色 |
Diff | グラデーションで明るさを変化させる量 |
Angle | グラデーションの角度 |
↓こんな風にグラデーションを作れます。
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Rectangle Width="100" Height="50" Fill="{local:ZuruiGradientBrush BaseColor=Red, Diff=0.8}" /> <Rectangle Grid.Column="1" Width="100" Height="50" Fill="{local:ZuruiGradientBrush BaseColor=DarkBlue, Diff=1.8}" /> </Grid>
ズルい配色
色相を変化させた色を設定するマークアップ拡張を作ってみました。
[MarkupExtensionReturnType(typeof(Color))] public class AdjustHueExtension : MarkupExtension { public AdjustHueExtension() : this(Colors.Transparent, 0) { } public AdjustHueExtension(Color baseColor, float hueDiff) { BaseColor = baseColor; HueDiff = hueDiff; } public Color BaseColor { get; set; } public float HueDiff { get; set; } public override object ProvideValue(IServiceProvider serviceProvider) { var adjust = BaseColor.ToHSV(); adjust.H += HueDiff; return adjust.ToRGB(); } }
このマークアップ拡張を使うと、以下のように指定した色から指定した分だけ色相を変化させた色を作成できます。
使い方
プロパティ | 説明 |
---|---|
BaseColor | 基準となる色 |
HueDiff | 色相を変化させる量 |
<Window.Resources> <SolidColorBrush x:Key="MainColorBrush" Color="Red" /> <SolidColorBrush x:Key="AccentColorBrush" Color="{local:AdjustHue BaseColor=Red, HueDiff=200}" /> </Window.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Rectangle Width="100" Height="50" Fill="{StaticResource MainColorBrush}" /> <Rectangle Grid.Column="1" Width="100" Height="50" Fill="{StaticResource AccentColorBrush}" /> </Grid>
配色とグラデーションを組み合わせて使う
この二つを組み合わせて、以下のようなことをしようとすると問題にブチ当たります。。。
Resourceに定義したColorを使って、自作のマークアップ拡張でグラデーションを作ると以下のようなエラーが出ます。
<Window.Resources> <Color x:Key="MainColor">#FFC13B23</Color> <SolidColorBrush x:Key="MainColorBrush" Color="{StaticResource MainColor}" /> <SolidColorBrush x:Key="AccentColorBrush" Color="{local:AdjustHue BaseColor={StaticResource MainColor}, HueDiff=200}" /> </Window.Resources>
Markup Extension の解析時に、型 'MS.Internal.Markup.MarkupExtensionParser+UnknownMarkupExtension' に対する不明なプロパティ 'BaseColor' が見つかりました。
IDEのデザイナ画面は正しく表示されるのに、ビルドができない。。。
で、色々調べてたら、以下の記事を見つけました。
【WPF】自作したマークアップからプロパティへアクセスできない。 | 創造的プログラミングと粘土細工
どうやら、マークアップ拡張を別アセンブリで定義すればよいらしい。
てことで、自分で作ったマークアップ拡張内で、StaticResourceとかを使いたい場合は、マークアップ拡張を、別Dllのクラスライブラリなどといった形で定義しておく必要があるようです。
使ってみた
今回作ったマークアップ拡張とかを使って、適当に画面を作ってみました。
<Window x:Class="WpfBaseTemplate1.Window4" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:zurui="clr-namespace:ZuruiDesign;assembly=ZuruiDesign" Title="Window4" Width="600" Height="400" Background="{zurui:TiledImageBrush Source=Image/retina_wood.png}"> <Window.Resources> <Color x:Key="MainColor">#FFC13B23</Color> <Color x:Key="AccentColor">#FF2274C1</Color> <Color x:Key="BaseColor">#FFFFFFFF</Color> <Color x:Key="TextColor">#FF222222</Color> <SolidColorBrush x:Key="MainColorBrush" Color="{StaticResource MainColor}" /> <SolidColorBrush x:Key="TextColorBrush" Color="{StaticResource TextColor}" /> <Style x:Key="ZuruiBlackTextBlockStyle1" TargetType="{x:Type TextBlock}"> <Setter Property="Foreground" Value="#FF000000" /> <Setter Property="Effect"> <Setter.Value> <DropShadowEffect BlurRadius="0" ShadowDepth="1" Color="#FFFFFFFF" /> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Rectangle Fill="{zurui:ZuruiGradientBrush BaseColor={StaticResource MainColor}, Diff=0.9}" /> <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="46" Foreground="{StaticResource MainColorBrush}" Style="{StaticResource ZuruiBlackTextBlockStyle1}" Text="TextBlock" TextWrapping="Wrap" /> <Button Grid.Column="1" Width="80" Height="30" Margin="20" HorizontalAlignment="Right" VerticalAlignment="Center" Background="{zurui:ZuruiGradientBrush BaseColor={StaticResource AccentColor}, Diff=0.9}" Content="Button" Foreground="White" /> </Grid> <Rectangle Grid.Row="2" Fill="{zurui:ZuruiGradientBrush BaseColor={StaticResource BaseColor}, Angle=90}" /> <TextBlock Grid.Row="2" Margin="20" Foreground="{StaticResource TextColorBrush}" TextAlignment="Right" TextWrapping="Wrap"> ズルいデザイン <LineBreak /> abccefg <LineBreak /> 123 <LineBreak /> </TextBlock> </Grid> </Window>
以上のようなマークアップ拡張を作ってみましたが、マークアップ拡張だと、リソースとしてBrushやColorを作るのに向かないですね。
で、こういうテーマカラーとなる配色や、グラデーションとかはリソースに定義して使いまわすことが多いと思うので、わざわざマークアップ拡張で作るようなものではなかったかも。。。