【问题标题】:How do I combine brushes in WPF?如何在 WPF 中组合画笔?
【发布时间】:2009-10-09 07:15:48
【问题描述】:

我有两把刷子。我不知道它们是什么类型的刷子。它们可以是 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.
        }
    }
}

【问题讨论】:

    标签: c# wpf animation brush


    【解决方案1】:

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

    我已经用上面的方法来组合画笔了,但是这里不行。

    经过一番思考,我决定为材质而不是画笔设置动画。 结果比动画画笔更容易。

    [注意]
    这个动画课程适合我的需要。它只会为材质中的画笔设置动画。我正在使用这个类来替换另一个材质的画笔。

    [注意]
    “to material”最终将完全替换“from material”,它不会以 MaterialGroup 结尾。

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

    材质动画

    使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Text; 使用 System.Windows.Media.Animation; 使用 System.Windows; 使用 System.Windows.Media; 使用 System.Windows.Controls; 使用 System.Windows.Media.Media3D; 命名空间 System.Windows.Media.Animation { 类 MaterialAnimation : 动画时间线 { 受保护的覆盖 Freezable CreateInstanceCore() { 返回新的 MaterialAnimation(); } 公共覆盖类型 TargetPropertyType { 得到{返回类型(材料); } } 静态材料动画() { FromProperty = DependencyProperty.Register("From", typeof(Material), 类型(材料动画)); ToProperty = DependencyProperty.Register("To", typeof(Material), 类型(材料动画)); } 公共静态只读 DependencyProperty FromProperty; 公开资料来自 { 得到 { 返回 (Material)GetValue(MaterialAnimation.FromProperty); } 放 { SetValue(MaterialAnimation.FromProperty, value); } } 公共静态只读 DependencyProperty ToProperty; 公开资料 { 得到 { 返回(材料)GetValue(材料动画.ToProperty); } 放 { SetValue(MaterialAnimation.ToProperty, 值); } } 公共覆盖对象GetCurrentValue(对象defaultOriginValue, 对象 defaultDestinationValue, AnimationClock animationClock) { 材料 fromVal = ((Material)GetValue(MaterialAnimation.FromProperty)).CloneCurrentValue(); 材质 toVal = ((Material)GetValue(MaterialAnimation.ToProperty)).CloneCurrentValue(); 如果((双)animationClock.CurrentProgress == 0.0) 从Val返回; //在这里它工作正常。 如果((双)animationClock.CurrentProgress == 1.0) 返回Val; //它在这里也可以正常工作。 if (toVal.GetType() == (new DiffuseMaterial()).GetType()) ((DiffuseMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress; 别的 if (toVal.GetType() == (new SpecularMaterial()).GetType()) ((SpecularMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress; 别的 ((EmissiveMaterial)toVal).Brush.Opacity = (double)animationClock.CurrentProgress; MaterialGroup MG = new MaterialGroup(); MG.Children.Add(fromVal); MG.Children.Add(toVal); 返回MG; } } }


    这是 Point3DCollectionAnimation 类。

    Point3DCollectionAnimation

    使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Text; 使用 System.Windows.Media.Animation; 使用 System.Windows; 使用 System.Windows.Media.Media3D; 命名空间 System.Windows.Media.Animation { 公共类 Point3DCollectionAnimation : 动画时间线 { 受保护的覆盖 Freezable CreateInstanceCore() { 返回新的 Point3DCollectionAnimation(); } 公共覆盖类型 TargetPropertyType { 得到{返回类型(Point3DCollection); } } 静态 Point3DCollectionAnimation() { FromProperty = DependencyProperty.Register("From", typeof(Point3DCollection), typeof(Point3DCollectionAnimation)); ToProperty = DependencyProperty.Register("To", typeof(Point3DCollection), typeof(Point3DCollectionAnimation)); } 公共静态只读 DependencyProperty FromProperty; 公共 Point3DCollection 来自 { 得到 { 返回 (Point3DCollection)GetValue(Point3DCollectionAnimation.FromProperty); } 放 { SetValue(Point3DCollectionAnimation.FromProperty, value); } } 公共静态只读 DependencyProperty ToProperty; 公共 Point3DCollection 到 { 得到 { 返回(Point3DCollection)GetValue(Point3DCollectionAnimation.ToProperty); } 放 { SetValue(Point3DCollectionAnimation.ToProperty, value); } } 公共覆盖对象GetCurrentValue(对象defaultOriginValue, 对象 defaultDestinationValue, AnimationClock animationClock) { Point3DCollection fromVal = ((Point3DCollection)GetValue(Point3DCollectionAnimation.FromProperty)); Point3DCollection toVal = ((Point3DCollection)GetValue(Point3DCollectionAnimation.ToProperty)); Point3DCollection ret; 诠释 t = 0; if (fromVal.Count > toVal.Count) { ret = fromVal.Clone(); foreach(toVal 中的 Point3D tov) { 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++; } } 别的 { 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++; } } 返回 ret; } } }

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

    请离开cmets。

    【讨论】:

      【解决方案2】:

      我发现了问题。视觉画笔不可冻结。为了让代码工作,我需要找到一种方法来冻结画笔。

      【讨论】:

        【解决方案3】:

        Aaron,我使用了您的 BrushAnimation 类,如上所示,它可以满足我的特定需求。但是,我注意到 StackOverflow 在知识共享许可下运行。因此,未经您的许可,从技术上讲,我不能在我的商业应用程序中使用该类(我不想根据知识共享许可)。你愿意给我许可吗?我仍然可以相信你的工作。

        我找不到任何其他方式与您联系,因为我还不能制作 cmets。

        【讨论】:

        • 是的,如果您愿意,您可以使用该课程。如果你给我一些荣誉会很好,但不一定。
        • 太棒了!谢谢。我会在计划中的适当位置给予奖励。
        【解决方案4】:

        只要您在前画笔中有透明像素,上述方法就应该有效。如果不是,前刷只会覆盖后刷。你应该提供一个更完整的例子来看看实际发生了什么。

        【讨论】:

        • 糟糕,我忘了提。为了制作动画,我会定期更改前刷的不透明度。动画开始时为 0,结束为 1。所以最后会覆盖背刷。它的问题是生成的画笔是完全透明的。
        • 也许你不小心设置了 VisualBrush "VB" 的透明度。用一个不完整的例子真的很难说出哪里出了问题。
        • 我添加了完整的课程。再看一遍。
        • btw: toVal.GetType() == typeof(SpecularMaterial) 无需创建实例来比较类型
        • 我不明白。似乎您的动画除了为材料的不透明度设置动画外什么都不做。您不必编写额外的类来在 XAML 中实现此目的。您可以非常轻松地在 XAML(或 C#)中为材质属性设置动画。对于 Material.Opacity,您只需使用 DoubleAnimation
        【解决方案5】:

        您可以使用视觉笔刷来实现这一点

        <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>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多