我有两把刷子。我不知道它们是什么类型的刷子。它们可以是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.
}
}
}
答案 0 :(得分:1)
我需要为画笔设置动画的原因是在我在3d对象中使用的材质中为画笔设置动画。我认为刷子的动画比材料更容易。
我已经使用上面的方法来组合画笔,但它在这里不起作用。
在思考了一下后,我决定给材料设置动画,而不是画笔。 结果比使画笔动画更容易。
[注]
此动画类适合我的需要。它只会动画材质中的画笔。我正在使用这个类替换另一个材质的画笔。
[注]
'to material'最终将完全替换'from material',它不会以MaterialGroup结束。
以下是需要它的MaterialAnimation类。我还有一个Point3DCollectionAnimation类。它可用于为3D网格设置动画。这非常有用。 你可以在这个下面找到它。
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类。
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>