【Win 10 应用开发】UI Composition 札记(八):用 XamlLight 制作灯光效果
2021-04-26 06:28
标签:应用 text gis strong alt setvalue isp connect def 前面老周已介绍过灯光的使用,如果你忘了,请用九牛二虎之力猛点击 这里 去复习一下。本篇老周再介绍另一种添加灯光的方法,这种方法是专为 XAML 元素而设计的,可以很方便地为可视化元素添加灯光效果。 不知道大伙伴是否发现,UIElement 类公开了一个 Lights 属性(15063,v1703,或更高版本),它是一个列表,可以添加若干个 XamlLight 对象。通过这个属性,我们也能为 XAML 可视化元素设置灯光。 虽然我们看到 XamlLight 类有构造函数,但是,它不是直接使用的,因为它一些重要成员都声明为 protected,这在外部类是无法访问的。所以,你必须自己派生出一个自定义的类型,然后为这些成员设置相关的内容。为什么这样做呢?你想想啊,如果只实例化这个类,运行时根本不可能知道你要用啥灯光,故你得自己去动手写。 先看看这些重要成员是啥。 先介绍一下长得最帅的那个—— CompositionLight,我们在代码中根据自己的需要,使用 Compositor 来创建灯光实例,还记得前面学过的内容吧,然后把灯光实例赋值给 CompositionLight 属性。 那么,在啥时候赋值呢?我们看到,有两个对应的方法—— OnConnected 和 OnDisconnected。当咱们把自定义的类型实例添加到 UIElement 元素的 Lights 列表中时,就会调用 OnConnected 方法,而跟随方法参数传递的就是这个可视化元素的实例。比如,你把这个自定义类实例添加到 Grid 的 Lights 列表中,那么传给 newElement 参数的就是这个 Grid。相反地,当我们自定义的XamlLight对象从 Lights 列表中被移除时,会调用 OnDisconnected 方法,这时候我们就应该把 CompositionLight 属性所占用的资源清理掉,如调用 Dispose 方法,然后把属性设置为 null。 估计你也看到了,XamlLight 类还有一个成员—— GetId 方法,你也必须实现这个成员,然后你要返回一个字符串,这个字符串必须能够唯一地代表你实现的这个类,最好的办法是返回这个类的类名,因为这个一般都能唯一的(我说的是包括命名空间名字的)。那这个字符串又在哪里用呢?你再看,XamlLight 类有两对静态方法: AddTargetElement 与 RemoveTargetElement:用来指定哪些元素能被灯光照见,Add 进去的可视化对象就能被照亮的,而 Remove 后的对象是不会被灯光照亮的,你会看到,方法的第一个参数是一个字符串类型的 lightId,对的,这就是上面我们实现 GetId 方法的作用了。 AddTargetBrush 与 RemoveTargetBrush:使灯光照射到画刷上,而不是照到可视化对象上,用法也一样,Add了的画刷会被照亮,Remove后的画刷是不被照亮的。 在应用灯光对象时你要记住,把它添加到 UIElement 对象的 Lights 列表中,仅仅说明为这个灯光安排了照射空间。这个前面在介绍灯光时老周讲过的,比如 PointLight ,它是点状光,你必须安排一个 CoordinateSpace 对象,作为灯光的参数,这好比你把蜡烛放在一个小房子中,你不能把蜡烛放在野外,因为空矿的环境会严重削弱光线,所以,你得安排一个参照空间。此处,把自定义 XamlLight 放进 Lights 列表中,仅仅相当于你安排了这个 UI 元素作为参照空间而已,而这个空间内的子元素并不会真正应用灯光,所以,你必须调用静态的 AddTargetElement 方法,指明里面的哪些子元素会被照亮。 如果你把灯光对象添加到 Grid 的 Lights 列表中,表明灯光是以这个 Grid 为参照空间,然后你调用 AddTargetElement 方法,并把这个 Grid 元素传给方法,这说明整个 Grid 元素包括它的子元素都会被照亮的。如果你只希望 Grid 元素中某个子元素被照亮,就把子元素传给 AddTargetElement 方法。 好,说了那么多 F 话,咱们动手试试。 从 XamlLight 类派生,我们自定义一个灯源,叫 MyCustLight。 GetId 方法我就不解释了,你能看懂的。说说其他成员,调用 OnConnected 方法时,咱们创建一个 PointLight 实例,需要用到的 Compositor 实例可以从 Window.Current.Compositor 属性中获取,同一个窗口下的UI元素都共用的。 设置好点状光的各个参数,然后记得赋值给 CompositionLight 属性,这个一定不要忘了,不然灯光是不起作用的。下面这一行也是重要的。 这意思就是,把 Lights 所属的 UI 元素加入到可被照亮区域,包括其子元素。 当光源从 Lights 列表中移除时,要调用 OnDisconnected 方法,在这个方法中,要把可照亮区域 Remove 掉,还要把 CompositionLight 属性所引用的资源清理掉。 好了,现在,自定义灯源已经做好,咱们用 XAML 对象试试。 为了方便看到灯光效果,我把 Grid 的背景弄成黑色。子元素中有文字,也有二师兄的头像,有关二师兄的照片,你可以网上找,二师兄那么出名,网上有他的照片。 首先,让大家看看,没有应用灯光效果时,二师兄的身份证。 二师兄还是那么帅。然后,转到代码视图,为 Grid 应用灯光。 如果你觉得用 XAML 添加更好,可以用 XAML 来添加。 注意,两种方法取一即可,不要重复加。 现在,我们看看,二师兄被灯光照射后会变成什么样的。 二师兄依旧很帅。 这时候你又在想,我只想让灯光照射二师兄的头像,而不希望照射到右边的文本,那咱办呢?上面老周说过了,决定元素是否被照射,就是 AddTargetElement 方法在起作用。我们把 MyCustLight 类改一下就行了,弄一个附加属性,值为 bool 类型,如果某个子元素设为 true,就照亮它,如果为 false 就不照亮了。 来,咱们把 MyCustLight 类改一下。 因为这个类我在声明时没有加 public 修饰符,默认就成为 internal ,非 public 类无法在 XAML 中使用附加属性,所以,得先把它改为公共类。 然后,GetId 方法的实现也要改,咱们知道,依赖项属性或附加属性都是静态成员,而我们在响应附加属性更改的回调方法中要用到 XamlLight 的 AddTargetElement 或 RemoveTargetElement 方法,这样是要提供这个 ID 字符串的,所以,我们可以定义一个静态属性,返回这个 ID,然后在 GetId 方法访问一下就可以了。 下面是重点,我们为这个类注册一个名为 IsLightEnabled 的附加属性。 附加属性封装比较特殊,用 Get**** 和 Set**** 两个静态方法,也必须是 public 的。 注意,Get*** 和 Set*** 中的 *** 一定要与你刚刚注册的附加属性的名字一致,不要写错了。 当这个附加属性被修改后,我们通过回调方法来判断属性值是否为 true,若为真,就应用灯光效果,若为假,就移除灯光效果。 在 OnConnected 和 OnDisconnected 方法的实现中,把刚才的 AddTargetElement 和 RemoveTargetElement 方法的调用代码删除掉,因为咱们已经用附加属性处理了。 现在,MyCustLight 类应该变成这个样子。 最后,在 XAML 代码中,让 Image 元素接收光源,而右边的文本不接收光源。 再次运行,就可以看到,只有二师兄的猪头上有灯光,而右边的文本不会被灯光照亮。 OK,今天的内容就扯到这里,88。 【Win 10 应用开发】UI Composition 札记(八):用 XamlLight 制作灯光效果 标签:应用 text gis strong alt setvalue isp connect def 原文地址:http://www.cnblogs.com/tcjiaan/p/7895866.htmlprotected virtual void OnConnected(UIElement newElement);
protected virtual void OnDisconnected(UIElement oldElement);
protected virtual string GetId();
// 这个属性用来设置要用的灯光对象
protected CompositionLight CompositionLight { get; set; }
class MyCustLight : XamlLight
{
protected override string GetId()
{
return GetType().FullName;
}
protected override void OnConnected(UIElement newElement)
{
// 创建灯光
var compositor = Window.Current.Compositor;
PointLight light = compositor.CreatePointLight();
// 设置灯光参数
light.Color = Colors.LightGreen;
light.Offset = new System.Numerics.Vector3(240f, 80f, 20f);
light.Intensity = 5.3f;
// 为属性赋值
CompositionLight = light;
// 这一句很重要
XamlLight.AddTargetElement(GetId(), newElement);
}
protected override void OnDisconnected(UIElement oldElement)
{
// 这一句是对应的,Add了之后就要Remove
XamlLight.RemoveTargetElement(GetId(), oldElement);
// 释放资源
CompositionLight.Dispose();
CompositionLight = null;
}
}
XamlLight.AddTargetElement(GetId(), newElement);
// 这一句是对应的,Add了之后就要Remove
XamlLight.RemoveTargetElement(GetId(), oldElement);
// 释放资源
CompositionLight.Dispose();
CompositionLight = null;
Grid Name="layout" Background="Black">
Grid Margin="10">
Grid.ColumnDefinitions>
ColumnDefinition Width="auto"/>
ColumnDefinition Width="*"/>
Grid.ColumnDefinitions>
Image Source="Assets/1.jpg" Width="300" Height="300"/>
StackPanel Grid.Column="1" Margin="13">
RichTextBlock Foreground="Yellow">
Paragraph>
Run Text="姓名:" FontWeight="Bold"/>
Run Text="八戒" />
Paragraph>
Paragraph>
Run Text="性别:" FontWeight="Bold"/>
Run Text="男"/>
Paragraph>
Paragraph>
Run Text="民族:" FontWeight="Bold"/>
Run Text="猪"/>
Paragraph>
Paragraph>
Run Text="优点:" FontWeight="Bold"/>
Run Text="勤劳、憨厚、和善"/>
Paragraph>
RichTextBlock>
StackPanel>
Grid>
Grid>
public MainPage()
{
this.InitializeComponent();
MyCustLight light = new MyCustLight();
layout.Lights.Add(light);
}
Grid Name="layout" Background="Black">
Grid.Lights>
local:MyCustLight/>
Grid.Lights>
……
Grid>
public class MyCustLight : XamlLight
protected override string GetId()
{
return LightID;
}
// 通过静态属性返回
private static string LightID => typeof(MyCustLight).FullName;
public static readonly DependencyProperty IsLightEnabledProperty = DependencyProperty.RegisterAttached("IsLightEnabled", typeof(bool), typeof(MyCustLight), new PropertyMetadata(false, OnIsLightEnabledPropertyChanged));
public static void SetIsLightEnabled(DependencyObject obj, bool val)
{
obj.SetValue(IsLightEnabledProperty, val);
}
public static bool GetIsLightEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsLightEnabledProperty);
}
private static void OnIsLightEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
bool b = (bool)e.NewValue;
UIElement targetUiele = d as UIElement;
if (b) //如要照亮
{
XamlLight.AddTargetElement(LightID, targetUiele);
}
else //如果不想照亮
{
XamlLight.RemoveTargetElement(LightID, targetUiele);
}
}
public class MyCustLight : XamlLight
{
protected override string GetId()
{
return LightID;
}
// 通过静态属性返回
private static string LightID => typeof(MyCustLight).FullName;
public static readonly DependencyProperty IsLightEnabledProperty = DependencyProperty.RegisterAttached("IsLightEnabled", typeof(bool), typeof(MyCustLight), new PropertyMetadata(false, OnIsLightEnabledPropertyChanged));
public static void SetIsLightEnabled(DependencyObject obj, bool val)
{
obj.SetValue(IsLightEnabledProperty, val);
}
public static bool GetIsLightEnabled(DependencyObject obj)
{
return (bool)obj.GetValue(IsLightEnabledProperty);
}
private static void OnIsLightEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
bool b = (bool)e.NewValue;
UIElement targetUiele = d as UIElement;
if (b) //如要照亮
{
XamlLight.AddTargetElement(LightID, targetUiele);
}
else //如果不想照亮
{
XamlLight.RemoveTargetElement(LightID, targetUiele);
}
}
protected override void OnConnected(UIElement newElement)
{
// 创建灯光
var compositor = Window.Current.Compositor;
PointLight light = compositor.CreatePointLight();
// 设置灯光参数
light.Color = Colors.LightGreen;
light.Offset = new System.Numerics.Vector3(240f, 80f, 20f);
light.Intensity = 5.3f;
// 为属性赋值
CompositionLight = light;
}
protected override void OnDisconnected(UIElement oldElement)
{
// 释放资源
CompositionLight.Dispose();
CompositionLight = null;
}
}
Grid Margin="10">
……
Image Source="Assets/1.jpg" Width="300" Height="300" local:MyCustLight.IsLightEnabled="True"/>
StackPanel Grid.Column="1" Margin="13" local:MyCustLight.IsLightEnabled="False">
RichTextBlock Foreground="Yellow">
……
RichTextBlock>
StackPanel>
Grid>
文章标题:【Win 10 应用开发】UI Composition 札记(八):用 XamlLight 制作灯光效果
文章链接:http://soscw.com/index.php/essay/79702.html