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>

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


    李志玮
    22 声望34 粉丝

    求索~~


    引用和评论

    0 条评论