如何在WPF中的几何图形中绘制阴影效果
How to draw dropshadow effect in a geometry in WPF
我正在 Canvas
中绘制以下 Shape
。
我想在通过更改其颜色(简单的部分)和绘图来选择它时突出显示它周围有一个小光环:
这就是我使用 SASS 的方式:http://codepen.io/aaromnido/pen/zKvAwd/
我如何在 WPF 中绘图?请记住,我正在使用 Shape's OnRender 方法绘图。
无论您的控件进入 Highlighted
状态的触发器是什么,在该触发器中只需设置 Effect
属性。对于我的测试,"trigger" 是 属性:
public static readonly DependencyProperty ShowShadowProperty =
DependencyProperty.Register ("ShowShadow", typeof (bool), typeof (TestShape), new PropertyMetadata (false, ShowShadowChanged));
public bool ShowShadow
{
get { return (bool)GetValue (ShowShadowProperty); }
set { SetValue (ShowShadowProperty, value); }
}
private static void ShowShadowChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((TestShape)d).OnShowShadow ();
}
private void OnShowShadow ()
{
if (ShowShadow)
{
Effect = new DropShadowEffect { Direction = 0, ShadowDepth = 20, BlurRadius = 33, Opacity = 1, Color = Colors.Black};
}
else
{
Effect = null;
}
}
这意味着您无需在 OnRender
中执行任何操作。
在构造函数中设置一些默认值。
其中一个默认值是 Shape.Effect
,因为它将在 MouseEnter
事件上进行动画处理。
为 Normal 和 MouseEnter 场景构造 VisualStates
。
使用 MouseEnter
和 MouseLeave
事件处理程序中的 VisualStateManager.GoToElementState()
更改元素的 VisualState
。
您可以使用 DP 公开各种属性以进行自定义。
NewShape.cs
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media.Effects;
namespace WpfWhosebug.NewShape
{
public class CNewShape : Shape
{
public CNewShape()
{
// setting the defaults
this.Width = 40;
this.Height = 40;
this.Stroke = new SolidColorBrush() { Color = Colors.Red };
this.StrokeThickness = 5;
this.Effect = new DropShadowEffect() {
Color = Colors.Transparent,
BlurRadius = 1,
Direction = -150,
ShadowDepth = 1
};
// constructing the VisualStates
_constructVisualStates();
// event handlers
this.MouseEnter += CNewShape_MouseEnter;
this.MouseLeave += CNewShape_MouseLeave;
}
#region EventHandlers
void CNewShape_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
VisualStateManager.GoToElementState(this, "VSNormal", false);
}
void CNewShape_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
VisualStateManager.GoToElementState(this, "VSMouseEnter", false);
}
#endregion
#region Overrides
// This needs to be implemented as it is abstract in base class
GeometryGroup geo = new GeometryGroup();
protected override Geometry DefiningGeometry
{
get { return geo; }
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
Pen pen = new Pen(this.Stroke, StrokeThickness);
drawingContext.DrawEllipse(Brushes.Transparent, pen, new Point(Width/2, Height/2), 40, 40);
drawingContext.DrawEllipse(Stroke, null, new Point(Width / 2, Height / 2), 30, 30);
base.OnRender(drawingContext);
}
#endregion
#region Helpers
private void _constructVisualStates()
{
VisualStateGroup vsg1 = new VisualStateGroup();
#region VSNormal (Normal Visual State)
VisualState stateVSNormal = new VisualState() { Name = "VSNormal" };
Storyboard sbVSNormal = new Storyboard();
ObjectAnimationUsingKeyFrames oa = new ObjectAnimationUsingKeyFrames();
Storyboard.SetTargetProperty(oa, new PropertyPath("Effect"));
DiscreteObjectKeyFrame dokf = new DiscreteObjectKeyFrame(null);
oa.KeyFrames.Add(dokf);
sbVSNormal.Children.Add(oa);
stateVSNormal.Storyboard = sbVSNormal;
vsg1.States.Add(stateVSNormal);
#endregion
#region VSMouseEnter (MouseEnter Visual State)
VisualState stateVSMouseEnter = new VisualState() { Name = "VSMouseEnter" };
Storyboard sbVSMouseEnter = new Storyboard();
ColorAnimation caStrokeColor = new ColorAnimation();
caStrokeColor.To = (Color)ColorConverter.ConvertFromString("#FF24BCDE");
Storyboard.SetTargetProperty(caStrokeColor, new PropertyPath("(Shape.Stroke).(SolidColorBrush.Color)"));
sbVSMouseEnter.Children.Add(caStrokeColor);
ColorAnimation caEffectColor = new ColorAnimation();
caEffectColor.To = (Color)ColorConverter.ConvertFromString("#FFA4E1F3");
Storyboard.SetTargetProperty(caEffectColor, new PropertyPath("(Shape.Effect).(Color)"));
sbVSMouseEnter.Children.Add(caEffectColor);
DoubleAnimation daBlurRadius = new DoubleAnimation();
daBlurRadius.To = 10;
Storyboard.SetTargetProperty(daBlurRadius, new PropertyPath("(Shape.Effect).(BlurRadius)"));
sbVSMouseEnter.Children.Add(daBlurRadius);
DoubleAnimation daDirection = new DoubleAnimation();
daDirection.To = -190;
Storyboard.SetTargetProperty(daDirection, new PropertyPath("(Shape.Effect).(Direction)"));
sbVSMouseEnter.Children.Add(daDirection);
stateVSMouseEnter.Storyboard = sbVSMouseEnter;
vsg1.States.Add(stateVSMouseEnter);
#endregion
VisualStateManager.GetVisualStateGroups(this).Add(vsg1);
}
#endregion
}
}
用法
<local:CNewShape Canvas.Left="70" Canvas.Top="52" Stroke="#FF374095" StrokeThickness="10" Width="100" Height="100" />
输出
图像质量差。在屏幕上实际输出看起来不错。
我正在 Canvas
中绘制以下 Shape
。
我想在通过更改其颜色(简单的部分)和绘图来选择它时突出显示它周围有一个小光环:
这就是我使用 SASS 的方式:http://codepen.io/aaromnido/pen/zKvAwd/
我如何在 WPF 中绘图?请记住,我正在使用 Shape's OnRender 方法绘图。
无论您的控件进入 Highlighted
状态的触发器是什么,在该触发器中只需设置 Effect
属性。对于我的测试,"trigger" 是 属性:
public static readonly DependencyProperty ShowShadowProperty =
DependencyProperty.Register ("ShowShadow", typeof (bool), typeof (TestShape), new PropertyMetadata (false, ShowShadowChanged));
public bool ShowShadow
{
get { return (bool)GetValue (ShowShadowProperty); }
set { SetValue (ShowShadowProperty, value); }
}
private static void ShowShadowChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((TestShape)d).OnShowShadow ();
}
private void OnShowShadow ()
{
if (ShowShadow)
{
Effect = new DropShadowEffect { Direction = 0, ShadowDepth = 20, BlurRadius = 33, Opacity = 1, Color = Colors.Black};
}
else
{
Effect = null;
}
}
这意味着您无需在 OnRender
中执行任何操作。
在构造函数中设置一些默认值。
其中一个默认值是
Shape.Effect
,因为它将在MouseEnter
事件上进行动画处理。为 Normal 和 MouseEnter 场景构造
VisualStates
。使用
MouseEnter
和MouseLeave
事件处理程序中的VisualStateManager.GoToElementState()
更改元素的VisualState
。
您可以使用 DP 公开各种属性以进行自定义。
NewShape.cs
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media.Effects;
namespace WpfWhosebug.NewShape
{
public class CNewShape : Shape
{
public CNewShape()
{
// setting the defaults
this.Width = 40;
this.Height = 40;
this.Stroke = new SolidColorBrush() { Color = Colors.Red };
this.StrokeThickness = 5;
this.Effect = new DropShadowEffect() {
Color = Colors.Transparent,
BlurRadius = 1,
Direction = -150,
ShadowDepth = 1
};
// constructing the VisualStates
_constructVisualStates();
// event handlers
this.MouseEnter += CNewShape_MouseEnter;
this.MouseLeave += CNewShape_MouseLeave;
}
#region EventHandlers
void CNewShape_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
VisualStateManager.GoToElementState(this, "VSNormal", false);
}
void CNewShape_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
VisualStateManager.GoToElementState(this, "VSMouseEnter", false);
}
#endregion
#region Overrides
// This needs to be implemented as it is abstract in base class
GeometryGroup geo = new GeometryGroup();
protected override Geometry DefiningGeometry
{
get { return geo; }
}
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
Pen pen = new Pen(this.Stroke, StrokeThickness);
drawingContext.DrawEllipse(Brushes.Transparent, pen, new Point(Width/2, Height/2), 40, 40);
drawingContext.DrawEllipse(Stroke, null, new Point(Width / 2, Height / 2), 30, 30);
base.OnRender(drawingContext);
}
#endregion
#region Helpers
private void _constructVisualStates()
{
VisualStateGroup vsg1 = new VisualStateGroup();
#region VSNormal (Normal Visual State)
VisualState stateVSNormal = new VisualState() { Name = "VSNormal" };
Storyboard sbVSNormal = new Storyboard();
ObjectAnimationUsingKeyFrames oa = new ObjectAnimationUsingKeyFrames();
Storyboard.SetTargetProperty(oa, new PropertyPath("Effect"));
DiscreteObjectKeyFrame dokf = new DiscreteObjectKeyFrame(null);
oa.KeyFrames.Add(dokf);
sbVSNormal.Children.Add(oa);
stateVSNormal.Storyboard = sbVSNormal;
vsg1.States.Add(stateVSNormal);
#endregion
#region VSMouseEnter (MouseEnter Visual State)
VisualState stateVSMouseEnter = new VisualState() { Name = "VSMouseEnter" };
Storyboard sbVSMouseEnter = new Storyboard();
ColorAnimation caStrokeColor = new ColorAnimation();
caStrokeColor.To = (Color)ColorConverter.ConvertFromString("#FF24BCDE");
Storyboard.SetTargetProperty(caStrokeColor, new PropertyPath("(Shape.Stroke).(SolidColorBrush.Color)"));
sbVSMouseEnter.Children.Add(caStrokeColor);
ColorAnimation caEffectColor = new ColorAnimation();
caEffectColor.To = (Color)ColorConverter.ConvertFromString("#FFA4E1F3");
Storyboard.SetTargetProperty(caEffectColor, new PropertyPath("(Shape.Effect).(Color)"));
sbVSMouseEnter.Children.Add(caEffectColor);
DoubleAnimation daBlurRadius = new DoubleAnimation();
daBlurRadius.To = 10;
Storyboard.SetTargetProperty(daBlurRadius, new PropertyPath("(Shape.Effect).(BlurRadius)"));
sbVSMouseEnter.Children.Add(daBlurRadius);
DoubleAnimation daDirection = new DoubleAnimation();
daDirection.To = -190;
Storyboard.SetTargetProperty(daDirection, new PropertyPath("(Shape.Effect).(Direction)"));
sbVSMouseEnter.Children.Add(daDirection);
stateVSMouseEnter.Storyboard = sbVSMouseEnter;
vsg1.States.Add(stateVSMouseEnter);
#endregion
VisualStateManager.GetVisualStateGroups(this).Add(vsg1);
}
#endregion
}
}
用法
<local:CNewShape Canvas.Left="70" Canvas.Top="52" Stroke="#FF374095" StrokeThickness="10" Width="100" Height="100" />
输出
图像质量差。在屏幕上实际输出看起来不错。