VisualBrush可视画刷

  • PaintingWithVisualBrush

clipboard.png
关键词:

  1. VisualBrush.Visual

实现效果:

  1. 背景色半透明、包含渐变文本、平铺效果

使用包含文本TextBlock的边框Border作为可视画刷VisualBrush,使用平铺、透明效果填充容器的背景色。

<StackPanel.Background>
  <VisualBrush Opacity="0.1" Viewport="0,0,250,30" ViewportUnits="Absolute" TileMode="Tile" Stretch="None">
    <VisualBrush.Visual>
      <Border Width="250" Background="Transparent">
        <TextBlock Margin="5" FontFamily="Palatino Linotype" FontSize="20px" >
          Painting with VisualBrush
          <TextBlock.Foreground>
            <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
              <LinearGradientBrush.GradientStops>
                <GradientStop Offset="0.0" Color="Black" />
                <GradientStop Offset="1.0" Color="Blue" />
              </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
          </TextBlock.Foreground>
        </TextBlock>
      </Border>
    </VisualBrush.Visual>
    <VisualBrush.RelativeTransform>
      <RotateTransform Angle="0" CenterX="1.5" CenterY="0.5" />
    </VisualBrush.RelativeTransform>
  </VisualBrush>
</StackPanel.Background>
  1. 同理下3 图案也是使用包含方框、文本、按钮的StackPanel容器作为Visual,设置为VisualBrush的属性值,进行方框的Fill填充。期间利用VisualBrush的Viewport、TileMode属性设置画刷图块的样式。
<Rectangle Width="150" Height="150" Stroke="Black" Margin="5,0,0,0">
    <Rectangle.Fill>
      <VisualBrush Viewport="0,0,50,50" ViewportUnits="Absolute" TileMode="Tile">
        <VisualBrush.Visual>
          <StackPanel Background="Transparent">
            <Rectangle Width="25" Height="25" Fill="Red" Margin="2" />
            <TextBlock FontSize="10pt" Margin="2">Hello, World!</TextBlock>
            <Button Margin="2">A Button</Button>
          </StackPanel>
        </VisualBrush.Visual>
        <VisualBrush.RelativeTransform>
          <RotateTransform Angle="45" CenterX="0.5" CenterY="0.5" />
        </VisualBrush.RelativeTransform>
      </VisualBrush>
    </Rectangle.Fill>
  </Rectangle>
  • MagnifyingGlass放大镜

clipboard.png

代码中一个注意细节为:

clipboard.png
关注点:

  1. Canvas--Ellipse.Fill-DrawingBrush--DrawingGroup--GeometryDrawing-GeometryDrawing.Brush-VisualBrush-Visual绑定
  2. GeometryDrawing.Geometry-RectangleGeometry-Rect

放大镜区域代码:

<!-- This canvas contains the magnifying glass. -->
<Canvas Name="magnifyingGlassCanvas" >
  
  <!-- The magnifying glass. -->
  <Ellipse Name="magnifyingGlassEllipse" Width="100" Height="100" Stroke="Black">
    <Ellipse.Fill>
      <DrawingBrush>
        <DrawingBrush.Drawing>
          <DrawingGroup>
            <DrawingGroup.Children>
            
              <!-- This GeometryDrawing provides an opaque background for the 
                   magnified view. -->
              <GeometryDrawing Brush="White">
                <GeometryDrawing.Geometry>
                  <RectangleGeometry Rect="0,0,1,1" />
                </GeometryDrawing.Geometry>
              </GeometryDrawing>
              
              <!-- The magnified view. -->
              <GeometryDrawing>
                <GeometryDrawing.Brush>
                
                  <!-- This VisualBrush magnifies its content. -->
                  <VisualBrush x:Name="myVisualBrush" ViewboxUnits="Absolute"
                    Visual="{Binding ElementName=magnifiedPanel}"/>
                </GeometryDrawing.Brush>
                <GeometryDrawing.Geometry>
                  <RectangleGeometry Rect="0,0,1,1" />
                </GeometryDrawing.Geometry>
              </GeometryDrawing>
            </DrawingGroup.Children>
          </DrawingGroup>
        </DrawingBrush.Drawing>
      </DrawingBrush>
    </Ellipse.Fill>
  </Ellipse>
</Canvas>

后台代码:

  1. 设置鼠标为十字Cursors.Cross,获取当前移动鼠标的坐标
  2. 判断上下左右边界的可放大区域

    1. 若鼠标靠近右边界,放大镜大小不能处于右边界外,设计放于鼠标左边。同理下边界同处理。
  3. 设置放大镜圆框的viewbox放大倍数为viewbox的Rect区域大小2020填充到100100的输出区域的放大比例
public partial class MagnifyingGlassExample : Page
{
    private static readonly double DistanceFromMouse = 5;

    private void UpdateMagnifyingGlass(object sender, MouseEventArgs args)
    {
        Mouse.SetCursor(Cursors.Cross);

        // Get the current position of the mouse pointer.
        var currentMousePosition = args.GetPosition(this);

        // Determine whether the magnifying glass should be shown to the
        // the left or right of the mouse pointer.
        if (ActualWidth - currentMousePosition.X > magnifyingGlassEllipse.Width + DistanceFromMouse)
        {
            Canvas.SetLeft(magnifyingGlassEllipse, currentMousePosition.X + DistanceFromMouse);
        }
        else
        {
            Canvas.SetLeft(magnifyingGlassEllipse,
                currentMousePosition.X - DistanceFromMouse - magnifyingGlassEllipse.Width);
        }

        // Determine whether the magnifying glass should be shown 
        // above or below the mouse pointer.
        if (ActualHeight - currentMousePosition.Y > magnifyingGlassEllipse.Height + DistanceFromMouse)
        {
            Canvas.SetTop(magnifyingGlassEllipse, currentMousePosition.Y + DistanceFromMouse);
        }
        else
        {
            Canvas.SetTop(magnifyingGlassEllipse,
                currentMousePosition.Y - DistanceFromMouse - magnifyingGlassEllipse.Height);
        }


        // Update the visual brush's Viewbox to magnify a 20 by 20 rectangle,
        // centered on the current mouse position.
        myVisualBrush.Viewbox =
            new Rect(currentMousePosition.X - 10, currentMousePosition.Y - 10, 20, 20);
    }
}

扩展:

    1. ActualWidth/Higth以Frame的边界为准好。
    2. 边缘的透明区域也需设置白色底色,在放大镜区域里再加个GeometryDrawing-RectangleGeometry即可。
    3. 放大镜区域最上层GeometryDrawing.Geometry设置为RectangleGeometry,其他若是几何圆不行。
    • ReflectionExample镜像反射

    clipboard.png
    实现效果:

    1. 镜面反射一个动画的Visual元素,如球的起落移动

    关键词:

    1. 镜面反射的各个细节考虑
    <EventTrigger RoutedEvent="Page.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation Storyboard.TargetName="bouncingBall" Storyboard.TargetProperty="(Canvas.Top)"
            From="0" To="250" Duration="0:0:3" RepeatBehavior="Forever" AutoReverse="True"
            AccelerationRatio="1.0" />
          <DoubleAnimation Storyboard.TargetName="bouncingBall" Storyboard.TargetProperty="(Canvas.Left)"
            From="0" To="350" Duration="0:0:20" RepeatBehavior="Forever" AutoReverse="True"
            AccelerationRatio="1.0" />           
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
      
      </Page.Triggers>

    反射效果:

    1. 容器为Canvas,其宽高绑定源Canvas的宽高
    2. Canvas的背景色设置为VisualBrush,Brush.Visual绑定为镜像源元素。
    3. 设置镜像的Y轴倒转,通过使用ScaleTransform.ScaleY,设置向下平移一个身位,使用TranslateTransform.
    4. 同时设置透明度的渐变。

    扩展:

    1. 实现思路灵活,简单有效

    李志玮
    22 声望34 粉丝

    求索~~


    引用和评论

    0 条评论