Skip to content

Commit 5c5dfaf

Browse files
committed
feat: SKCanvasElement sample
1 parent 87ad4c6 commit 5c5dfaf

File tree

3 files changed

+229
-0
lines changed

3 files changed

+229
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#if HAS_UNO_SKIA
2+
using SkiaSharp;
3+
using Uno.WinUI.Graphics2DSK;
4+
using Windows.Foundation;
5+
6+
namespace UnexpectedApis.Views;
7+
8+
public class SampleSKCanvasElement : SKCanvasElement
9+
{
10+
public static int SampleCount => 3;
11+
12+
public static DependencyProperty SampleProperty { get; } = DependencyProperty.Register(
13+
nameof(Sample),
14+
typeof(int),
15+
typeof(SampleSKCanvasElement),
16+
new PropertyMetadata(0, (o, args) => ((SampleSKCanvasElement)o).SampleChanged((int)args.NewValue)));
17+
18+
public int Sample
19+
{
20+
get => (int)GetValue(SampleProperty);
21+
set => SetValue(SampleProperty, value);
22+
}
23+
24+
private void SampleChanged(int newIndex)
25+
{
26+
Sample = Math.Min(Math.Max(0, newIndex), SampleCount - 1);
27+
Invalidate();
28+
}
29+
30+
protected override void RenderOverride(SKCanvas canvas, Size area)
31+
{
32+
var minDim = Math.Min(area.Width, area.Height);
33+
// draw horizontally centered
34+
var x = (area.Width - minDim) / 2;
35+
var y = (area.Height - minDim) / 2;
36+
canvas.Translate((float)x, (float)y);
37+
// rescale to fit the given area, assuming each drawing is 260x260
38+
canvas.Scale((float)(minDim / 260), (float)(minDim / 260));
39+
40+
switch (Sample)
41+
{
42+
case 0:
43+
SkiaDrawing0(canvas);
44+
break;
45+
case 1:
46+
SkiaDrawing1(canvas);
47+
break;
48+
case 2:
49+
SkiaDrawing2(canvas);
50+
break;
51+
}
52+
}
53+
54+
// https://fiddle.skia.org/c/@shapes
55+
private void SkiaDrawing0(SKCanvas canvas)
56+
{
57+
var paint = new SKPaint();
58+
paint.Style = SKPaintStyle.Fill;
59+
paint.IsAntialias = true;
60+
paint.StrokeWidth = 4;
61+
paint.Color = new SKColor(0xff4285F4);
62+
63+
var rect = SKRect.Create(10, 10, 100, 160);
64+
canvas.DrawRect(rect, paint);
65+
66+
var oval = new SKPath();
67+
oval.AddRoundRect(rect, 20, 20);
68+
oval.Offset(new SKPoint(40, 80));
69+
paint.Color = new SKColor(0xffDB4437);
70+
canvas.DrawPath(oval, paint);
71+
72+
paint.Color = new SKColor(0xff0F9D58);
73+
canvas.DrawCircle(180, 50, 25, paint);
74+
75+
rect.Offset(80, 50);
76+
paint.Color = new SKColor(0xffF4B400);
77+
paint.Style = SKPaintStyle.Stroke;
78+
canvas.DrawRoundRect(rect, 10, 10, paint);
79+
}
80+
81+
// https://fiddle.skia.org/c/@bezier_curves
82+
private void SkiaDrawing1(SKCanvas canvas)
83+
{
84+
var paint = new SKPaint();
85+
paint.Style = SKPaintStyle.Stroke;
86+
paint.StrokeWidth = 8;
87+
paint.Color = new SKColor(0xff4285F4);
88+
paint.IsAntialias = true;
89+
paint.StrokeCap = SKStrokeCap.Round;
90+
91+
var path = new SKPath();
92+
path.MoveTo(10, 10);
93+
path.QuadTo(256, 64, 128, 128);
94+
path.QuadTo(10, 192, 250, 250);
95+
canvas.DrawPath(path, paint);
96+
}
97+
98+
// https://fiddle.skia.org/c/@shader
99+
private void SkiaDrawing2(SKCanvas canvas)
100+
{
101+
var paint = new SKPaint();
102+
using var pathEffect = SKPathEffect.CreateDiscrete(10.0f, 4.0f);
103+
paint.PathEffect = pathEffect;
104+
SKPoint[] points =
105+
{
106+
new SKPoint(0.0f, 0.0f),
107+
new SKPoint(256.0f, 256.0f)
108+
};
109+
SKColor[] colors =
110+
{
111+
new SKColor(66, 133, 244),
112+
new SKColor(15, 157, 88)
113+
};
114+
paint.Shader = SKShader.CreateLinearGradient(points[0], points[1], colors, SKShaderTileMode.Clamp);
115+
paint.IsAntialias = true;
116+
var path = Star();
117+
canvas.DrawPath(path, paint);
118+
119+
SKPath Star()
120+
{
121+
const float R = 60.0f, C = 128.0f;
122+
var path = new SKPath();
123+
path.MoveTo(C + R, C);
124+
for (var i = 1; i < 15; ++i)
125+
{
126+
var a = 0.44879895f * i;
127+
var r = R + R * (i % 2);
128+
path.LineTo((float)(C + r * Math.Cos(a)), (float)(C + r * Math.Sin(a)));
129+
}
130+
return path;
131+
}
132+
}
133+
}
134+
#endif
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<Page
2+
x:Class="Uno.Gallery.Views.SamplePages.SKCanvasElementPage"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:local="using:Uno.Gallery"
6+
xmlns:samples="using:Uno.Gallery.Views.Samples"
7+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9+
xmlns:smtx="using:ShowMeTheXAML"
10+
mc:Ignorable="d"
11+
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
12+
13+
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
14+
<local:SamplePageLayout IsDesignAgnostic="True">
15+
<local:SamplePageLayout.DesignAgnosticTemplate>
16+
<DataTemplate>
17+
<smtx:XamlDisplay
18+
UniqueKey="SKCanvasElementPage_Basic"
19+
smtx:XamlDisplayExtensions.Header="Basic SKCanvasElement">
20+
<Grid>
21+
<Grid RowSpacing="20">
22+
<Grid.RowDefinitions>
23+
<RowDefinition Height="Auto" />
24+
<RowDefinition Height="*" />
25+
</Grid.RowDefinitions>
26+
<Button HorizontalAlignment="Center" Click="NextSample_Click">Next sample</Button>
27+
<Grid Height="140" Grid.Row="1" x:Name="SKContainer">
28+
</Grid>
29+
</Grid>
30+
</Grid>
31+
32+
<!-- C# code
33+
public class SampleSKCanvasElement : SKCanvasElement
34+
{
35+
protected override void RenderOverride(SKCanvas canvas, Size area)
36+
{
37+
// Custom rendering logic goes here
38+
}
39+
}
40+
-->
41+
</smtx:XamlDisplay>
42+
</DataTemplate>
43+
</local:SamplePageLayout.DesignAgnosticTemplate>
44+
</local:SamplePageLayout>
45+
</Grid>
46+
</Page>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using Microsoft.UI.Xaml;
2+
using Microsoft.UI.Xaml.Controls;
3+
using Microsoft.UI.Xaml.Controls.Primitives;
4+
using Microsoft.UI.Xaml.Data;
5+
using Microsoft.UI.Xaml.Input;
6+
using Microsoft.UI.Xaml.Media;
7+
using Microsoft.UI.Xaml.Navigation;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.IO;
11+
using System.Linq;
12+
using System.Runtime.InteropServices.WindowsRuntime;
13+
using UnexpectedApis.Views;
14+
using Windows.Foundation;
15+
using Windows.Foundation.Collections;
16+
17+
namespace Uno.Gallery.Views.SamplePages;
18+
19+
[SamplePage(SampleCategory.UIComponents, "SKCanvasElement", Description = "Represents a 2D graphics canvas.", DocumentationLink = "https://platform.uno/docs/articles/controls/SKCanvasElement.html")]
20+
public sealed partial class SKCanvasElementPage : Page
21+
{
22+
#if HAS_UNO_SKIA
23+
public int MaxSampleIndex => SampleSKCanvasElement.SampleCount - 1;
24+
25+
private SampleSKCanvasElement _canvasElement;
26+
#endif
27+
28+
public SKCanvasElementPage()
29+
{
30+
this.InitializeComponent();
31+
32+
this.Loaded += SKCanvasElementPage_Loaded;
33+
}
34+
35+
private void SKCanvasElementPage_Loaded(object sender, RoutedEventArgs e)
36+
{
37+
#if HAS_UNO_SKIA
38+
var container = (Grid)FindName("SKContainer");
39+
container.Children.Add(_canvasElement = new SampleSKCanvasElement());
40+
#endif
41+
}
42+
43+
private void NextSample_Click(object sender, RoutedEventArgs e)
44+
{
45+
#if HAS_UNO_SKIA
46+
_canvasElement.Sample = (_canvasElement.Sample + 1) % SampleSKCanvasElement.SampleCount;
47+
#endif
48+
}
49+
}

0 commit comments

Comments
 (0)