zoukankan      html  css  js  c++  java
  • [UWP]通过自定义XamlCompositionBrushBase实现图片平铺

    1. 什么是XamlCompositionBrushBase

    我早就想试试自定义XamlCompositionBrushBase,但一直没机会。上一篇文章介绍到使用Win2D的BorderEffect实现图片的平铺功能,原理很简单,但每次都要写这些代码很繁琐,正好就用这个作为例子试试XamlCompositionBrushBase。

    CompositionBrush灵活多变,它的基本用法如下:

    1. 通过Compositor创建CompositionBrush;
    2. 配置CompositionBrush;
    3. 创建SpriteVisual并将它的Brush设置为CompositionBrush;
    4. 使用ElementCompositionPreview.SetElementChildVisual 将SpriteVisual设置到某个UIElement的可视化层里。

    这些步骤很繁琐,而且不能用在XAML中。XamlCompositionBrushBase提供了将CompositionBrush用在XAML中一个桥梁,他继承自Brush类,可以直接像普通的XAML 画笔(如SolidColorBrush)那样直接用在XAML中。

    如上图所示,Windows Community Toolkit中已经提了很不少XamlCompositionBrushBase的实现,它们的使用方式已经有很多文章介绍,这里不一一列举。

    2. 自定义XamlCompositionBrushBase

    这篇文章将介绍一个自定义的画笔:TiledImageBrush,它的主要目标是实现ImageBrush没有的图片平铺功能,并且它可以在XAML中使用,使用方式如下:

    <Rectangle IsHitTestVisible="False">
        <Rectangle.Fill>
            <controls:TiledImageBrush Source="ms-appx:///Assets/flutter.png"/>
        </Rectangle.Fill>
    </Rectangle>
    

    顺便复习下普通的ImageBrush的用法:

    <Rectangle >
        <Rectangle.Fill>
            <ImageBrush ImageSource="ms-appx:///Assets/flutter.png"/>
        </Rectangle.Fill>
    </Rectangle>
    

    看起来TiledImageBrush的用法是不是和ImageBrush很像?接下来讲解TiledImageBrush的实现步骤。TiledImageBrush继承自XamlCompositionBrushBase,而实现XamlCompositionBrushBase的一般步骤如下:

    protected override void OnConnected()
    {
        // Delay creating composition resources until they're required.
        if (CompositionBrush == null)
        {
             CompositionBrush = CreateCompositionBrush();//Create A CompositionBrush.
        }
    }
    
    protected override void OnDisconnected()
    {
        // Dispose of composition resources when no longer in use.
        if (CompositionBrush != null)
        {
            CompositionBrush.Dispose();
            CompositionBrush = null;
        }
    }
    

    首先重写OnConnected,当画笔在屏幕上首次用于绘制元素时会调用这个函数。在这个函数里创建CompositionBrush并赋值给XamlCompositionBrushBase.CompositionBrush

    然后重写OnDisconnected,它在画笔不再用于绘制任何元素时被调用。在这个函数里尽可能地释放各种资源,例如CompositionBrush 。这两步就是实现XamlCompositionBrushBase的基本步骤。

    创建CompositionBrush有很多种玩法,我之前写过两篇文章分别介绍 CompositionBrush入门在CompositionBrush上使用Effect。这里使用使用Win2D的BorderEffect实现图片的平铺功能这篇文章里介绍到的代码,首先使用LoadedImageSurface.StartLoadFromUri创建CompositionSurfaceBrush,然后加入到BorderEffect里实现图片平铺,然后把产生的CompositionEffectBrush赋值给XamlCompositionBrushBase.CompositionBrush

    TiledImageBrush中添加了Source属性用于设置图片Uri(实际上是个ImageSource类型),模仿ImageBrush,这里的Source也是一个ImageSource类型的属性,虽然实际上使用的是它的UriSource。详细代码如下:

    public ImageSource Source
    {
        get => (ImageSource)GetValue(SourceProperty);
        set => SetValue(SourceProperty, value);
    }
    
    private void UpdateSurface()
    {
        if (Source != null && _surfaceBrush != null)
        {
            var uri = (Source as BitmapImage)?.UriSource ?? new Uri("ms-appx:///");
            _surface = LoadedImageSurface.StartLoadFromUri(uri);
            _surfaceBrush.Surface = _surface;
        }
    }
    
    

    OnConnected的详细代码如下:

    protected override void OnConnected()
    {
        base.OnConnected();
    
        if (CompositionBrush == null)
        {
            _surfaceBrush = Compositor.CreateSurfaceBrush();
            _surfaceBrush.Stretch = CompositionStretch.None;
    
            UpdateSurface();
    
            _borderEffect = new BorderEffect()
            {
                Source = new CompositionEffectSourceParameter("source"),
                ExtendX = Microsoft.Graphics.Canvas.CanvasEdgeBehavior.Wrap,
                ExtendY = Microsoft.Graphics.Canvas.CanvasEdgeBehavior.Wrap
            };
    
            _borderEffectFactory = Compositor.CreateEffectFactory(_borderEffect);
            _borderEffectBrush = _borderEffectFactory.CreateBrush();
            _borderEffectBrush.SetSourceParameter("source", _surfaceBrush);
            CompositionBrush = _borderEffectBrush;
        }
    }
    

    这样一个基本的XamlCompositionBrush就完成了,完整的代码可以在这里查看:

    OnePomodoro_TiledImageBrush.cs at master

    3. 参考

    XamlCompositionBrushBase Class (Windows.UI.Xaml.Media) - Windows UWP applications _ Microsoft Docs

    WindowsCommunityToolkit_Microsoft.Toolkit.Uwp.UI.Media_Brushes at master

    UWP TiledBrush - CodeProject

    Working with Brushes and Content – XAML and Visual Layer Interop, Part One - Windows Developer Blog

  • 相关阅读:
    H5实现魔方游戏
    T-SQL:CTE用法(十)
    c# API接收Base64转图片
    T-SQL :联接查询练习 (杂)
    T-SQL:基础练习(杂)
    UI5-文档-导航栏
    UI5-文档-4.10-Descriptor for Applications
    UI5-文档-4.9-Component Configuration
    UI5-文档-4.8-Translatable Texts
    UI5-文档-4.7-JSON Model
  • 原文地址:https://www.cnblogs.com/dino623/p/using_XamlCompositionBrushBase_to_implement_the_tiling_function_of_image.html
Copyright © 2011-2022 走看看