WPF:Graphics--Brushes--ImageBrush图像画刷

本文介绍WPF中ImageBrush的应用技巧,包括填充形状、按钮背景等,并讲解Stretch、TileMode等属性的作用,同时演示了动画效果的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ImageBrush图像画刷

clipboard.png

clipboard.png
组织:TabItem+Frame

  • PaintingWithImages

以上图中使用了ImageBrush作为:
Filling a Shape--Ellipse.Fill
Painting a Button--Button.Background
Painting a Panel--DockPanel.Background
OutLining a Shape--Ellipes.Stroke
Painting Text--Text.Foreground
Painting a Border--Border.BorderBrush

  • Alignment 排列方式

clipboard.png

  • Stretch Modes 拉伸方式

clipboard.png

<Rectangle.Fill>
    <ImageBrush
      Stretch="Uniform" ImageSource="sampleImages\square.jpg" />
  </Rectangle.Fill>
  • TilingExample图块平铺模式

clipboard.png
TileBrush.TileMode 属性:该值指定当基本图块小于输出区域时 TileBrush 如何填充您所绘制的区域。
ViewportUnits值默认为RelativeToBoundingBox相对坐标

  1. Viewport 属性决定 TileBrush 中图块的大小和位置。 默认情况下, TileBrush 具有一个可填充整个输出区域的图块。 Stretch 属性控制 TileBrush 内容如何适合该图块。 您可以通过使用 Viewport 属性来重写此默认行为并指定图块大小。
  2. 使用 ViewportUnits 属性指定 Viewport 使用绝对坐标还是相对坐标。 如果坐标是相对的,则是相对于输出区域的大小而言。 点 (0,0) 表示输出区域的左上角,(1,1) 表示输出区域的右下角。 要指定 Viewport 属性使用绝对坐标,请将 ViewportUnits 属性设置为 Absolute。
<!-- The ImageBrush's content is flipped horizontally as it is
         tiled in this example. -->
<Rectangle Name="flipXTileRectangle" Grid.Row="3" Grid.Column="2" Width="150" Height="150" Stroke="LimeGreen" StrokeThickness="1" HorizontalAlignment="Left">
  <Rectangle.Fill>
    <ImageBrush Viewport="0,0,50,50" ViewportUnits="Absolute"  TileMode="FlipX" AlignmentX="Left" AlignmentY="Top" ImageSource="sampleImages\triangle.jpg" />
  </Rectangle.Fill>
</Rectangle>
  • TileSizeExample定义图块单元大小及填充方式

clipboard.png

clipboard.png
以上一个是修改TileMode="FlipXY"呈现效果

<!-- The ImageBrush's tiles are set to 25 by 50 pixels. -->
<Rectangle
  Grid.Row="6" Grid.Column="2"
  Width="200" Height="150"
  Stroke="LimeGreen" StrokeThickness="1" HorizontalAlignment="Left">
  <Rectangle.Fill>
    <ImageBrush
      Viewport="0,0,25,50"
      ViewportUnits="Absolute"
      TileMode="FlipXY"
      AlignmentX="Left"
      AlignmentY="Top"
      ImageSource="sampleImages\cherries_larger.jpg" />
  </Rectangle.Fill>
</Rectangle>

TileBrush.AlignmentX 属性:获取或设置 TileBrush 基本图块中内容的水平对齐。
当满足以下任一条件时将使用 TileBrush 的AlignmentX 和 AlignmentY 属性:

  1. Stretch 属性为 Uniform 或 UniformToFill,而 Viewbox 和 Viewport 的纵横比不同。
  2. Stretch 属性为 None 并且 Viewbox和 Viewport具有不同的大小。
  3. 注意,可通过使用 Viewbox 属性指定 TileBrush 内容的尺寸;可通过使用 Viewport 属性指定 TileBrush 基本图块的位置和大小。
  4. Stretch默认值为 Fill,因此上述的AlignmentX、Y在上个图片中无效。
  • TextfillsExample 文本填充ImageBrush方式

clipboard.png

上3图 :

<TextBlock Grid.Row="2" Grid.Column="2"
  FontSize="70pt" FontWeight="Bold"  FontFamily="Verdana"
  Margin="10">
  <TextBlock.Foreground>
    <ImageBrush
      Viewport="0,0,25,25" ViewportUnits="Absolute"
      TileMode="Tile"
          ImageSource="sampleImages\purpleblock.jpg" />
  </TextBlock.Foreground>
  Text
</TextBlock>

以上为在Text的输出区域中进行贴图TileMode="Tile"

  • InteractiveExample综合交互示例

clipboard.png
效果:

  1. 玻璃Radiobutton按钮+背景色Viewport、旋转的天空云彩样式
  2. 设置应用图像的内容、拉伸、图块、贴图效果的参数

关注词:

  1. ImageBrush:Stretch、AlignmentX、lignmentY、TileMode、ViewportUnits、ViewboxUnits、Viewport、Viewport
  2. Enum.GetNames()
  3. ViewPort、ScaleTransform的配合使用
  • 初始化ComboBox的值

ComboBox的值由Enum.GetNames获取的集合循环添加进去。SelectedItem由图像默认的各对应参数设定。
TextBox的值同理。

private void LoadInteractiveMenus()
{
    var values = Enum.GetNames(typeof (Stretch));
    foreach (var stretchMode in values)
        stretchSelector.Items.Add(stretchMode);
    stretchSelector.SelectedItem = myImageBrush.Stretch.ToString();
    //stretchSelector.SelectedIndex = 0;

    values = Enum.GetNames(typeof (AlignmentX));
    foreach (var hAlign in values)
        horizontalAlignmentSelector.Items.Add(hAlign);
    horizontalAlignmentSelector.SelectedItem = myImageBrush.AlignmentX.ToString();

    values = Enum.GetNames(typeof (AlignmentY));
    foreach (var vAlign in values)
        verticalAlignmentSelector.Items.Add(vAlign);
    verticalAlignmentSelector.SelectedItem = myImageBrush.AlignmentY.ToString();

    values = Enum.GetNames(typeof (TileMode));
    foreach (var tileMode in values)
        tileSelector.Items.Add(tileMode);
    tileSelector.SelectedItem = myImageBrush.TileMode.ToString();

    values = Enum.GetNames(typeof (BrushMappingMode));
    foreach (var mappingMode in values)
    {
        viewportUnitsSelector.Items.Add(mappingMode);
        viewboxUnitsSelector.Items.Add(mappingMode);
    }
    viewportUnitsSelector.SelectedItem = myImageBrush.ViewportUnits.ToString();
    viewboxUnitsSelector.SelectedItem = myImageBrush.ViewboxUnits.ToString();
    viewportEntry.Text = myImageBrush.Viewport.ToString();
    viewboxEntry.Text = myImageBrush.Viewbox.ToString();
}

当重设置ImageBrush参数后,应用选择的值:

  1. 同理枚举值由Enum.Parse()获取并赋值到图片上
  2. 文本的区域值通过RectConverter转换到对应类型
  3. 若出现转换或调用对象无效后进行异常提示。
// Applies the selected options to the image brush.
private void UpdateBrush(object sender, RoutedEventArgs args)
{
    try
    {
        myImageBrush.ImageSource = (_selectedButton.Content as Image).Source;
        myImageBrush.Stretch = (Stretch) Enum.Parse(typeof (Stretch), (string) stretchSelector.SelectedItem);
        myImageBrush.AlignmentX =
            (AlignmentX) Enum.Parse(typeof (AlignmentX), (string) horizontalAlignmentSelector.SelectedItem);
        myImageBrush.AlignmentY =
            (AlignmentY) Enum.Parse(typeof (AlignmentY), (string) verticalAlignmentSelector.SelectedItem);
        myImageBrush.TileMode = (TileMode) Enum.Parse(typeof (TileMode), (string) tileSelector.SelectedItem);
        myImageBrush.ViewportUnits =
            (BrushMappingMode)
                Enum.Parse(typeof (BrushMappingMode), (string) viewportUnitsSelector.SelectedItem);
        myImageBrush.ViewboxUnits =
            (BrushMappingMode) Enum.Parse(typeof (BrushMappingMode), (string) viewboxUnitsSelector.SelectedItem);

        var myRectConverter = new RectConverter();
        var parseString = viewportEntry.Text;

        if (!string.IsNullOrEmpty(parseString))
            myImageBrush.Viewport = (Rect) myRectConverter.ConvertFromString(parseString);
        else
        {
            myImageBrush.Viewport = Rect.Empty;
            viewportEntry.Text = "Empty";
        }

        parseString = viewboxEntry.Text;

        if (!string.IsNullOrEmpty(parseString) && parseString.ToLower() != "(auto)")
            myImageBrush.Viewbox = (Rect) myRectConverter.ConvertFromString(parseString);
        else
        {
            viewboxEntry.Text = "Empty";
            myImageBrush.Viewbox = Rect.Empty;
        }
    }
    catch (InvalidOperationException invalidOpEx)
    {
        MessageBox.Show("Invalid Viewport or Viewbox. " + invalidOpEx);
    }
    catch (FormatException formatEx)
    {
        MessageBox.Show("Invalid Viewport or Viewbox. " + formatEx);
    }
}

ps:bug:当多次点击Frame时,Page加载的方法会执行多次,导致ComboBox的值再次赋值多次。
解决方法:定义一个布尔值的是否加载标志IsFormatted,判断是否需要重新加载ComboBox的item值。

  • border背景填充蓝天白云飘动、缓慢旋转样式呈现:

    1. 针对Rectangle.Fill属性中的ImageBrush的ImageBrush.Viewport基本图块的位置和尺寸viewport值 进行RectAnimation动画
    2. 针对(Rectangle.Fill).(ImageBrush.Transform).(RotateTransform.Angle)

方框填充的画刷的转换角度值 进行动画

<Style x:Key="MyAnimatedRectangleStyle">
<Style x:Key="MyAnimatedRectangleStyle">
    <Setter Property="Rectangle.Fill">
        <Setter.Value>
            <ImageBrush ImageSource="sampleImages\purpleblock.jpg" TileMode="FlipXY" Opacity="0.25">
                <ImageBrush.Transform>
                    <RotateTransform Angle="0" />
                </ImageBrush.Transform>
            </ImageBrush>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <EventTrigger RoutedEvent="Rectangle.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard>
                    <Storyboard SpeedRatio="1.25">
                        <RectAnimation Storyboard.TargetProperty="(Rectangle.Fill).(ImageBrush.Viewport)"
      To="0,0,0.5,0.5" Duration="0:0:20" RepeatBehavior="Forever" AutoReverse="True" />
                        <DoubleAnimation 
      Storyboard.TargetProperty="(Rectangle.Fill).(ImageBrush.Transform).(RotateTransform.Angle)" 
      To="360" Duration="0:1:00" RepeatBehavior="Forever" AccelerationRatio="0.5" DecelerationRatio="0.5" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger.Actions>
        </EventTrigger>
    </Style.Triggers>
</Style>
  1. 标题中蓝色背景border效果:

使用纯色渐变呈现蓝色天空背景色

<Border Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4"  
  BorderBrush="Black" BorderThickness="6" Margin="0,0,0,10">
  <Border.Background>
    <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
      <LinearGradientBrush.GradientStops>
        <GradientStop Offset="0.0" Color="#993399FF" />
        <GradientStop Offset="1.0" Color="#996600FF" />
      </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
  </Border.Background>

以上使用数据、天空实现效果代码简单有效。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值