如何在WPF中组合画笔?

时间:2009-10-09 07:15:48

标签: c# wpf animation brush

我有两把刷子。我不知道它们是什么类型的刷子。它们可以是ImageBrushes,SolidBrushes或VisualBrushes。我每个都有一个“刷”类型的变量。

我需要组合两个画笔。我该怎么做?

我试过这个。但它没有用。这是我需要的画笔的Back和Front。

Border Bd = new Border();
Border Bdr = new Border();

Bd.Width = 1.0;
Bd.Height = 1.0;

Bd.Background = Back;
Bdr.Background = Front;

Bd.Child = Bdr;

Brush VB = new VisualBrush(Bd);

我需要这个,因为我正在制作一个自定义动画类来为画笔设置动画。 在进行了一些测试之后,我得出结论,错误在于刷子的组合,而不是在班级的其他地方。

生成的画笔完全透明。


[编辑]

这是完整的BrushAnimation类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;

namespace WPFSoPaTest
{
    class BrushAnimation : AnimationTimeline
    {
                protected override Freezable CreateInstanceCore()
        {
            return new BrushAnimation();
        }
        public override Type TargetPropertyType
        {
            get { return typeof(Brush); }
        }
        static BrushAnimation()
        {
            FromProperty = DependencyProperty.Register("From", typeof(Brush),
                typeof(BrushAnimation));

            ToProperty = DependencyProperty.Register("To", typeof(Brush),
                typeof(BrushAnimation));
        }
        public static readonly DependencyProperty FromProperty;
        public Brush From
        {
            get
            {
                return (Brush)GetValue(BrushAnimation.FromProperty);
            }
            set
            {
                SetValue(BrushAnimation.FromProperty, value);
            }
        }
        public static readonly DependencyProperty ToProperty;
        public Brush To
        {
            get
            {
                return (Brush)GetValue(BrushAnimation.ToProperty);
            }
            set
            {
                SetValue(BrushAnimation.ToProperty, value);
            }
        }
        public override object GetCurrentValue(object defaultOriginValue,
        object defaultDestinationValue, AnimationClock animationClock)
        {
            Brush fromVal = ((Brush)GetValue(BrushAnimation.FromProperty)).CloneCurrentValue();
            Brush toVal = ((Brush)GetValue(BrushAnimation.ToProperty)).CloneCurrentValue();

            if ((double)animationClock.CurrentProgress == 0.0)
                return fromVal; //Here it workes fine.

            if ((double)animationClock.CurrentProgress == 1.0)
                return toVal;   //It workes also here fine.

            toVal.Opacity = (double)animationClock.CurrentProgress;


            Border Bd = new Border();
            Border Bdr = new Border();

            Bd.Width = 1.0;
            Bd.Height = 1.0;

            Bd.Background = fromVal;
            Bdr.Background = toVal;

            Bd.Visibility = Visibility.Visible;
            Bdr.Visibility = Visibility.Visible;
            Bd.Child = Bdr;

            Brush VB = new VisualBrush(Bd);
            return VB; //But here it return's a transparent brush.

            //If I return the 'toVal' variable here it animates correctly the opacity.
        }
    }
}

5 个答案:

答案 0 :(得分:1)

我需要为画笔设置动画的原因是在我在3d对象中使用的材质中为画笔设置动画。我认为刷子的动画比材料更容易。

我已经使用上面的方法来组合画笔,但它在这里不起作用。

在思考了一下后,我决定给材料设置动画,而不是画笔。 结果比使画笔动画更容易。

[注]
此动画类适合我的需要。它只会动画材质中的画笔。我正在使用这个类替换另一个材质的画笔。

[注]
'to material'最终将完全替换'from material',它不会以MaterialGroup结束。

以下是需要它的MaterialAnimation类。我还有一个Point3DCollectionAnimation类。它可用于为3D网格设置动画。这非常有用。 你可以在这个下面找到它。

MaterialAnimation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Media.Media3D;

namespace System.Windows.Media.Animation
{
    class MaterialAnimation : AnimationTimeline
    {
                protected override Freezable CreateInstanceCore()
        {
            return new MaterialAnimation();

        }
        public override Type TargetPropertyType
        {
            get { return typeof(Material); }
        }
        static MaterialAnimation()
        {
            FromProperty = DependencyProperty.Register("From", typeof(Material),
                typeof(MaterialAnimation));

            ToProperty = DependencyProperty.Register("To", typeof(Material),
                typeof(MaterialAnimation));
        }
        public static readonly DependencyProperty FromProperty;
        public Material From
        {
            get
            {
                return (Material)GetValue(MaterialAnimation.FromProperty);
            }
            set
            {
                SetValue(MaterialAnimation.FromProperty, value);
            }
        }
        public static readonly DependencyProperty ToProperty;
        public Material To
        {
            get
            {
                return (Material)GetValue(MaterialAnimation.ToProperty);
            }
            set
            {
                SetValue(MaterialAnimation.ToProperty, value);
            }
        }
        public override object GetCurrentValue(object defaultOriginValue,
        object defaultDestinationValue, AnimationClock animationClock)
        {
            Material fromVal = ((Material)GetValue(MaterialAnimation.FromProperty)).CloneCurrentValue();
            Material toVal = ((Material)GetValue(MaterialAnimation.ToProperty)).CloneCurrentValue();

            if ((double)animationClock.CurrentProgress == 0.0)
                return fromVal; //Here it workes fine.

            if ((double)animationClock.CurrentProgress == 1.0)
                return toVal;   //It workes also here fine.            

            if (toVal.GetType() == (new DiffuseMaterial()).GetType())
                ((DiffuseMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress;
            else
                if (toVal.GetType() == (new SpecularMaterial()).GetType())
                    ((SpecularMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress;
                else
                    ((EmissiveMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress;


            MaterialGroup MG = new MaterialGroup();

            MG.Children.Add(fromVal);
            MG.Children.Add(toVal);            

            return MG; 
        }
    }
}


这是Point3DCollectionAnimation类。

Point3DCollectionAnimation

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media.Media3D;

namespace System.Windows.Media.Animation
{
    public class Point3DCollectionAnimation : AnimationTimeline
    {
        protected override Freezable CreateInstanceCore()
        {
            return new Point3DCollectionAnimation();
        }
        public override Type TargetPropertyType
        {
            get { return typeof(Point3DCollection); }
        }
        static Point3DCollectionAnimation()
        {
            FromProperty = DependencyProperty.Register("From", typeof(Point3DCollection),
                typeof(Point3DCollectionAnimation));

            ToProperty = DependencyProperty.Register("To", typeof(Point3DCollection),
                typeof(Point3DCollectionAnimation));
        }
        public static readonly DependencyProperty FromProperty;
        public Point3DCollection From
        {
            get
            {
                return (Point3DCollection)GetValue(Point3DCollectionAnimation.FromProperty);
            }
            set
            {
                SetValue(Point3DCollectionAnimation.FromProperty, value);
            }
        }
        public static readonly DependencyProperty ToProperty;
        public Point3DCollection To
        {
            get
            {
                return (Point3DCollection)GetValue(Point3DCollectionAnimation.ToProperty);
            }
            set
            {
                SetValue(Point3DCollectionAnimation.ToProperty, value);
            }
        }
        public override object GetCurrentValue(object defaultOriginValue,
        object defaultDestinationValue, AnimationClock animationClock)
        {
            Point3DCollection fromVal = ((Point3DCollection)GetValue(Point3DCollectionAnimation.FromProperty));
            Point3DCollection toVal = ((Point3DCollection)GetValue(Point3DCollectionAnimation.ToProperty));

            Point3DCollection ret;

            int t = 0;
            if (fromVal.Count > toVal.Count)
            {
                ret = fromVal.Clone();
                foreach (Point3D tov in toVal)
                {
                    Point3D frov = fromVal[t];
                    Point3D newv = new Point3D();

                    newv.X = (double)animationClock.CurrentProgress * (tov.X - frov.X) + frov.X;
                    newv.Y = (double)animationClock.CurrentProgress * (tov.Y - frov.Y) + frov.Y;
                    newv.Z = (double)animationClock.CurrentProgress * (tov.Z - frov.Z) + frov.Z;
                    ret[t] = newv;
                    t++;
                }
            }
            else
            {
                ret = toVal.Clone();
                foreach (Point3D frov in fromVal)
                {
                    Point3D tov = toVal[t];
                    Point3D newv = new Point3D();

                    newv.X = (double)animationClock.CurrentProgress * (tov.X - frov.X) + frov.X;
                    newv.Y = (double)animationClock.CurrentProgress * (tov.Y - frov.Y) + frov.Y;
                    newv.Z = (double)animationClock.CurrentProgress * (tov.Z - frov.Z) + frov.Z;
                    ret[t] = newv;
                    t++;
                }
            }

            return ret;
        }
    }
}

我希望这些课程对于需要它们的人有用。我在互联网上搜索了它们,但没有找到它们。我确信有更多的人需要这些课程。

请留言。

答案 1 :(得分:1)

我发现了这个问题。 Visual Brushes不可冻结。要使代码工作,我需要找到一种方法来冻结画笔。

答案 2 :(得分:1)

Aaron,我已经使用了如上所示的BrushAnimation类,它可以满足我的特定需求。但是,我注意到StackOverflow在Creative Commons许可下运行。因此,我在未经您许可的情况下,无法在我的商业应用程序中使用该类(我不希望使用Creative Commons许可证)。你愿意给我许可吗?我仍然相信你的工作。

我找不到任何其他方式与您联系,因为我还不能发表评论。

答案 3 :(得分:0)

只要前笔中有透明像素,上述方法就可以正常工作。如果不是,前刷会覆盖后刷。您应该提供一个更完整的示例来查看实际情况。

答案 4 :(得分:0)

您可以使用可视化刷来实现

<Grid.Background>
       <VisualBrush>
                <VisualBrush.Visual>
                    <Grid 
                        Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}, Mode=OneWay}" 
                        Height="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type FrameworkElement}}, Mode=OneWay}">

                        <Rectangle Fill="Blue" />
                        <Image Source="your image path" Stretch="Uniform" />

                    </Grid>
                </VisualBrush.Visual>
            </VisualBrush>
        </Grid.Background>