XAML 如何计算和显示叠加背景的结果背景色(吸管效果)

yhqotfr8  于 2022-12-07  发布在  其他
关注(0)|答案(1)|浏览(143)

我正在创建一个黑暗的主题ResourceDictionary:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="Primary" Color="#008080"/>
    <SolidColorBrush x:Key="PrimaryVariant" Color="#4DCECF"/>
    <SolidColorBrush x:Key="Secondary" Color="#B894F6"/>
    <SolidColorBrush x:Key="SecondaryVariant" Color="#9A66F4"/>

    <SolidColorBrush x:Key="Background" Color="#131313"/>
    <SolidColorBrush x:Key="Elevation1" Color="Black"/> <!--Placeholder-->
    <SolidColorBrush x:Key="Elevation2" Color="Black"/> <!--Placeholder-->
    <SolidColorBrush x:Key="Elevation3" Color="Black"/> <!--Placeholder-->
    <SolidColorBrush x:Key="Elevation4" Color="Black"/> <!--Placeholder-->

    <SolidColorBrush x:Key="OnPrimary" Color="Black"/>
    <SolidColorBrush x:Key="OnSecondary" Color="Black"/>
    <SolidColorBrush x:Key="OnBackground" Color="White"/>
</ResourceDictionary>

我正在尝试计算不同海拔的颜色十六进制代码。为此,我使用我的目标背景颜色(即#131313),然后覆盖一个部分透明的白色层。

<Grid Grid.Row="1"
          Grid.Column="2">
        <Border Background="{DynamicResource Background}"/>
        <Border Background="#0DFFFFFF"
                Style="{StaticResource ElevationStyle}">
            <TextBlock Text="5%"
                       Style="{StaticResource TextBlockStyle}"/>
        </Border>
    </Grid>

所以这里我有两个重叠的边框,一个用#131313背景填充,另一个用#0DFFFFFFF背景填充。

#131313 + #0DFFFFFF = #1F1F1F

是否有一种方法可以自动计算生成的叠加颜色,以便在将基本背景颜色从#131313更改为其他颜色时可以看到新叠加值的结果?
我也希望能够显示此值。

<Grid Grid.Row="1"
          Grid.Column="2">
        <Border Background="{DynamicResource Background}"/>
        <Border Background="#0DFFFFFF"
                Style="{StaticResource ElevationStyle}">
            <TextBlock Text="5%"
                       Style="{StaticResource TextBlockStyle}"/>
            <TextBlock Text="**<Show the hex code here>**"
                       Style="{StaticResource TextBlockStyle}"/>
        </Border>
    </Grid>

p1iqtdky

p1iqtdky1#

您可以像这样组合颜色:

public static class ColorCombiner
{
    public static Color Combine(Color source, Color added, int addedAmountPercentage)
    {
        //the Alpha channel of the added color converted to double (0-1)
        var addedTransparencyAmount = (double)added.A / 255;

        //the added amount percentage converted to double (0-1)
        var addedAmount = (double)addedAmountPercentage / 100;

        //combined alpha and amount percentage
        var amount = addedTransparencyAmount * addedAmount;

        //blend channels
        var r = BlendChannel(source.R, added.R, amount);
        var g = BlendChannel(source.G, added.G, amount);
        var b = BlendChannel(source.B, added.B, amount);

        //create resulting color
        return Color.FromRgb(r, g, b);
    }

    private static byte BlendChannel(byte source, byte added, double addedAmount)
    {
        //blend channel: if addedAmount is 0.60, use 60% of added color and 40% of source color
        var sourceAmount = 1d - addedAmount;
        var result = (source * sourceAmount) + (added * addedAmount);
        return Convert.ToByte(result);
    }
}

结果如下:

下面是演示的完整代码:
ColorCombiner.cs

using System;
using System.Windows.Media;

namespace WpfSuperimposedColors;

public static class ColorCombiner
{
    public static Color Combine(Color source, Color added, int addedAmountPercentage)
    {
        //the Alpha channel of the added color converted to double (0-1)
        var addedTransparencyAmount = (double)added.A / 255;

        //the added amount percentage converted to double (0-1)
        var addedAmount = (double)addedAmountPercentage / 100;

        //combined alpha and amount percentage
        var amount = addedTransparencyAmount * addedAmount;

        //blend channels
        var r = BlendChannel(source.R, added.R, amount);
        var g = BlendChannel(source.G, added.G, amount);
        var b = BlendChannel(source.B, added.B, amount);

        //create resulting color
        return Color.FromRgb(r, g, b);
    }

    private static byte BlendChannel(byte source, byte added, double addedAmount)
    {
        //blend channel: if addedAmount is 0.60, use 60% of added color and 40% of source color
        var sourceAmount = 1d - addedAmount;
        var result = (source * sourceAmount) + (added * addedAmount);
        return Convert.ToByte(result);
    }
}

型号

using System.Windows.Media;
using System.Collections.Generic;

namespace WpfSuperimposedColors;

public record ColoringItem(string Name, SolidColorBrush Brush, string Hex)
{
    public ColoringItem(string Name, Color Color) : this(Name, new SolidColorBrush(Color), GetHex(Color)) { }

    private static string GetHex(Color c)
    {
        if (c.A < 255)
        {
            return $"#{c.A:X2}{c.R:X2}{c.G:X2}{c.B:X2}";
        }

        return $"#{c.R:X2}{c.G:X2}{c.B:X2}";
    }
}

public record ColoringSection(ColoringItem Source, ColoringItem Added, IEnumerable<ColoringItem> Results);

MainWindow.xaml.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;

namespace WpfSuperimposedColors;
public partial class MainWindow : Window
{
    public ObservableCollection<ColoringSection> Items { get; } = new();

    public MainWindow()
    {
        InitializeComponent();

        //#2d00b3
        var primary = Color.FromRgb(45, 0, 179);
        //#2d00b3 at 50% transparency
        var primary50 = Color.FromArgb(127, 45, 0, 179);

        Items.Add(CreateDemoSection(Colors.White, "White", primary, "Primary"));
        Items.Add(CreateDemoSection(Colors.White, "White", primary50, "Half Transparent Primary"));
        Items.Add(CreateDemoSection(Colors.Black, "Black", primary, "Primary"));
        Items.Add(CreateDemoSection(Colors.Black, "Black", primary50, "Half Transparent Primary"));

        DataContext = this;
    }

    private ColoringSection CreateDemoSection(Color baseColor, string baseName, Color additionColor, string additionName)
    {
        var baseItem = new ColoringItem(baseName, baseColor);
        var additionItem = new ColoringItem(additionName, additionColor);
        var items = new List<ColoringItem>();

        for (int amountPercentage = 5; amountPercentage <= 100; amountPercentage += 5)
        {
            var color = ColorCombiner.Combine(baseColor, additionColor, amountPercentage);
            items.Add(new ColoringItem($"{amountPercentage}%", color));
        }

        return new ColoringSection(baseItem, additionItem, items);
    }
}

MainWindow.xaml

<Window
    x:Class="WpfSuperimposedColors.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:WpfSuperimposedColors"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">

    <ScrollViewer Padding="5">
        <ItemsControl ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type local:ColoringSection}">
                    <StackPanel>
                        <TextBlock Margin="5,15,5,5" FontSize="18">
                            <Run Text="{Binding Added.Name}" />
                            <Run Text="{Binding Added.Hex, StringFormat='({0})'}" />
                            <Run Text="on" />
                            <Run Text="{Binding Source.Name}" />
                            <Run Text="background" />
                        </TextBlock>

                        <WrapPanel>
                            <Border
                                Width="80"
                                Height="60"
                                Margin="5"
                                Background="{Binding Source.Brush}"
                                BorderBrush="Black"
                                BorderThickness="1" />
                            <Border
                                Width="80"
                                Height="60"
                                Margin="5"
                                Background="{Binding Added.Brush}"
                                BorderBrush="Black"
                                BorderThickness="1" />
                        </WrapPanel>

                        <ItemsControl Margin="5" ItemsSource="{Binding Results}">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Border
                                        Width="80"
                                        Height="60"
                                        Background="{Binding Brush}">
                                        <Border
                                            Padding="5"
                                            HorizontalAlignment="Center"
                                            VerticalAlignment="Center"
                                            Background="#20000000"
                                            CornerRadius="5">
                                            <StackPanel>
                                                <TextBlock
                                                    Foreground="#fff"
                                                    Text="{Binding Name}"
                                                    TextAlignment="Center"
                                                    TextWrapping="Wrap" />
                                                <TextBlock
                                                    Foreground="#fff"
                                                    Text="{Binding Hex}"
                                                    TextAlignment="Center"
                                                    TextWrapping="Wrap" />
                                            </StackPanel>
                                        </Border>
                                    </Border>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</Window>
    • 编辑**

我已经为这个任务整合了一个小的颜色混合库,它被称为DarkColors
以下是它的功能:

相关问题