Gambar bentuk

Pelajari cara menggambar bentuk, seperti elipsis, persegi panjang, poligon, dan jalur. Kelas Jalur adalah cara untuk memvisualisasikan bahasa gambar berbasis vektor yang cukup kompleks dalam antarmuka pengguna XAML; misalnya, Anda dapat menggambar kurva Bezier.

Dua set kelas menentukan wilayah ruang di XAML UI: Kelas bentuk dan kelas Geometri. Perbedaan utama antara kelas-kelas ini adalah bahwa Bentuk memiliki kuas yang terkait dengannya dan dapat dirender ke layar, dan Geometri hanya mendefinisikan wilayah ruang dan tidak dirender kecuali membantu menyumbangkan informasi ke properti UI lain. Anda dapat menganggap Bentuk sebagai UIElement dengan batasnya yang ditentukan oleh Geometri. Topik ini mencakup terutama kelas Bentuk .

Kelas Bentuk adalah Garis, Elips, Persegi Panjang, Poligon, Poliline, dan Jalur. Jalur menarik karena dapat menentukan geometri arbitrer, dan kelas Geometri terlibat di sini karena itulah salah satu cara untuk menentukan bagian-bagian Jalur.

UWP dan WinUI 2

Penting

Informasi dan contoh dalam artikel ini dioptimalkan untuk aplikasi yang menggunakan SDK Aplikasi Windows dan WinUI 3, tetapi umumnya berlaku untuk aplikasi UWP yang menggunakan WinUI 2. Lihat referensi API UWP untuk informasi dan contoh spesifik platform.

Bagian ini berisi informasi yang Anda butuhkan untuk menggunakan kontrol di aplikasi UWP atau WinUI 2.

API untuk bentuk ini ada di namespace Windows.UI.Xaml.Shapes .

Isi dan Goresan untuk bentuk

Agar Bentuk dapat dirender ke kanvas aplikasi, Anda harus mengaitkan Brush dengannya. Atur properti Isian Bentuk ke Kuas yang Anda inginkan. Untuk informasi selengkapnya tentang kuas, lihat Menggunakan kuas.

Bentuk juga dapat memiliki Stroke, yang merupakan garis yang digambar di sekitar perimeter bentuk. Stroke juga membutuhkan Brush yang mendefinisikan penampilannya, dan harus memiliki nilai bukan nol untuk StrokeThickness. StrokeThickness adalah properti yang mendefinisikan ketebalan perimeter di sekitar tepi bentuk. Jika Anda tidak menentukan nilai Brush untuk Stroke, atau jika Anda mengatur StrokeThickness ke 0, maka batas di sekitar bentuk tidak digambar.

Ellipse

Elips adalah bentuk dengan perimeter melengkung. Untuk membuat Elips dasar, tentukan Lebar, Tinggi, dan Sikat untuk Isian.

Contoh berikutnya membuat Elips dengan Lebar 200 dan Tinggi 200, dan menggunakan SteelBlue berwarna SolidColorBrush sebagai Isiannya.

<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);

Ini Elips yang dirender.

A rendered Ellipse.

Dalam hal ini Elips adalah apa yang kebanyakan orang akan mempertimbangkan lingkaran, tetapi itulah cara Anda mendeklarasikan bentuk lingkaran di XAML: gunakan Elips dengan Lebar dan Tinggi yang sama.

Ketika Elips diposisikan dalam tata letak UI, ukurannya diasumsikan sama dengan persegi panjang dengan Lebar dan Tinggi tersebut; area di luar perimeter tidak memiliki penyajian tetapi masih merupakan bagian dari ukuran slot tata letaknya.

Satu set 6 elemen Elips adalah bagian dari templat kontrol untuk kontrol ProgressRing, dan 2 elemen Elips konsentris adalah bagian dari RadioButton.

Persegi panjang

Persegi panjang adalah bentuk empat sisi dengan sisi yang berlawanan sama. Untuk membuat Persegi Dasar, tentukan Lebar, Tinggi, dan Isian.

Anda dapat membulatkan sudut Persegi Panjang. Untuk membuat sudut bulat, tentukan nilai untuk properti RadiusX dan RadiusY. Properti ini menentukan sumbu x dan sumbu y elips yang menentukan kurva sudut. Nilai maksimum yang diizinkan dari RadiusX adalah Lebar dibagi dua dan nilai maksimum RadiusY yang diizinkan adalah Tinggi dibagi dua.

Contoh berikutnya membuat Persegi Panjang dengan Lebar 200 dan Tinggi 100. Ini menggunakan nilai Biru SolidColorBrush untuk Fill dan nilai Hitam SolidColorBrush untuk Stroke-nya. Kita atur StrokeThickness ke 3. Kami mengatur properti RadiusX ke 50 dan properti RadiusY ke 10, yang memberikan sudut bulat Persegi.

<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);

Berikut persegi panjang yang dirender.

A rendered Rectangle.

Ada beberapa skenario untuk definisi UI di mana alih-alih menggunakan Persegi Panjang, Batas mungkin lebih tepat. Jika niat Anda adalah membuat bentuk persegi panjang di sekitar konten lain, mungkin lebih baik menggunakan Batas karena dapat memiliki konten anak dan akan secara otomatis mengukur sekitar konten tersebut, daripada menggunakan dimensi tetap untuk tinggi dan lebar seperti Persegi panjang . Batas juga memiliki opsi memiliki sudut bulat jika Anda mengatur properti CornerRadius.

Di sisi lain, Persegi panjang mungkin merupakan pilihan yang lebih baik untuk komposisi kontrol. Bentuk Persegi terlihat di banyak templat kontrol karena digunakan sebagai bagian "FocusVisual" untuk kontrol yang dapat difokuskan. Setiap kali kontrol berada dalam status visual "Terfokus", persegi panjang ini dibuat terlihat, di status lain disembunyikan.

Poligon

Poligon adalah bentuk dengan batas yang ditentukan oleh jumlah titik semena-mena. Batas dibuat dengan menyambungkan garis dari satu titik ke titik berikutnya, dengan titik terakhir tersambung ke titik pertama. Properti Poin mendefinisikan kumpulan titik yang membentuk batas. Di XAML, Anda menentukan titik dengan daftar yang dipisahkan koma. Di kode-belakang Anda menggunakan PointCollection untuk menentukan titik dan Anda menambahkan setiap titik individu sebagai nilai Titik ke koleksi.

Anda tidak perlu secara eksplisit mendeklarasikan poin sehingga titik awal dan titik akhir keduanya ditentukan sebagai nilai Titik yang sama. Logika penyajian untuk Poligon mengasumsikan bahwa Anda mendefinisikan bentuk tertutup dan akan menghubungkan titik akhir ke titik awal secara implisit.

Contoh berikutnya membuat Poligon dengan 4 poin diatur ke (10,200), , (60,140)(130,140), dan (180,200). Ini menggunakan nilai LightBlue dari SolidColorBrush untuk Isinya, dan tidak memiliki nilai untuk Stroke sehingga tidak memiliki kerangka perimeter.

<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);

Berikut polygon yang dirender.

A rendered Polygon.

Tip

Nilai Titik sering digunakan sebagai jenis di XAML untuk skenario selain mendeklarasikan simpul bentuk. Misalnya, Titik adalah bagian dari data peristiwa untuk peristiwa sentuhan, sehingga Anda dapat mengetahui dengan tepat di mana dalam ruang koordinat terjadinya tindakan sentuhan. Untuk informasi selengkapnya tentang Point dan cara menggunakannya di XAML atau kode, lihat topik referensi API untuk Point.

Garis

Garis hanyalah garis yang digambar di antara dua titik dalam ruang koordinat. Garis mengabaikan nilai apa pun yang disediakan untuk Isian, karena tidak memiliki ruang interior. Untuk Baris, pastikan untuk menentukan nilai untuk properti Stroke dan StrokeThickness, karena jika tidak, Line tidak akan merender.

Anda tidak menggunakan nilai Titik untuk menentukan bentuk Garis, sebagai gantinya Anda menggunakan nilai Ganda diskrit untuk X1, Y1, X2, dan Y2. Ini memungkinkan markup minimal untuk garis horizontal atau vertikal. Misalnya, <Line Stroke="Red" X2="400"/> menentukan garis horizontal yang panjangnya 400 piksel. Properti X,Y lainnya adalah 0 secara default, jadi dalam hal titik XAML ini akan menarik garis dari (0,0) ke (400,0). Anda kemudian dapat menggunakan TranslateTransform untuk memindahkan seluruh Baris, jika Anda ingin memulainya pada titik selain (0,0).

<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

Polyline mirip dengan Poligon karena batas bentuk didefinisikan oleh sekumpulan titik, kecuali titik terakhir dalam Polyline tidak terhubung ke titik pertama.

Catatan

Anda dapat secara eksplisit memiliki titik awal dan titik akhir yang identik dalam Poin yang ditetapkan untuk Polyline, tetapi dalam hal ini Anda mungkin dapat menggunakan Poligon sebagai gantinya.

Jika Anda menentukan Isian Polyline, Isi akan melukis ruang interior bentuk, meskipun titik awal dan titik akhir titik yang ditetapkan untuk Poliline tidak bersinggungan. Jika Anda tidak menentukan Isian, maka Polyline mirip dengan apa yang akan dirender jika Anda telah menentukan beberapa elemen Baris individual di mana titik awal dan titik akhir baris berturut-turut berpotongan.

Seperti halnya Poligon, properti Poin mendefinisikan kumpulan titik yang membentuk batas. Di XAML, Anda menentukan titik dengan daftar yang dipisahkan koma. Di code-behind, Anda menggunakan PointCollection untuk menentukan titik dan Anda menambahkan setiap titik individual sebagai struktur Titik ke koleksi.

Contoh ini membuat Polyline dengan empat poin yang diatur ke (10,200), , (60,140)(130,140), dan (180,200). Stroke didefinisikan tetapi bukan Isian.

<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);

Berikut polyline yang dirender. Perhatikan bahwa poin pertama dan terakhir tidak terhubung oleh garis besar Stroke seperti yang ada di Poligon.

A rendered Polyline.

Jalur

Jalur adalah Bentuk yang paling serbaguna karena Anda dapat menggunakannya untuk menentukan geometri arbitrer. Tetapi dengan fleksibilitas ini datang kompleksitas. Sekarang mari kita lihat cara membuat Jalur dasar di XAML.

Anda menentukan geometri jalur dengan properti Data. Ada dua teknik untuk mengatur Data:

  • Anda dapat mengatur nilai string untuk Data di XAML. Dalam formulir ini, nilai Path.Data menggunakan format serialisasi untuk grafik. Anda biasanya tidak mengedit teks nilai ini dalam bentuk string setelah pertama kali dibuat. Sebagai gantinya, Anda menggunakan alat desain yang memungkinkan Anda bekerja dalam desain atau menggambar metafora di permukaan. Kemudian Anda menyimpan atau mengekspor output, dan ini memberi Anda file XAML atau fragmen string XAML dengan informasi Path.Data .
  • Anda dapat mengatur properti Data ke satu objek Geometri. Ini dapat dilakukan dalam kode atau di XAML. Geometri tunggal itu biasanya adalah GeometryGroup, yang bertindak sebagai kontainer yang dapat menggabungkan beberapa definisi geometri ke dalam satu objek untuk tujuan model objek. Alasan paling umum untuk melakukan ini adalah karena Anda ingin menggunakan satu atau beberapa kurva dan bentuk kompleks yang dapat didefinisikan sebagai nilai Segments untuk PathFigure, misalnya BezierSegment.

Contoh ini menunjukkan Jalur yang mungkin dihasilkan dari penggunaan Blend untuk Visual Studio untuk menghasilkan hanya beberapa bentuk vektor lalu menyimpan hasilnya sebagai XAML. Total Jalur terdiri dari segmen kurva Bezier dan segmen garis. Contohnya terutama dimaksudkan untuk memberi Anda beberapa contoh elemen apa yang ada dalam format serialisasi Path.Data dan apa yang diwakili angka.

Data ini dimulai dengan perintah pemindahan, yang ditunjukkan oleh "M", yang menetapkan titik awal absolut untuk jalur.

Segmen pertama adalah kurva Bezier kubik yang dimulai pada dan berakhir di (100,200) , yang digambar (400,175)dengan menggunakan dua titik (100,25) kontrol dan (400,350). Segmen ini ditunjukkan oleh perintah "C" dalam string atribut Data .

Segmen kedua dimulai dengan perintah garis horizontal absolut "H", yang menentukan garis yang digambar dari titik (400,175) akhir subpath sebelumnya ke titik (280,175)akhir baru . Karena ini adalah perintah garis horizontal, nilai yang ditentukan adalah koordinat x.

<Path Stroke="DarkGoldenRod" 
      StrokeThickness="3"
      Data="M 100,200 C 100,25 400,350 400,175 H 280" />

Inilah Jalur yang dirender.

Screenshot of a simple rendered path.

Contoh berikutnya menunjukkan penggunaan teknik lain yang kita bahas: GeometryGroup dengan PathGeometry. Contoh ini melatih beberapa jenis geometri berkontribusi yang dapat digunakan sebagai bagian dari PathGeometry: PathFigure dan berbagai elemen yang dapat menjadi segmen di PathFigure.Segments.

<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);

Inilah Jalur yang dirender.

Screenshot of a complex rendered path.

Menggunakan PathGeometry mungkin lebih mudah dibaca daripada mengisi string Path.Data. Di sisi lain, Path.Data menggunakan sintaks yang kompatibel dengan definisi jalur gambar Scalable Vector Graphics (SVG) sehingga mungkin berguna untuk porting grafis dari SVG, atau sebagai output dari alat seperti Blend.