11.WPF绘图

11.绘图

WPF基本的图形包括:

  • Line,直线段
  • Rectangle,矩形
  • Ellipse,椭圆
  • Polygon,多边形,由多条直线段围成的闭合区域
  • Polylin,折线,不闭合
  • Path,路径,闭合区域,基本图形中功能最强大的一个,可由直线、圆弧、贝塞尔曲线组成

绘图不一定要在Canvas中完成,可以再任何一种布局中完成。

基本图形

Line

X1,Y1作为起点,X2,Y2作为终点。Stroke(边线)属性的数据类型是Brush,用来填充。

<Window x:Class="WpfApplication1.Window45"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window45" Height="293" Width="437">
    <Grid>
        <Line X1="10" Y1="20" X2="260" Y2="20" Stroke="Red" StrokeThickness="10"></Line>
        <Line X1="10" Y1="40" X2="260" Y2="40" Stroke="Orange" StrokeThickness="6"></Line>
        <Line X1="10" Y1="60" X2="260" Y2="60" Stroke="Green" StrokeThickness="3"></Line>
        <Line X1="10" Y1="80" X2="260" Y2="80" Stroke="Purple" StrokeThickness="2"></Line>
        <Line X1="10" Y1="100" X2="260" Y2="100" Stroke="Black" StrokeThickness="1"></Line>
        <Line X1="10" Y1="120" X2="260" Y2="120" StrokeDashArray="3" Stroke="Black" StrokeThickness="1"></Line>
        <Line X1="10" Y1="140" X2="260" Y2="140" StrokeDashArray="5" Stroke="Black" StrokeThickness="1"></Line>
        <Line X1="10" X2="260" Y1="160" Y2="160" Stroke="Black" StrokeThickness="6" StrokeEndLineCap="Flat"></Line>
        <Line X1="10" X2="260" Y1="180" Y2="180" Stroke="Black" StrokeThickness="8" StrokeEndLineCap="Triangle"></Line>
        <Line X1="10" X2="260" Y1="200" Y2="200" StrokeEndLineCap="Round" StrokeThickness="10">
            <Line.Stroke>
                <LinearGradientBrush EndPoint="0,0.5" StartPoint="1,0.5">
                    <GradientStop Color="Blue"></GradientStop>
                    <GradientStop Offset="1" Color="Red"></GradientStop>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
    </Grid>
</Window>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dv5lBODs-1668244504880)(C:\Users\cni23287938\AppData\Roaming\Typora\typora-user-images\image-20221111151636222.png)]

Rectangle

矩形由Stroke(边线)和Fill(填充)构成。数据类型均为Brush,常见的Brush子类有:

  • SolidColorBrush:实心画刷,常用Red、Blue等字符串赋值
  • LinearGradientBrush:线性渐变画刷
  • RadialGradentBrush:径向渐变画刷
  • ImageBrush:图片作为内容
  • DrawingBrush:矢量图或者位图填充
  • VisualBrush:每个控件的可视化形象可以通过Visual类的方法获得,并用该形象进行填充,这就是VisualBrush。如:控件被拖拽过程中显示一个幻影,这个幻影就可以使用VisualBrush来填充。
<Window x:Class="WpfApplication1.Window46"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window46" Height="390" Width="600">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="180" />
            <ColumnDefinition Width="10" />
            <ColumnDefinition Width="180" />
            <ColumnDefinition Width="10" />
            <ColumnDefinition Width="180*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="160" />
            <RowDefinition Height="10" />
            <RowDefinition Height="160" />
        </Grid.RowDefinitions>
        <!--实心填充-->
        <Rectangle Grid.Row="0" Grid.Column="0" Stroke="Black" Fill="LightBlue"></Rectangle>
        <!--线性渐变-->
        <Rectangle Grid.Row="0" Grid.Column="2">
            <Rectangle.Fill>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="#FFB6F8F1" Offset="0"></GradientStop>
                    <GradientStop Color="#FF0082BD" Offset="0.25"></GradientStop>
                    <GradientStop Color="#FF95DEFF" Offset="0.6"></GradientStop>
                    <GradientStop Color="#FF004F72" Offset="1"></GradientStop>
                </LinearGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <!--径向渐变-->
        <Rectangle Grid.Row="0" Grid.Column="4">
            <Rectangle.Fill>
                <RadialGradientBrush>
                    <GradientStop Color="#FFB6F8F1" Offset="0"></GradientStop>
                    <GradientStop Color="#FF0082BD" Offset="0.25"></GradientStop>
                    <GradientStop Color="#FF95DEFF" Offset="0.75"></GradientStop>
                    <GradientStop Color="#FF004F72" Offset="1.5"></GradientStop>
                </RadialGradientBrush>
            </Rectangle.Fill>
        </Rectangle>
        <!--图片填充-->
        <Rectangle Grid.Row="2" Grid.Column="0">
            <Rectangle.Fill>
                <ImageBrush ImageSource="./01077_1.png" Viewport="0,0,0.3,0.3" TileMode="Tile">
                    
                </ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
        <!--矢量图-->
        <Rectangle Grid.Row="2" Grid.Column="2">
            <Rectangle.Fill>
                <DrawingBrush Viewport="0,0,0.2,0.2" TileMode="Tile">
                    <DrawingBrush.Drawing>
                        <GeometryDrawing Brush="LightBlue">
                            <GeometryDrawing.Geometry>
                                <EllipseGeometry RadiusX="10" RadiusY="10"></EllipseGeometry>
                            </GeometryDrawing.Geometry>
                        </GeometryDrawing>
                    </DrawingBrush.Drawing>
                </DrawingBrush>
            </Rectangle.Fill>
        </Rectangle>
        <!--无填充,使用线性渐变填充边框-->
        <Rectangle Grid.Row="2" Grid.Column="5" StrokeThickness="10">
            <Rectangle.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="White" Offset="0.3"></GradientStop>
                    <GradientStop Color="Blue" Offset="1"></GradientStop>
                </LinearGradientBrush>
            </Rectangle.Stroke>
        </Rectangle>
    </Grid>
</Window>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-acj40m9h-1668244504881)(11.绘图.assets/image-20221111153230825.png)]

使用visualBrush的案例

<Grid Margin="10">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="160" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="160" />
    </Grid.ColumnDefinitions>
    <StackPanel Background="White" x:Name="spleft">
        <Button Height="40" Content="OK" x:Name="btnReal" Click="btnReal_Click"></Button>
    </StackPanel>
    <Button Grid.Column="1" Content=">>" Margin="5,0"></Button>
    <StackPanel Grid.Column="2" Background="White" x:Name="spRight">
    </StackPanel>
</Grid>
double o = 1;//不透明度指数
private void btnReal_Click(object sender, RoutedEventArgs e)
{
    VisualBrush vb = new VisualBrush(this.btnReal);
    Rectangle rtg = new Rectangle();
    rtg.Width = btnReal.Width;
    rtg.Height = btnReal.Height;
    rtg.Fill = vb;
    rtg.Opacity = o;
    o -= 0.2;
    this.spRight.Children.Add(rtg);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fuS3Exaf-1668244504881)(11.绘图.assets/image-20221111154534841.png)]

Ellipse

<Grid>
    <Ellipse Height="140"  Name="ellipse1" Stroke="Gray" Width="140" Cursor="Hand" ToolTip="A Ball">
        <Ellipse.Fill>
            <RadialGradientBrush GradientOrigin="0.2,0.8" RadiusX="0.75" RadiusY="0.75">
                <RadialGradientBrush.RelativeTransform>
                    <TransformGroup>
                        <RotateTransform Angle="90" CenterX="0.5" CenterY="0.5"></RotateTransform>
                    </TransformGroup>
                </RadialGradientBrush.RelativeTransform>
                <GradientStop Color="#FFFFFFFF" Offset="0" />
                <GradientStop Color="#FF444444" Offset="0.66" />
                <GradientStop Color="#FF999999" Offset="1" />
            </RadialGradientBrush>
        </Ellipse.Fill>
    </Ellipse>
</Grid>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-peioLCuy-1668244504882)(11.绘图.assets/image-20221111154656159.png)]

Path

路径可以替代其他几种图形,并且可以将直线、圆弧等基本元素结合形成复杂的图形。Path最重要的属性是Data,其数据类型为Geometry抽象类。Geometry子类包括:

  • LineGeometry:直线几何
  • RectangleGeometry:矩形几何
  • EllipseGeometry:椭圆几何
  • PathGeometry:路径几何
  • StreamGeometry:PathGeometry的轻量替代类,不支持Binding、动画等
  • CombinedGeometry:多个基本图形的组合,形成一个几何图形
  • GeometryGroup:多个基本图形的组合,形成一个几何图形组

与Line、Rectangle等的区别:Line等可以独立存在,而Geometry只能结合其他几何,不能独立存在。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="160" />
        <RowDefinition Height="160" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="160" />
        <ColumnDefinition Width="160" />
    </Grid.ColumnDefinitions>
    <!--直线-->
    <Path Stroke="Blue" StrokeThickness="2" Grid.Row="0" Grid.Column="0">
        <Path.Data>
            <LineGeometry StartPoint="0,0" EndPoint="160,160"></LineGeometry>
        </Path.Data>
    </Path>
    <!--矩形路径-->
    <Path Stroke="Orange" Fill="Yellow" Grid.Row="0" Grid.Column="1">
        <Path.Data>
            <RectangleGeometry Rect="20,20,120,120" RadiusX="10" RadiusY="10"></RectangleGeometry>
        </Path.Data>
    </Path>
    <!--椭圆路径-->
    <Path Stroke="Green" Fill="LawnGreen" Grid.Column="0" Grid.Row="1">
        <Path.Data>
            <EllipseGeometry Center="80,80" RadiusX="60" RadiusY="40"></EllipseGeometry>
        </Path.Data>
    </Path>
    <!--自定义路径-->
    <Path Stroke="Yellow" Fill="Orange" Grid.Row="1" Grid.Column="1">
        <Path.Data>
            <PathGeometry>
 <!--Path.Figures属性可以容纳Figuress对象,PathFigure的Segments属性可以容纳各种线段用于形复杂的图形-->
                <PathGeometry.Figures>
                    <PathFigure StartPoint="25,140" IsClosed="True">
                        <PathFigure.Segments>
                            <LineSegment Point="20,40"></LineSegment>
                            <LineSegment Point="40,110"></LineSegment>
                            <LineSegment Point="50,20"></LineSegment>
                            <LineSegment Point="80,110"></LineSegment>
                            <LineSegment Point="110,20"></LineSegment>
                            <LineSegment Point="120,110"></LineSegment>
                            <LineSegment Point="140,40"></LineSegment>
                            <LineSegment Point="135,140"></LineSegment>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathGeometry.Figures>
            </PathGeometry>
        </Path.Data>
    </Path>
</Grid>

PathFigure的Segments属性所包含的线段:

  • LineSegment:直线
  • ArcSegment:圆弧
  • BezierSement:三次方贝塞尔曲线
  • QuadraticBezierSement:二次方贝塞尔曲线
  • PolyLineSegment:多直线段
  • PolyBezierSegment:多三次方贝塞尔曲线
  • PolyQuadraticBezierSement:多二次方贝塞尔曲线

注意:绘制上面的线段是没有起点的,起点就是上一个线段的终点,第一个线段的起点是PathFigure的StartPoint。

路径标记法

Path非常强大,但是上面的标签式的语法过于繁琐。WPF提供路径标记法来替代标签式语法。、

路径标记法就是各种线段的简记法,如<LineSegment Point="15,15">可以改为L, 15,15。除此之外,路径标记法还增加了一些实用的命令,如H 80,代表从当前点画一条水平直线,横坐标终点是80。

使用路径标记法的步骤分为三步移动至起点->绘图->闭合图形,常用命令如下:

命令用途语法示例标签式语法分类
M移动到起点M 起始点M 10,10移动命令
L绘制直线L 终点L 150,30绘图命令
H绘制水平直线H 终点横坐标H 180绘图命令
V绘制数值线V 终点纵坐标V 180绘图命令
A绘制圆弧A 母椭圆尺寸 旋转角度是否大弧 顺/逆 终点A 180,80 45 1 1 150,150绘图命令
C三次方贝塞尔曲线C 控制点1 控制点2 终点C 250,0 50,200 300,200绘图命令
Q二次方贝塞尔Q 控制点1 终点Q 150,100 300,200绘图命令
S平滑三次贝塞尔S 控制点2 终点S 100,200 200,300绘图命令
T平滑二次方贝塞尔T 终点T 400,200绘图命令
Z闭合图形ZM 0,0 L 40,80 L80,40 Z关闭命令

裁剪界面

不规则窗体和控件仅需使用Clip属性就可以做到。

<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
    <Path Stroke="Orange" Fill="Yellow" x:Name="clipPath0" Visibility="Hidden" Data="M 55,100 A 50,50 0 1 1 100,60 A 110,95 0 0 1 200,60 A 50,50 0 1 1 250,100 A 110,95 0 1 1 55,100 Z">
    </Path>
    <Button Content="Clip" Width="80" Height="25" Click="Button_Click" HorizontalAlignment="Center" VerticalAlignment="Center"></Button>
</Grid>
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.Clip = clipPath0.Data;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIIf142q-1668244504882)(11.绘图.assets/image-20221111165718454.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rFXmg5cL-1668244504883)(11.绘图.assets/image-20221111165800466.png)]

图形的效果与滤镜

简单易用的BitmapEffect

WPF早期的效果属性,是使用CPU来进行运算,会导致程序卡顿,不建议使用

BitmapEffect派生类:

  • BevelBitmapEffect:斜角效果
  • BitmapEffectGroup:符合效果
  • BlurBitmapEffect:模糊效果
  • DropShadowBitmapEffect:投影效果
  • EmbossBitmapEffect:浮雕效果
  • OuterGlowBitmapEffect:外发光效果
<Button Content="Click Me" Grid.Column="0" Grid.Row="0" Margin="20">
    <Button.BitmapEffect>
        <BlurBitmapEffect Radius="3"/>
    </Button.BitmapEffect>
</Button>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IAm7FxjF-1668244504883)(11.绘图.assets/image-20221112164221060.png)]

Effect

采用GPU对UI进行渲染,功能强大。

Effect具有如下派生类

  • BlurEffect:模糊效果
  • DropShadowEffect:投影效果
  • ShaderEffect:着色器(抽象类)

图形的变形

WPF中的变形与UI元素是分开的,可以单独设置一个旋转45度的变形,然后把该变形赋值给不同的UI元素。

控制变形的属性有两个:

  • RenderTransform:呈现变形
  • LayoutTransform:布局变形

这两个属性的值类型为Transform抽象类型,常见的派生类有:

  • MatrixTransform:矩阵变形
  • RotateTransform:旋转变形
  • ScaleTransform:缩放变形
  • SkewTransform:拉伸变形
  • TranslateTransform:偏移变形
  • TransformGroup:变形组

呈现变形(Render Transform)

让UI元素呈现出来的属性与本来的属性不一样,如按钮本来在左上角,但是让他呈现在右下角,且旋转45度。

<Window x:Class="WpfApplication1.Window59"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window59" Height="334" Width="485">
    <Grid Margin="10" Background="AliceBlue">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto">
            </ColumnDefinition>
            <ColumnDefinition Width="*">
            </ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto">
            </RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Button Width="80" Height="80" Content="OK" Background="Red" Foreground="White">
            <Button.RenderTransform>
                <!--复合变形-->
                <TransformGroup>
                    <!--旋转变形-->
                    <RotateTransform CenterX="40" CenterY="40" Angle="45"></RotateTransform>
                    <!--偏移变形-->
                    <TranslateTransform X="300" Y="150"></TranslateTransform>
                </TransformGroup>
            </Button.RenderTransform>
        </Button>
    </Grid>
</Window>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ynrVYjuf-1668244504884)(11.绘图.assets/image-20221112170224537.png)]

在Grid中划分了2行2列,第一行第一列根据Button自动调整,然后利用变形天正button的位置和角度,但是Button本身的位置属性却没有改变,这样仅仅改变button的显示效果会极大提高效率。所以在做动画的时候一定要用Render Transform。

布局变形

与呈现变形不同,布局变形会影响整个窗体的布局导致重新测算,所以会影响程序的性能。布局变形一般用在静态变形上。

实现文字纵向排列

  • 使用呈现变形
<Grid x:Name="titleBar" Background="LightBlue">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
        <ColumnDefinition Width="*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock FontSize="24" Text="Hello Transformer" VerticalAlignment="Bottom" HorizontalAlignment="Center">
        <TextBlock.LayoutTransform>
            <RotateTransform Angle="-90"></RotateTransform>
        </TextBlock.LayoutTransform>
    </TextBlock>
</Grid>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p3CXShVD-1668244504884)(11.绘图.assets/image-20221112170931574.png)]

看上去实现了纵向排列,但事实上TextBox本身属性没有变,所以Grid的第一列宽度任然没有变。

  • 使用布局变形

将上面的

<TextBlock.LayoutTransform>
    <RotateTransform Angle="-90"></RotateTransform>
</TextBlock.LayoutTransform>

改为

<TextBlock.LayoutTransform>
    <RotateTransform Angle="-90"></RotateTransform>
</TextBlock.LayoutTransform>

此时,Grid的第一列宽度改变。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jd0b6Tf3-1668244504884)(11.绘图.assets/image-20221112171325173.png)]

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SkiaSharp.Views.Forms.WPF 是一个用于在 WPF 应用程序中集成 SkiaSharp 的库。SkiaSharp 是一个跨平台的 2D 图形库,可以用于绘制矢量图形和处理图像。 要在 WPF 中使用 SkiaSharp.Views.Forms.WPF,需要安装以下 NuGet 包: - SkiaSharp:包含 SkiaSharp 库本身。 - SkiaSharp.Views.Forms.WPF:包含用于在 WPF 中显示 SkiaSharp 内容的控件。 首先,在你的 WPF 项目中,使用 NuGet 管理器安装这两个包。 然后,在 XAML 文件中,将 `SkiaSharp.Views.Forms.SKCanvasView` 控件添加到你的布局中: ```xml <Window x:Class="YourNamespace.YourWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:skia="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" Title="SkiaSharp in WPF" Height="450" Width="800"> <Grid> <skia:SKCanvasView PaintSurface="OnPaintSurface" /> </Grid> </Window> ``` 然后,在代码文件中,添加 `OnPaintSurface` 事件处理程序,该事件将在绘制表面时触发: ```csharp using SkiaSharp; using SkiaSharp.Views.WPF; public partial class YourWindow : Window { public YourWindow() { InitializeComponent(); } private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) { SKSurface surface = e.Surface; SKCanvas canvas = surface.Canvas; // 在这里编写绘图逻辑 canvas.Clear(SKColors.White); SKPaint paint = new SKPaint(); paint.Color = SKColors.Blue; canvas.DrawCircle(200, 200, 100, paint); } } ``` 在 `OnPaintSurface` 事件处理程序中,你可以使用 SkiaSharp 提供的 API 进行绘图操作。在这个示例中,我们使用蓝色画笔在画布上绘制了一个圆。 这样,你就可以在 WPF 应用程序中使用 SkiaSharp 绘制图形和处理图像了。运行应用程序,你将看到一个显示了绘制内容的窗口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

步、步、为营

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值