0

任何人都知道如何解决这个问题?

我没有任何代码可以展示,因为我不知道从哪里开始,这就是我发布这个的原因。

我的计划是在带有隐藏背景图像的 WPF App WrapWindow 上动态加载大约 7000 个单词的字符串数组。文本应该是透明的以暴露后面的图像(类似于标签云)。我已附上示例的链接,这将帮助您可视化问题。

我曾尝试使用 ImageBrush,但它不支持直接内容(即字符串)。我也尝试过使用不透明蒙版,但没有任何成功。

为了给你一个想法,下面是图片和链接到类似的未回答的主题,但我试图达到的效果。

不透明背景的透明文本

在此处输入图像描述

欢迎任何想法。

谢谢

好的,这就是我目前所拥有的,也是我能够用单个硬编码字符串实现的。

简单的 xaml、图像作为背景和 WrapPanel,它由 TEST STRING 以按钮的形式动态填充。

<Grid>
   <Image Source="/Images/test.jpg" Stretch="Fill"/>
   <WrapPanel x:Name="WrapPan"/>
</Grid>

只是背后代码的草稿副本。

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            LoadData();
        }

        string[] test = { "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",
        "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING", "TEST STRING",};

        private void LoadData()
        {
            for (int i = 0; i < test.Length; i++)
            {
                Button BtnWithName = new Button
                {
                    Style = (Style)FindResource("MaterialDesignFlatButton"),
                    Content = test[i].ToString(),
                    Padding = new Thickness(0, 0, 5, 0),
                    Height = 12,
                    Command = DialogHost.OpenDialogCommand,
                    FontSize = 10,
                    Foreground = Brushes.White,
                    Opacity = 1,
                    FontFamily = new FontFamily("Arial Black"),
                    ToolTip = test[i].ToString(),

                };

                Button BtnClose = new Button
                {
                    Content = "Close",
                    Command = DialogHost.CloseDialogCommand,
                    Width = 100
                };

                Grid myGrid = new Grid();
                myGrid.Height = 200;
                myGrid.Width = 200;

                RowDefinition gridRow1 = new RowDefinition();
                RowDefinition gridRow2 = new RowDefinition();

                myGrid.RowDefinitions.Add(gridRow1);
                myGrid.RowDefinitions.Add(gridRow2);

                TextBlock textBlock = new TextBlock();
                textBlock.HorizontalAlignment = HorizontalAlignment.Center;
                textBlock.Text = test[i].ToString();

                StackPanel sp = new StackPanel();
                sp.HorizontalAlignment = HorizontalAlignment.Center;
                sp.Children.Add(textBlock);
                myGrid.Children.Add(sp);
                Grid.SetRow(sp, 0);

                myGrid.Children.Add(BtnClose);
                Grid.SetRow(BtnClose, 1);

                myGrid.VerticalAlignment = VerticalAlignment.Center;


                BtnWithName.CommandParameter = myGrid;
                WrapPan.Children.Add(BtnWithName);

            }
        }   
    }

这给了我下面的输出:

在此处输入图像描述

然后,经过一些实验,我资助了将 VisulaBrush 设置为 TextBlock 的方式应用图像不透明蒙版,这给了我想要的效果。现在的问题仍然是我将如何使用字符串数组动态地做与上面相同的事情,但效果如下?

       <Image Source="/Images/test.jpg" Stretch="Fill">
            <Image.Effect>
                <BlurEffect Radius="0"/>
            </Image.Effect>
            <Image.OpacityMask>
                <VisualBrush>
                    <VisualBrush.Visual >
                        <TextBlock Text="test" />
                    </VisualBrush.Visual>
                </VisualBrush>
            </Image.OpacityMask>
        </Image>

在此处输入图像描述

BrushVisual 只能有一个 Item,所以我将 WrapPanel 放在 MaterialDesign DialogHost 中。我现在可以用我的字符串填充 WrapPanel。我现在遇到的问题是,无论我做什么,我都无法控制按钮上的文本大小,而且当我调整窗口大小时,我放置的按钮越多,图像就会被扭曲和挤压(下图)并拉伸或压缩。

<Image Source="/Images/test.jpg" Stretch="Fill">
    <Image.Effect>
        <BlurEffect Radius="0"/>
    </Image.Effect>
   <Image.OpacityMask>
        <VisualBrush >
            <VisualBrush.Visual>
                <materialDesign:DialogHost>
                    <WrapPanel  x:Name="WrapPan"/>
                </materialDesign:DialogHost>
            </VisualBrush.Visual>
        </VisualBrush>
    </Image.OpacityMask> 
</Image>

在此处输入图像描述

4

1 回答 1

0

您可以使用文本轮廓的几何形状剪辑画布。这是一个将文本概述为形状的类。

public class OutlinedText : Shape
{
    public static readonly DependencyProperty TextProperty =
       DependencyProperty.Register(
       "Text",
       typeof(string),
       typeof(OutlinedText));

    private Geometry testGeometry;

    public OutlinedText()
    {
        FontFamily = new FontFamily("Arial");
        FontWeight = FontWeights.ExtraBold;
        FontStyle = FontStyles.Normal;
        this.FontSize = 14;
    }

    public FontFamily FontFamily { get; set; }

    public int FontSize { get; set; }

    public FontStyle FontStyle { get; set; }

    public FontWeight FontWeight { get; set; }

    public Point Origin { get; private set; }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { this.SetValue(TextProperty, value); }
    }

    protected override Geometry DefiningGeometry => this.testGeometry ?? Geometry.Empty;

    public static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((OutlinedText)d).CreateTextGeometry();

    protected override Size MeasureOverride(Size availableSize)
    {
        if (this.testGeometry == null)
        {
            this.CreateTextGeometry();
        }

        if (this.testGeometry.Bounds == Rect.Empty)
        {
            return new Size(0, 0);
        }

        return new Size(Math.Min(availableSize.Width, this.testGeometry.Bounds.Width), Math.Min(availableSize.Height, this.testGeometry.Bounds.Height));
    }

    private void CreateTextGeometry()
    {
        var formattedText = new FormattedText(
            this.Text,
            Thread.CurrentThread.CurrentUICulture,
            FlowDirection.LeftToRight,
            new Typeface(FontFamily, FontStyle, FontWeight, FontStretches.Normal),
            this.FontSize,
            Brushes.Black);
        this.testGeometry = formattedText.BuildGeometry(this.Origin);
    }
}

像往常一样在 xaml 中使用它

<local:OutlinedText
        Fill="Transparent"
        FontSize="16"
        Stroke="Black"
        StrokeThickness="1"
        Text="Test text"
        Visibility="Visible" />

因此,如果您有一个带有白色背景的画布,您可以使用与文本路径相反的方式对其进行剪辑。要反转剪辑,请创建一个路径,该路径将文本的路径几何与与画布尺寸相同的矩形组合在一起。使用“排除”的组合几何模式。

 <Canvas
        x:Name="canvas"
        Background="White"
        Clip="{Binding ElementName=path, Path=RenderedGeometry}" />

    <Path Name="path" Fill="White">
        <Path.Data>
            <CombinedGeometry
                Geometry1="{Binding ElementName=rect, Path=RenderedGeometry}"
                Geometry2="{Binding ElementName=ot, Path=RenderedGeometry}"
                GeometryCombineMode="Exclude" />
        </Path.Data>
    </Path>
    <local:OutlinedText
        x:Name="ot"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        Panel.ZIndex="1"
        Fill="Red"
        FontSize="16"
        Stroke="Black"
        StrokeThickness="1"
        Text="Test text"
        Visibility="Hidden" />
    <Rectangle
        x:Name="rect"
        Width="{Binding ElementName=canvas, Path=ActualWidth}"
        Height="{Binding ElementName=canvas, Path=ActualHeight}" />
于 2020-06-03T16:52:06.240 回答