繪製圖形
瞭解如何繪製圖形,例如省略號、矩形、多邊形和路徑。 Path 類別是在 XAML UI 中可視化相當複雜的向量型繪圖語言的方式;例如,您可以繪製 Bezier 曲線。
兩組類別定義 XAML UI 中的空間區域:Shape 類別和 Geometry 類別。 這些類別之間的主要差異在於 Shape 有與其相關聯的筆刷,而且可以轉譯到畫面, 而Geometry 只會定義空間區域,而且除非有助於將資訊提供給另一個UI屬性,否則不會轉譯。 您可以將 Shape 視為 UIElement,其界限是由 Geometry 所定義。 本主題主要 涵蓋Shape 類別。
Shape 類別為 Line、Ellipse、Rectangle、Polygon、Polyline 和 Path。 Path 很有趣,因為它可以定義任意幾何,而 Geometry 類別則在這裡涉及,因為這是定義 Path 部分的其中一種方式。
UWP 和 WinUI 2
重要
本文中的資訊和範例已針對使用 Windows 應用程式 SDK 和 WinUI 3 的應用程式進行優化,但通常適用於使用 WinUI 2 的 UWP 應用程式。 如需平臺特定資訊和範例,請參閱 UWP API 參考。
本節包含您在 UWP 或 WinUI 2 應用程式中使用控件所需的資訊。
這些圖形的 API 存在於 Windows.UI.Xaml.Shapes 命名空間中。
圖形的填滿和筆劃
若要讓 Shape 轉譯至應用程式畫布,您必須將 Brush 與其產生關聯。 將 Shape 的 Fill 屬性設定為您想要的 Brush。 如需筆刷的詳細資訊,請參閱 使用筆刷。
圖形也可以有 Stroke,這是在圖形周邊周圍繪製的線條。 Stroke 也需要定義其外觀的 Brush,而且應該具有 StrokeThickness 的非零值。 StrokeThickness 是定義圖形邊緣周圍周長粗細的屬性。 如果您未指定 Stroke 的 Brush 值,或將 StrokeThickness 設定為 0,則不會繪製圖形周圍的框線。
橢圓形
橢圓形是具有弧形周長的形狀。 若要建立基本的 Ellipse,請指定 Fill 的 Width、Height 以及 Brush。
下一個範例會建立寬度為 200 和 Height 為 200 的 Ellipse,並使用 SteelBlue 色彩的 SolidColorBrush 做為其 Fill。
<Ellipse Fill="SteelBlue" Height="200" Width="200" />
var ellipse1 = new Ellipse();
ellipse1.Fill = new SolidColorBrush(Colors.SteelBlue);
ellipse1.Width = 200;
ellipse1.Height = 200;
// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(ellipse1);
以下是轉譯的Ellipse。
大多數人會將這裡的 Ellipse 視為圓形,事實上您在 XAML 宣告圓形的方式正是:使用相等 Width 與 Height 的 Ellipse。
當 Ellipse 位於 UI 配置中時,其大小會假設與具有該 Width 和 Height 的矩形相同;周邊以外的區域沒有轉譯,但仍是其版面配置位置大小的一部分。
一組 6 個 Ellipse 元素是 ProgressRing 控件的控件範本的一部分,而 2 個同心 Ellipse 元素是 RadioButton 的一部分。
矩形
Rectangle 是一個四面圖案,其相反的兩側相等。 若要建立基本 Rectangle,請指定 Width、Height 和 Fill。
您可以圓角 矩形。 若要建立圓角,請指定RadiusX和RadiusY屬性的值。 這些屬性會指定橢圓形的 X 軸和 Y 軸,以定義角落的曲線。 RadiusX 允許的最大值是 Width 除以 2,RadiusY的最大允許值為 Height 除以 2。
以下範例會建立 Width 200 與 Height 100 的 Rectangle。 它的 Fill 使用 SolidColorBrush 的 Blue 值,Stroke 使用 SolidColorBrush 的 Black 值。 我們將 StrokeThickness 設成 3。 我們將RadiusX屬性設定為50,並將RadiusY屬性設定為10,以提供矩形圓角。
<Rectangle Fill="Blue"
Width="200"
Height="100"
Stroke="Black"
StrokeThickness="3"
RadiusX="50"
RadiusY="10" />
var rectangle1 = new Rectangle();
rectangle1.Fill = new SolidColorBrush(Colors.Blue);
rectangle1.Width = 200;
rectangle1.Height = 100;
rectangle1.Stroke = new SolidColorBrush(Colors.Black);
rectangle1.StrokeThickness = 3;
rectangle1.RadiusX = 50;
rectangle1.RadiusY = 10;
// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(rectangle1);
以下是轉譯的矩形。
UI 定義有一些案例,其中,而不是使用 Rectangle,框線可能更合適。 如果您打算在其他內容周圍建立矩形圖形,最好是使用 Border,因為它可以有子內容,而且會自動調整該內容的大小,而不是像 Rectangle 那樣使用固定尺寸的高度和寬度。 如果您設定 CornerRadius 屬性,Border 也可以選擇使用圓角。
另一 方面,矩形 可能是控件組合的較佳選擇。 許多控件範本中都會看到矩形圖形,因為它用來做為可設定焦點控件的「焦點Visual」部分。 每當控件處於「焦點」視覺狀態時,這個矩形就會成為可見的,在其他狀態中則是隱藏的。
Polygon
多邊形是一個圖形,其界限是由任意數目的點所定義。 界限的建立方式是將線條從一個點連接到下一個點,最後一個點連接到第一個點。 Points 屬性會定義構成界限的點集合。 在 XAML 中,您會使用逗號分隔清單來定義點。 在程式代碼後置中,您會使用 PointCollection 來定義點,並將每個個別點新增為 Point 值至集合。
您不需要明確宣告點,讓起點和終點都指定為相同的 Point 值。 Polygon 的轉譯邏輯會假設您正在定義封閉的圖形,並將終點隱含地連接到起點。
下一個範例會建立一個 Polygon,並將 4 點設定為 (10,200)
、(60,140)
、 (130,140)
和 (180,200)
。 它會使用 SolidColorBrush 的 LightBlue 值作為 Fill,且 Stroke 沒有值,因此沒有周邊外框。
<Polygon Fill="LightBlue"
Points="10,200,60,140,130,140,180,200" />
var polygon1 = new Polygon();
polygon1.Fill = new SolidColorBrush(Colors.LightBlue);
var points = new PointCollection();
points.Add(new Windows.Foundation.Point(10, 200));
points.Add(new Windows.Foundation.Point(60, 140));
points.Add(new Windows.Foundation.Point(130, 140));
points.Add(new Windows.Foundation.Point(180, 200));
polygon1.Points = points;
// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(polygon1);
以下是轉譯的多邊形。
提示
除了宣告圖形頂點以外的案例,Point 值通常用來做為 XAML 中的類型。 例如, Point 是觸控事件事件數據的一部分,因此您可以確切地知道觸控動作在座標空間中發生的位置。 如需 Point 以及如何在 XAML 或程式代碼中使用它的詳細資訊,請參閱 Point 的 API 參考主題。
線條
線條只是座標空間中兩點之間繪製的線條。 Line 會忽略 Fill 提供的任何值,因為它沒有內部空間。 針對Line,請務必指定 Stroke 和 StrokeThickness 屬性的值,否則Line將不會轉譯。
您不使用 Point 值來指定線條圖形,而是使用 X1、Y1、X2 和 Y2 的離散 Double 值。 這可啟用水平或垂直線的最小標記。 例如, <Line Stroke="Red" X2="400"/>
定義長度為 400 像素的水平線。 其他 X,Y 屬性預設為 0,因此就點而言,此 XAML 會從 (0,0)
繪製一行至 (400,0)
。 然後,如果您想要從 (0,0) 以外的某個點開始,您可以使用 TranslateTransform 來移動整個 Line。
<Line Stroke="Red" X2="400"/>
var line1 = new Line();
line1.Stroke = new SolidColorBrush(Colors.Red);
line1.X2 = 400;
// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(line1);
聚合線條
Polyline 與 Polygon 相似,因為圖形的界限是由一組點所定義,但 Polyline 中的最後一個點未連接到第一個點。
如果指定 Polyline 的 Fill,Fill 就會繪製圖形的內部空間,即使設定給 Polyline 之 Points 的起點與終點未交叉也一樣。 如果未指定 Fill,Polyline 會與指定數個個別 Line 元素的轉譯結果一樣,即連續線條的起點與終點會交叉。
如同 Polygon,Points 屬性會定義構成界限的點集合。 在 XAML 中,您會使用逗號分隔清單來定義點。 在程式代碼後置中,您可以使用 PointCollection 來定義點,並將每個個別點新增為 Point 結構至集合。
此範例會建立一個 Polyline,並將四個點設定為 (10,200)
、(60,140)
、 (130,140)
和 。(180,200)
筆劃已定義,但不是 Fill。
<Polyline Stroke="Black"
StrokeThickness="4"
Points="10,200,60,140,130,140,180,200" />
var polyline1 = new Polyline();
polyline1.Stroke = new SolidColorBrush(Colors.Black);
polyline1.StrokeThickness = 4;
var points = new PointCollection();
points.Add(new Windows.Foundation.Point(10, 200));
points.Add(new Windows.Foundation.Point(60, 140));
points.Add(new Windows.Foundation.Point(130, 140));
points.Add(new Windows.Foundation.Point(180, 200));
polyline1.Points = points;
// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot>
layoutRoot.Children.Add(polyline1);
以下是轉譯的 Polyline。 請注意,第一個和最後一個點不會由 Stroke 外框連接,因為它們位於 Polygon 中。
路徑
Path 是最多用途的Shape,因為您可以使用它來定義任意幾何。 但隨著這種多功能性,複雜度也隨之而來。 現在讓我們看看如何在 XAML 中建立基本 路徑 。
您可以使用 Data 屬性定義路徑的幾何。 設定資料有兩種技術:
- 您可以在 XAML 中設定 Data 的字串值。 在此表單中 ,Path.Data 值會取用圖形的串行化格式。 您通常不會在第一次建立此值之後,以字串形式文字編輯此值。 相反地,您會使用設計工具,讓您能夠在介面上設計或繪製隱喻。 然後儲存或匯出輸出,這會提供具有 Path.Data 資訊的 XAML 檔案或 XAML 字串片段。
- 您可以將 Data 屬性設定為單一 Geometry 物件。 這可以在程式代碼或 XAML 中完成。 該單一 Geometry 通常是 GeometryGroup,做為容器,可以針對物件模型的目的,將多個幾何定義複合成單一物件。 這樣做最常見的原因是您想要使用一或多個曲線和複雜圖形,這些圖形可以定義為PathFigure的Segment值,例如BezierSegment。
此範例顯示路徑,可能是使用 Blend for Visual Studio 產生一些向量圖形,然後將結果儲存為 XAML。 Path 總計是由 Bezier 曲線線段和線條線段所組成。 此範例主要是為了提供一些範例,說明 Path.Data 串行化格式中有哪些元素存在,以及數位代表的內容。
此 資料 會以 「M」 表示的 move 命令開始,該命令會建立路徑的絕對起點。
第一個線段是一個三次方貝塞爾曲線,其開頭 (100,200)
為 ,並以 (400,175)
兩個控制點 (100,25)
和 (400,350)
來繪製。 此區段是由 Data 屬性字串中的 「C」 命令表示。
第二個區段的開頭是絕對水平線命令 「H」,它會指定從前一個子路徑端點 (400,175)
繪製到新端點 (280,175)
的線條。 因為它是水平線命令,所以指定的值是 x 座標。
<Path Stroke="DarkGoldenRod"
StrokeThickness="3"
Data="M 100,200 C 100,25 400,350 400,175 H 280" />
以下是轉譯 的路徑。
下一個範例示範我們討論的其他技術用法:具有PathGeometry的GeometryGroup。 此範例會練習一些可做為 PathGeometry 一部分的參與幾何類型:PathFigure,以及 PathFigure.Segment 中可以是區段的各種元素。
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<GeometryGroup>
<RectangleGeometry Rect="50,5 100,10" />
<RectangleGeometry Rect="5,5 95,180" />
<EllipseGeometry Center="100, 100" RadiusX="20" RadiusY="30"/>
<RectangleGeometry Rect="50,175 100,10" />
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure IsClosed="true" StartPoint="50,50">
<PathFigure.Segments>
<PathSegmentCollection>
<BezierSegment Point1="75,300" Point2="125,100" Point3="150,50"/>
<BezierSegment Point1="125,300" Point2="75,100" Point3="50,50"/>
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</GeometryGroup>
</Path.Data>
</Path>
var path1 = new Microsoft.UI.Xaml.Shapes.Path();
path1.Fill = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 204, 204, 255));
path1.Stroke = new SolidColorBrush(Colors.Black);
path1.StrokeThickness = 1;
var geometryGroup1 = new GeometryGroup();
var rectangleGeometry1 = new RectangleGeometry();
rectangleGeometry1.Rect = new Rect(50, 5, 100, 10);
var rectangleGeometry2 = new RectangleGeometry();
rectangleGeometry2.Rect = new Rect(5, 5, 95, 180);
geometryGroup1.Children.Add(rectangleGeometry1);
geometryGroup1.Children.Add(rectangleGeometry2);
var ellipseGeometry1 = new EllipseGeometry();
ellipseGeometry1.Center = new Point(100, 100);
ellipseGeometry1.RadiusX = 20;
ellipseGeometry1.RadiusY = 30;
geometryGroup1.Children.Add(ellipseGeometry1);
var pathGeometry1 = new PathGeometry();
var pathFigureCollection1 = new PathFigureCollection();
var pathFigure1 = new PathFigure();
pathFigure1.IsClosed = true;
pathFigure1.StartPoint = new Windows.Foundation.Point(50, 50);
pathFigureCollection1.Add(pathFigure1);
pathGeometry1.Figures = pathFigureCollection1;
var pathSegmentCollection1 = new PathSegmentCollection();
var pathSegment1 = new BezierSegment();
pathSegment1.Point1 = new Point(75, 300);
pathSegment1.Point2 = new Point(125, 100);
pathSegment1.Point3 = new Point(150, 50);
pathSegmentCollection1.Add(pathSegment1);
var pathSegment2 = new BezierSegment();
pathSegment2.Point1 = new Point(125, 300);
pathSegment2.Point2 = new Point(75, 100);
pathSegment2.Point3 = new Point(50, 50);
pathSegmentCollection1.Add(pathSegment2);
pathFigure1.Segments = pathSegmentCollection1;
geometryGroup1.Children.Add(pathGeometry1);
path1.Data = geometryGroup1;
// When you create a XAML element in code, you have to add
// it to the XAML visual tree. This example assumes you have
// a panel named 'layoutRoot' in your XAML file, like this:
// <Grid x:Name="layoutRoot">
layoutRoot.Children.Add(path1);
以下是轉譯 的路徑。
使用 PathGeometry 可能比填入 Path.Data 字串更容易閱讀。 另一方面, Path.Data 會使用與可調整向量圖形 (SVG) 影像路徑定義相容的語法,因此它可能有助於從 SVG 移植圖形,或作為 Blend 之類的工具的輸出。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應