【问题标题】:How to draw dropshadow effect in a geometry in WPF如何在 WPF 中的几何图形中绘制阴影效果
【发布时间】:2016-10-05 10:44:58
【问题描述】:

我正在Canvas 中绘制以下Shape

我想通过改变它的颜色(简单的部分)并在它周围画一个小光环突出显示它

这就是我使用 SASS 的方式:http://codepen.io/aaromnido/pen/zKvAwd/

如何在 WPF 中绘图?请记住,我正在使用Shape's OnRender 方法进行绘图。

【问题讨论】:

    标签: wpf canvas drawing shape


    【解决方案1】:
    1. 在构造函数中设置一些默认值。

    2. 其中一个默认值是Shape.Effect,因为它会在MouseEnter 事件上进行动画处理。

    3. 为 Normal 和 MouseEnter 场景构造 VisualStates

    4. MouseEnterMouseLeave 事件处理程序中使用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 WpfStackOverflow.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" />
    

    输出

    图像质量很差。屏幕上的实际输出看起来不错。

    【讨论】:

      【解决方案2】:

      无论您的触发器是什么,您的控件进入Highlighted 状态,在该触发器中只需设置Effect 属性。对于我的测试,“触发器”是一个属性:

          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 中执行任何操作。

      【讨论】:

        猜你喜欢
        • 2013-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-24
        • 2019-07-22
        • 2012-01-29
        • 2012-11-02
        相关资源
        最近更新 更多