WPF&x27;魔术';否定刷?

WPF&x27;魔术';否定刷?,wpf,brush,Wpf,Brush,我有一个渐变可以改变它的颜色,我想里面的文字应该总是可见的 如果有现成的资源,我宁愿动态地做;我想要一把“神奇画笔”,可以抵消颜色的影响 有实验吗?好吧,颜色反转可以作为位图效果来完成,但有一种更简单的方法 制作一个网格,作为3个子面板的容器,使这些子面板完全重叠: 将文本放在一个背景为透明的面板中(默认情况下是这样的)。将此面板命名为“掩码” 制作另一个名为“mainbackground”的面板,并将主渐变作为其背景。将其放在“遮罩”面板之后,以便覆盖文本 制作另一个名为“invertedfo

我有一个渐变可以改变它的颜色,我想里面的文字应该总是可见的

如果有现成的资源,我宁愿动态地做;我想要一把“神奇画笔”,可以抵消颜色的影响


有实验吗?

好吧,颜色反转可以作为位图效果来完成,但有一种更简单的方法

制作一个
网格
,作为3个子面板的容器,使这些子面板完全重叠:

将文本放在一个背景为透明的面板中(默认情况下是这样的)。将此面板命名为“掩码”

制作另一个名为“mainbackground”的面板,并将主渐变作为其背景。将其放在“遮罩”面板之后,以便覆盖文本

制作另一个名为“invertedforeground”的面板,并将其设置为相反的坡度。对于主渐变中的每个颜色值,将其设置为相反的颜色(例如,如果一种颜色为
#FF0000
,则将其设置为
#00FFFF
)。可以像设置第一个渐变的动画一样设置该渐变的动画,只是使用相反的值。然后将此面板的
OpacityMask
设置为
VisualBrush
,并将
VisualBrush
Visual
属性设置为
{Binding ElementName=mask}

<Grid>
    <Grid.Resources>
        <local:MyColorConverter x:Key="colorConverter" />
    </Grid.Resources>
    <Grid
        Name="mask">
        <TextBlock
            Name="mytext"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            FontSize="32"
            Foreground="White"
            FontWeight="Bold">Blah blah blah</TextBlock>
    </Grid>

    <Grid Name="mainbackground">
        <Grid.Background>
            <LinearGradientBrush
                ColorInterpolationMode="ScRgbLinearInterpolation"
                EndPoint="1,0">
                <GradientStop x:Name="stop1"
                    Color="#FF0000"
                    Offset="0" />
                <GradientStop x:Name="stop2"
                    Color="#00FF00"
                    Offset="0.5" />
                <GradientStop x:Name="stop3"
                    Color="#0000FF"
                    Offset="1" />
            </LinearGradientBrush>
        </Grid.Background>
    </Grid>

    <Grid Name="invertedforeground">
        <Grid.Background>
            <LinearGradientBrush
                ColorInterpolationMode="ScRgbLinearInterpolation"
                EndPoint="1,0">
                <GradientStop
                    Color="{Binding ElementName=stop1, Path=Color, Converter={StaticResource colorConverter}}"
                    Offset="0" />
                <GradientStop
                    Color="{Binding ElementName=stop2, Path=Color, Converter={StaticResource colorConverter}}"
                    Offset="0.5" />
                <GradientStop
                    Color="{Binding ElementName=stop3, Path=Color, Converter={StaticResource colorConverter}}"
                    Offset="1" />
            </LinearGradientBrush>
        </Grid.Background>
        <Grid.OpacityMask>
            <VisualBrush
                Visual="{Binding ElementName=mask}" />
        </Grid.OpacityMask>
    </Grid>
</Grid>

废话废话
您可能会使用绑定和值转换器,这样您只需要设置一个渐变的动画,而另一个只需跟随


编辑:我尝试为文本设置一个倒置的前景画笔,但它会粘在
文本块的坐标上,因此我恢复到以前的解决方案,将文本用作
不透明掩码



编辑2:我添加了自定义
IValueConverter
的示例用法,并将文本渐变颜色绑定到原始渐变颜色。您还可以在更高的位置使用绑定和转换器,例如将invertedforeground
背景
属性绑定到
Main背景
背景
属性,转换器使用输入渐变笔刷并返回不同的渐变笔刷(这使您可以创建一个与原始配置截然不同的渐变)。

Joel就如何对齐渐变笔刷给出了一个很好的答案。我想谈谈自动创建一个新渐变笔刷的复杂性,该笔刷保证可以在旧笔刷上看到

在WPF中,颜色是三维建模的,因为它需要三个数字(如R/G/B或H/S/B)定义WPF颜色,不计算alpha分量。给定的渐变填充可以被视为三维颜色空间中从一个颜色点到另一个颜色点的路径。要创建在每个点上形成对比的反向渐变,需要创建一个在任何点上都不“太接近”原始路径的附加路径。“太近”是指人眼很难分辨的任何两种颜色。这实际上是主观的。大约4%的色盲者对“太近”的理解与非色盲者不同

对于一个非色盲的人来说,如果“太近”是合理定义的,那么总会有很多路径满足标准。在这种情况下,需要额外的标准来决定哪一条路径“更好”例如,文本应该与背景形成尽可能强烈的对比,还是应该在大多数情况下具有相同的总体色调

另一方面,“太近”的保守定义考虑了每个人的颜色感知,例如“亮度必须至少相差25%”将遇到相反的问题:在每一点上满足条件的唯一梯度必须实际上是不连续的,即它必须同时从一种颜色跳到远处的颜色。例如,考虑从黑色到白色的简单梯度。如果只涉及亮度,对比背景必须有间断。否则它将在某个点匹配

基于这些原因,创建一个通用算法来产生对比背景与其说是一门科学,不如说是一门艺术。可以使用多种算法,不同的算法适用于不同的情况

用于此目的的一个简单算法是保持色调和饱和度与渐变相同,并将亮度设置为
(亮度+50%)mod 100%
。但是,在大多数情况下,该算法不会产生非常美观的结果,并且亮度变化不会超过50%。对该算法的修改是反转或移动色调和饱和度值

计算对比亮度的更简单的算法是
亮度>50%?0%:100%
。这也可能存在美学问题


这里的底线是,反转渐变颜色没有一个正确的答案。但是,如果你有一个算法可以做到这一点,那么使用Joel的不透明遮罩技术以及实现算法的绑定和IValueConverter就可以了。

你能举一个例子说明如何更改渐变颜色吗?那就是e点。我想要一个动态画笔,而不是静态画笔。你说的动态是什么意思?你在代码中指定了不同的颜色?它们作为动画的一部分会发生变化?你只是说你使用DynamicSource而不是StaticResource吗?+1用于使用不透明掩码同步渐变的布局。另外两个注意事项:1.反转画笔可以从m使用与IValueConverter rat绑定的前景笔刷