SkiaShrap graphics library renders gradients very very smooth and I love it on WPF (as opposed to natural way of creating gradients) it also scales nicely when a window resizes without extra code;
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Windows; | |
using System.Windows.Input; | |
using SkiaSharp; | |
using Topten.RichTextKit; | |
namespace Xaml.Shop.SkiaWPFSamples | |
{ | |
SKPaint pinkFillPaint = new SKPaint | |
{ | |
Style = SKPaintStyle.Fill, | |
Color = SKColors.Pink, | |
TextSize = 80, | |
IsAntialias = true | |
}; | |
SKPaint pinkStrokePaint = new SKPaint | |
{ | |
Style = SKPaintStyle.Stroke, | |
Color = SKColors.HotPink.WithAlpha(90), | |
StrokeWidth = 0.5f, | |
StrokeCap = SKStrokeCap.Round, | |
IsAntialias = true | |
}; | |
private void skiaCanvas2_PaintSurface(object sender, SkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs e) | |
{ | |
SKSurface easel = e.Surface; | |
SKCanvas canvas = easel.Canvas; | |
canvas.Clear(SKColor.Parse("#FF27293D")); | |
var goldenRatio= 1.61803399f; | |
var width = e.Info.Width; | |
var height = e.Info.Height; | |
var minVal = 0; | |
var maxVal = 130; | |
var stepHeight = 10; | |
var stepCount = ((maxVal - minVal) / stepHeight); | |
var headerH = (height - (height / goldenRatio))/2; | |
var sideMargin = (width- (width / goldenRatio))/5; | |
var xStart = 0f; | |
var xEnd = width - (sideMargin * 2); | |
var yStart = 0f; | |
var yEnd = 0f; | |
canvas.Translate(sideMargin, headerH); | |
var chartHeight = height - (headerH * 2); | |
var charWidth = width - (sideMargin * 2); | |
var adjustedStepHeight = (int)Math.Floor((chartHeight / stepCount)); | |
var adjustedMaxVal = maxVal*((chartHeight) / maxVal); | |
var count = 0; | |
//draw chart rectangle | |
SKRect chartRect = new SKRect(xStart,yStart,charWidth,chartHeight); | |
canvas.DrawRect(chartRect,pinkStrokePaint); | |
//draw horizontal lines | |
for (int i = 0; i < stepCount+1; i++) | |
{ | |
var y = (i * adjustedStepHeight); | |
if (i > 0 && i < stepCount) | |
{ | |
canvas.DrawLine(xStart, y, xEnd, y, pinkStrokePaint); | |
} | |
var rs = new RichString().Alignment(Topten.RichTextKit.TextAlignment.Right) | |
.FontFamily("Segoe UI") | |
.FontSize(10) | |
.Add($"{maxVal - count}", textColor: SKColors.WhiteSmoke); | |
var tw = rs.MeasuredWidth; | |
rs.MaxWidth =25; | |
rs.Paint(canvas,new SKPoint(xStart - 30, y), new TextPaintOptions{IsAntialias = true}); | |
count += stepHeight; | |
canvas.Save(); | |
} | |
//draw vertical lines | |
for (int i = 0; i < 10; i++) | |
{ | |
var w = charWidth / 10; | |
canvas.DrawLine(i * w, 0, i*w, chartHeight, pinkStrokePaint); | |
} | |
canvas.Restore(); | |
var values = new List<int> {50,80,130,70,90,40,110,100,70,42}; | |
var z = 0; | |
foreach (var val in values) | |
{ | |
using (SKPaint paint = new SKPaint()) | |
{ | |
var secWidth = (charWidth / 10); | |
var barW = secWidth / 4 * 3; | |
var marginLeft = (secWidth - barW) / 2; | |
var barH = val; | |
// Create 300-pixel square centered rectangle | |
float x = marginLeft+secWidth*z; | |
float y = (chartHeight - (val / 10 * adjustedStepHeight)); | |
SKRect rect = new SKRect(x, y, x + barW, chartHeight); | |
// Create linear gradient from upper-left to lower-right | |
paint.Shader = SKShader.CreateLinearGradient( | |
new SKPoint(rect.Left, rect.Top), | |
new SKPoint(rect.Right, rect.Bottom), | |
new SKColor[] { SKColors.DeepPink, SKColor.Parse("#fd5d93") }, | |
new float[] { 0, 1 }, | |
SKShaderTileMode.Mirror); | |
// Draw the gradient on the rectangle | |
canvas.DrawRect(rect, paint); | |
var rs = new RichString().Alignment(Topten.RichTextKit.TextAlignment.Center) | |
.FontFamily("Segoe UI") | |
.FontSize(10) | |
.Add($"{val}", textColor: SKColors.WhiteSmoke); | |
var tw = rs.MeasuredWidth; | |
rs.MaxWidth = 25; | |
rs.Paint(canvas, new SKPoint(x, y), new TextPaintOptions { IsAntialias = true }); | |
z++; | |
} | |
} | |
} | |
}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Window x:Class="Xaml.Shop.SkiaWPFSamples.MainWindow" | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |
xmlns:skia="clr-namespace:SkiaSharp.Views;assembly=SkiaSharp.Views.WPF" | |
xmlns:local="clr-namespace:SkiaWPFSamples" | |
xmlns:wpf="clr-namespace:SkiaSharp.Views.WPF;assembly=SkiaSharp.Views.WPF" | |
mc:Ignorable="d" | |
Title="WPF SKIA 2D Samples" Height="1020" Width="1900"> | |
<Grid> | |
//set skia canvas | |
<wpf:SKElement x:Name="skiaCanvas2" PaintSurface="skiaCanvas2_PaintSurface" /> | |
</Grid> | |
</Window> |