创建动态阴影






4.75/5 (12投票s)
如何创建一个容器控件,用于在任何包含的控件上创建完全夸张的动态阴影。
引言
本文说明了如何创建一个容器控件,用于在任何包含的控件上创建完全夸张的动态阴影。它还展示了创建自定义 WPF 控件的原理。这些阴影可能会为您的应用程序带来额外的关注,或者如果用在所有控件上,可能会毁掉它。
背景
我看到一个 jQuery 示例展示了动态阴影,并认为在 WPF 中会更好。因此,我决定尝试一下……
解决方案
我创建了一个包含自定义 WPF 容器控件的单个项目。类 MainWindow
包含一个依赖属性 MousePosition
。所有容器控件都绑定到此属性,以获取鼠标位置的更新。
类图
使用 DynamicDropshadow
控件
<Window x:Class="Dk.Nmt.Development.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:Dk.Nmt.Development"
Title="MainWindow" Height="449" Width="567">
<Grid>
<my:DynamicDropshadow Height="131" HorizontalAlignment="Left" Margin="325,63,0,0"
x:Name="dynamicDropshadow1" VerticalAlignment="Top" Width="178"
MousePosition="{Binding Path=MousePosition, RelativeSource={RelativeSource AncestorType=Window}}">
<Label>Wrapped control goes here...</Label>
</my:DynamicDropshadow>
...
DynamicDropshadow
的样式实现了一个控件模板,该模板使用边框来放置阴影
<Style x:Key="DynamicDropshadowStyle" TargetType="{x:Type Development:DynamicDropshadow}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontFamily" Value="Tahoma" />
<Setter Property="FontSize" Value="11px" />
<Setter Property="Padding" Value="6" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Development:DynamicDropshadow}">
<Border x:Name="PART_DropShadowBorder" CornerRadius="5"
Background="{TemplateBinding Background}">
<Border.Effect>
<DropShadowEffect
Color="{Binding ShadowColor, RelativeSource={RelativeSource TemplatedParent}}"
Opacity="{Binding ShadowOpacity, RelativeSource={RelativeSource TemplatedParent}}"
Direction="{Binding Direction, RelativeSource={RelativeSource TemplatedParent}}"
ShadowDepth="{Binding ShadowDepth, RelativeSource={RelativeSource TemplatedParent}}"
BlurRadius="{Binding ShadowBlur, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border.Effect>
<ContentPresenter x:Name="PART_DropShadowContent"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
阴影的计算是在鼠标移动时完成的。计算是基于鼠标指针的方向和距离进行的
public void CalcDropShadow()
{
// Get the position to the mouse, relative to the center of the control
var p = Mouse.GetPosition(this);
p.Offset(-Width / 2, -Height / 2);
// Calculate the angle to the mouse position
if (p.X > 0 && p.Y < 0)
Direction = Math.Atan(-p.Y / p.X) * (180f / Math.PI) - 180;
if (p.X < 0)
Direction = Math.Atan(-p.Y / p.X) * (180f / Math.PI);
if (p.X > 0 && p.Y > 0)
Direction = Math.Atan(-p.Y/p.X)*(180f/Math.PI) + 180;
// Calculate distance, depth and blur
double distance = Math.Sqrt(Math.Pow(p.X, 2) + Math.Pow(p.Y, 2));
ShadowDepth = 1 + .1 * distance;
ShadowBlur = Math.Max(20 - .1 * distance,5);
}
我选择让阴影随着与鼠标的距离增加而变得更深、更不模糊。
关注点
一些控件,如 Calendar
,似乎在应用效果时会丢失 ClearType
。
历史
这是版本 1.0.0.0。