SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

XAMLでズルいデザイン~その3・ズルい背景~

ちょっと時間が空きましたが、今回は↓のスライドでズルい背景と紹介されていたものをWPFで作ってみます。
ズルいデザインテクニック2013 + セミフラット version // Speaker Deck

ズルい背景パターン

まずは、参考元のスライドで紹介されていた、以下のサイトのテクスチャを使ってみました。
http://subtlepatterns.com/
こういう、ほんのりとしたテクスチャっていいですね。
WPFの標準のスケルトンコードだと、背景色が真っ白になってしまっているので、
少し色を付けたり、こういうテクスチャを使ったりするだけで、だいぶ雰囲気が変わります。

真っ白な背景

f:id:minami_SC:20140301233959p:plain

白い壁紙風

f:id:minami_SC:20140301234011p:plain

木目の背景

f:id:minami_SC:20140301234018p:plain


で、WEBデザインとかでよく使う、タイル状に画像を並べるのって、XAMLでは微妙に面倒です。
ImageBrushとかのTileModeプロパティで色々と指定できるのですが、元の画像をそのままのサイズでタイル状に並べるには、↓みたいに、画像のサイズをわざわざ書かなければなりません。

        <Grid.Background>
            <ImageBrush ImageSource="Image/retina_wood.png"
                        Stretch="None"
                        TileMode="Tile"
                        Viewport="0,0,512,512"
                        ViewportUnits="Absolute" />
        </Grid.Background>

画像をタイル状に並べるBrushを生成するマークアップ拡張

タイル状に並べるときに、毎回わざわざ画像のサイズを指定するのは面倒なので、マークアップ拡張にしてみました。

    [MarkupExtensionReturnType(typeof(ImageBrush))]
    public class TiledImageBrushExtension : MarkupExtension
    {
        public TiledImageBrushExtension()
        {
            Source = null;
        }

        public TiledImageBrushExtension(ImageSource source)
        {
            Source = source;
        }

        public ImageSource Source { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return new ImageBrush(this.Source){
                                    Stretch = Stretch.None,
                                    TileMode = System.Windows.Media.TileMode.Tile,
                                    ViewportUnits = BrushMappingMode.Absolute,
                                    Viewport = new Rect(0, 0, this.Source.Width, this.Source.Height) };
        }
    }

こういうのを作っておくと、下のように書くだけでタイル状に並べた背景を作ることができます。

    <Grid Background="{local:TiledImageBrush Source=Image/white_wall.png}" />

ぼかした画像の背景

参考リンクのスライドでは触れてませんが、
近年のフラットデザインだと、極端にブラーをかけた画像を背景にすることも多いですよね。

ぼかした画像のBrushを作るマークアップ拡張 - SourceChord
以前作った↑のようなマークアップ拡張を使うとこういう雰囲気が簡単に出せます。
で、コツとしては、画像の上に半透明の白or黒のレイヤーを被せてやると、イイ感じになると思います。
ってことで、前回のマークアップ拡張をちょっと修正して、ぼかした画像の上に半透明のレイヤーを重ねられるようにしました。

BluredImageBrushExtension
    [MarkupExtensionReturnType(typeof(VisualBrush))]
    public class BluredImageBrushExtension : MarkupExtension
    {
        public ImageSource Source { get; set; }
        public Stretch Stretch { get; set; }

        public double BlurRadius { get; set; }
        public double RenderAtScale { get; set; }

        public Color LayerColor { get; set; }


        public BluredImageBrushExtension()
        {
            Source = null;
            Stretch = System.Windows.Media.Stretch.UniformToFill;
            BlurRadius = 100;
            RenderAtScale = 0.05;
            LayerColor = Colors.Transparent;
        }

        public BluredImageBrushExtension(ImageSource source, Stretch stretch, double blurRadius, double renderAtScale, Color layerColor)
        {
            Source = source;
            Stretch = stretch;
            BlurRadius = blurRadius;
            RenderAtScale = renderAtScale;
            LayerColor = layerColor;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            // ぼかしをかけたImageコントロールを作成
            var img = new Image()
            {
                Source = this.Source,
                ClipToBounds = true,
                Effect = new BlurEffect() { Radius = this.BlurRadius }
            };
            // 画像の上に重ねるレイヤーを作成
            var rect = new Rectangle()
            {
                Fill = new SolidColorBrush(LayerColor)
            };

            // BitmapCacheを設定したGridに配置
            var visual = new Grid()
            {
                CacheMode = new BitmapCache(this.RenderAtScale)
            };
            visual.Children.Add(img);
            visual.Children.Add(rect);

            // ↑のGridを使って、VisualBrushを作成
            var brush = new VisualBrush(visual) { Stretch = this.Stretch };

            return brush;
        }
    }

使い方

    <Grid Background="{local:BluredImageBrush Source=Image/sample.jpg,
                                              Stretch=UniformToFill,
                                              BlurRadius=80,
                                              RenderAtScale=0.1,
                                              LayerColor=#88FFFFFF}">

結果はこんな感じ。
f:id:minami_SC:20140301234047j:plain


もうちょっと工夫しないとカッコいい画面にはなりませんが、こういうのを用意しておけばWPFでも気軽にぼかした画像の背景を使えるようになるかと思います。