【Win10】实现控件倒影效果
先引入个小广告:
最近买了台小米盒子折腾下,发觉 UI 还是挺漂亮的,特别是主页那个倒影效果。

(图随便找的,就是上面图片底部的那个倒影效果。)
好了,广告结束,回归正题,这个倒影效果我个人觉得是挺不错的,那么有没有办法在 Win10 中实现呢?
稍微分析了一下,大概层次是这样的:

简单点来说,就是倒影显示跟控件显示一样,然后往下翻转,再平移一下就好了。最后再对倒影加个渐变透明就 perfect 了。
翻转、平移都很容易,使用 RenderTransform 就可以了。麻烦就麻烦在如何让倒影的显示跟控件的显示相同。
在 WinRT 里,是没有 VisualBrush 这种东西的,因此我们得另寻他径。俗语说:上帝关闭一扇门的同时也为你打开一扇窗。微软虽然去掉 VisualBrush,但是给了我们 RenderTargetBitmap 这种获取绝大部分控件当前样貌的神器。(MediaElement 获取不了,WebView 则需另外使用 WebViewBrush 来获取,这里我们忽略掉这两个不是常见需求的家伙。)
那么我们就可以将倒影设置为 Image 控件,然后赋值上 RenderTargetBitmap 就可以了。但问题又来了,我们应该什么时候去抓一次控件的外貌?查阅 MSDN 得知,LayoutUpdated 事件可以帮到我们。
还等什么,立马开始编写我们的代码。
创建我们的项目,新建一个名字叫做 ReflectionPanel 的模板化控件。
然后定义我们的控件模板如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ReflectionPanelDemo"
xmlns:controls="using:ReflectionPanelDemo.Controls">
<Style TargetType="controls:ReflectionPanel">
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:ReflectionPanel">
<Grid x:Name="RootLayout"
Background="{TemplateBinding Background}">
<!--#region 倒影-->
<!--以控件底部中心作为变换点-->
<Image x:Name="ReflectionImage"
Stretch="None"
RenderTransformOrigin="0.5,1">
<Image.RenderTransform>
<TransformGroup>
<!--以控件底部反转控件-->
<ScaleTransform ScaleY="-1" />
<!--倒影与实际内容的间距-->
<TranslateTransform x:Name="SpacingTransform"
Y="0" />
</TransformGroup>
</Image.RenderTransform>
</Image>
<!--#endregion-->
<!--#region 实际内容-->
<ContentControl x:Name="ContentBorder"
Content="{TemplateBinding Content}" />
<!--#endregion-->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
这样对应上之前的分析了。
接下来编写 cs 代码。
protected override void OnApplyTemplate()
{
FrameworkElement rootLayout = (FrameworkElement)this.GetTemplateChild("RootLayout"); // 实际内容容器。
this._contentBorder = (ContentControl)this.GetTemplateChild("ContentBorder"); // 倒影图片。
this._reflectionImage = (Image)this.GetTemplateChild("ReflectionImage"); // 倒影位移。
this._spacingTransform = (TranslateTransform)this.GetTemplateChild("SpacingTransform");
this._spacingTransform.Y = this.ReflectionSpacing; if (DesignMode.DesignModeEnabled == false)
{
rootLayout.LayoutUpdated += this.RootLayoutChanged;
}
} private async void RootLayoutChanged(object sender, object e)
{
try
{
// 呈现控件到图像源。
RenderTargetBitmap contentRender = new RenderTargetBitmap();
await contentRender.RenderAsync(this._contentBorder); // 设置倒影图片。
this._reflectionImage.Source = contentRender;
}
catch
{
}
}
这里是最关键的代码。详细可以看文章末尾提供的 demo。
接下来尝试一下吧。

感觉还不错的说。
最后,我们来做渐变的半透明效果。
在 WinRT 里,由于没了 OpacityMask 属性,因此我们还是从图片入手吧。
RenderTargetBitmap 有一个叫 GetPixelsAsync 的方法,可以获取到图片的数据,格式是以 BGRA8 的格式,这里联动一下老周的 blog 好了(http://www.cnblogs.com/tcjiaan/p/4231886.html)。
简单点说,就是每 4 个 byte 代表一个像素。我们再简单分析下需求,那么可以得出,图片最顶部是最透明的,最底部是最不透明的。
经过简单的数学计算,我们可以写出以下代码:
// 获取图像数据。
byte[] bgra8 = (await contentRender.GetPixelsAsync()).ToArray(); // 获取图像高度和宽度。
int width = contentRender.PixelWidth;
int height = contentRender.PixelHeight; for (int i = ; i < bgra8.Length; i += )
{
// 获取该像素原来的 A 通道。
byte a = bgra8[i + ]; // 计算该像素的 Y 轴坐标。
int y = (i / ) / width; // 计算新的 A 通道值。
bgra8[i + ] = (byte)(a * y / height);
}
最后我们将修改后的 data 弄到 Image 控件上去就 ok 了。这里我们使用 WriteableBitmap。
WriteableBitmap outputBitmap = new WriteableBitmap(width, height);
bgra8.CopyTo(outputBitmap.PixelBuffer); // 设置倒影图片。
this._reflectionImage.Source = outputBitmap;
大功告成,看一下 Demo 的效果。

最后附带完整 Demo 下载:ReflectionPanelDemo.zip
【Win10】实现控件倒影效果的更多相关文章
- Delphi XE2 新控件 布局Panel TGridPanel TFlowPanel
Delphi XE2 新控件 Firemonkey 布局Panel Windows平台VCl TGridPanel TFlowPanel FMX 跨平台 TLayout TGridLayout TFl ...
- 【Win10】SplitView控件
SplitView是Win10中的新控件. 用于呈现两部分视图. 一个视图是主要内容,另一个视图是用于导航.(也就是通常说的汉堡菜单.) 主要结构: <SplitView> <Spl ...
- 【Win10开发】相对布局——RelativePanel控件
我们知道,Win10引入了Universal Windows Platform,那么我们针对不同的平台该有不同的布局,此时我们就需要相对布局,就会用到RelativePanel这个控件.我们不再将控件 ...
- 模仿win10样式,基于jquery的时间控件
工作需要,写了一个基于jquery的时间控件,仿win10系统时间控件格式. 目前基本功能都有了,但时间格式只实现少数,但由于结构设计已经充分优化,填充起来非常容易. 这个控件相对网上其他的时间控件, ...
- win10 uwp 拖动控件
我们会使用控件拖动,可以让我们做出好看的动画,那么我们如何移动控件,我将会告诉大家多个方法.其中第一个是最差的,最后的才是我希望大神你去用. Margin 移动 我们可以使用Margin移动,但这是w ...
- WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书
原文:WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书 最近项目中使用弹出控件Popup,发现弹出框的对齐方式在不同的系统中存在不同(Popup在win10上是 ...
- Win10 UWP开发系列——开源控件库:UWPCommunityToolkit
在开发应用的过程中,不可避免的会使用第三方类库.之前用过一个WinRTXamlToolkit.UWP,现在微软官方发布了一个新的开源控件库—— UWPCommunityToolkit 项目代码托管在G ...
- 【Win10】【Win2D】实现控件阴影效果
学过 WPF 的都知道,在 WPF 中,为控件添加一个阴影效果是相当容易的. <Border Width="100" Height="100" Backg ...
- 【WIN10】基本控件
先發個下載地址: http://yunpan.cn/cHuCqYzvsWFAL 访问密码 3470 說明一下.這個示例只是最簡單的演示,並不能提供太大的實用價值. 後面會介紹 Bing & ...
随机推荐
- \extras\intel\Hardware_Accelerated_Execution_Manager HAXM 未安装导致AndroidStudio新建了模拟器开启不了
之前安装过 bios模式也是正常的.所以按照下面的步骤操作. https://software.intel.com/en-us/android 在这个界面 选择右侧的, 下载后解压到下面图上的路径: ...
- Java工具类_随机生成任意长度的字符串【密码、验证码】
import java.util.Random; public class PasswordCreate { /** * 获得密码 * @param len 密码长度 * @return */ pub ...
- Cause: org.xml.sax.SAXParseException; lineNumber: 45; columnNumber: 62; 元素内容必须由格式正确的字符数据或标记组成。
三月 09, 2018 12:13:39 下午 org.apache.catalina.core.StandardContext listenerStart严重: Exception sending ...
- grep匹配字符串出现的次数
背景:想要匹配一个html页面中某个字符出现的次数 遇到的问题: 用grep -c “xxx字符”得到的是行数,如果一行中有多个匹配到的字符,只会算作一个 解决方法: 使用grep - ...
- 检测到有潜在危险的 Request.Form 值——ValidateRequest的使用
1.aspx中 在 Web 应用程序中,要阻止依赖于恶意输入字符串的黑客攻击,约束和验证用户输入是必不可少的.跨站点脚本攻击就是此类攻击的一个示例. 当请求验证检测到潜在的恶意客户端输入时,会引发此异 ...
- 增加路由ip
C:\Windows\system32>route add ip地址 -P 操作完成!
- TZOJ 4839 麦森数(模拟快速幂)
描述 形如2^P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2^P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有9 ...
- 4-js 函数
总是有些奇奇怪怪的问题: <div> <p class="productStatus"> <span>成交量 <em>${goods ...
- css3阴影效果
http://blog.csdn.net/freshlover/article/details/7610269
- 大乐透 Java随机码
package suijishu; import java.util.Random; // TODO Auto-generated method stub public class Xuanqi { ...