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

[UWP]通过自定义XamlCompositionBrushBase实现图片平铺的更多相关文章

  1. ie8下背景图片平铺问题

    IE9+及其他浏览器实现背景图片平铺可能需要一个属性就可以background-size:100%/cover; 但是ie8下background-size是不兼容的,因此我们需要用到滤镜,来解决背景 ...

  2. Duilib技巧:背景图片平铺

    贴图的描述 方式有两种    // 1.aaa.jpg    // 2.file='aaa.jpg' res='' restype='0' dest='0,0,0,0' source='0,0,0,0 ...

  3. android实现图片平铺效果&WebView多点触控实现缩放

    1.图片平铺效果实现非常简单,只要在xml中添加一个 android:tileMode的属性就可以了.首先在drawable文件夹中添加自己的my.xml文件.代码: Java代码 <?xml ...

  4. Canvas 图片平铺设置

    /** * 图片平铺 */ function initDemo7(){ var canvas = document.getElementById("demo7"); if (!ca ...

  5. iOS UIButton 设置图片平铺

    UIImage *image2 = [UIImage imageNamed:imgName]; CGFloat top = ; // 顶端盖高度 CGFloat bottom = ; // 底端盖高度 ...

  6. Android中设定背景图片平铺。

    注:本文由Colin撰写,版权所有!转载请注明原文地址,谢谢合作! 在做Android开发时,我们常常需要为程序设定一个背景,但由于现在的Android设备尺寸不一,如果随便设置一个图片为背景,那么很 ...

  7. 一款js控制背景图片平铺

    背景图片的平铺方法有很多种,纯色背景,渐变背景,图片背景,今天讲的是移动端的图片背景~~~~ <style> html,body{;;} .body{background: url(ima ...

  8. [ATL/WTL]_[0基础]_[CBitmap复制图片-截取图片-平铺图片]

    场景: 1.当你须要截取图片部分区域作为某个控件的背景. 2.须要平铺图片到一个大区域让他自己主动放大时. 3.或者须要合并图片时. 代码: CDC sdc; CDC ddc; sdc.CreateC ...

  9. LODOP中设置设置图片平铺水印,超文本透明

    之前的博文:LODOP中平铺图片 文本项Repeat. 该博文中是平铺的图片,上面是文本.如果是图片add_print_image和add_print_text纯文本,这两个打印项设计的,可以直接通过 ...

随机推荐

  1. RegExp实现字符替换

    将字符串组中的所有Paul替换成Ringo,g:执行全局匹配,查找所有匹配而非在找到第一个匹配后停止;\b:匹配单词边界,划分匹配字符的起始范围 <!DOCTYPE html> <h ...

  2. 手写OOXML文档——导出xlsx格式表格文档

    一.准备工作: 2个js库,另外把样式文件抽离出来 require('file-saver'); import JSZip from 'jszip' import {stylesData,theme1 ...

  3. Ubuntu安装NASM和简单的使用教程

    1. 安装 sudo apt-get install nasm 这样nasm就安装好了,终端输入命令: nasm -version 输出版本信息就说明安装成功 2. 使用 创建"hello. ...

  4. 项目代码管理工具Git的总结

    在项目的开发中,代码的同步管理很重要,团队的几个人可以通过免费的github管理自己的开源项目代码,高效方便.下面说说,开发中经常用到的git指令操作,基于github平台. 0.配置提交者的账户和邮 ...

  5. Android Studio 模拟器Intel 加速

    Starting emulator for AVD 'Phone1'emulator: ERROR: x86 emulation currently requires hardware acceler ...

  6. DP题 总结 [更新中]

    建设中 ... 预防针 : 本蒟蒻代码风格清奇(⊙﹏⊙)b 一.选学霸 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议.所 ...

  7. LeetCode初级算法--树02:验证二叉搜索树

    LeetCode初级算法--树02:验证二叉搜索树 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...

  8. java集合之HashSet哈希SET基础

    hashSet实现set接口.serializable.cloneable接口.不允许有重复值,但可以null,不保证与插入顺序一致. HashSet迭代的时间与HashSet实例的大小(元素的数量) ...

  9. VMware安装和linux(centos7)系统安装

    下载centos系统ISO镜像 安装linux系统和winsdows安装系统一样,需要系统文件.浏览器访问centos官网进行下载,http://www.centos.org,因为是国外网站所有下载速 ...

  10. dapper之连接数据库(Oracle,SQL Server,MySql)

    因为项目需求,需要项目同时可以访问三个数据库,因此本人经过一番研究,得出以下代码. 1.建立公共连接抽象类(DataBase) public abstract class DataBase { /// ...