2025-11-18
C#
00

目录

线性渐变(Linear Gradient)
基本语法
完整示例:基础线性渐变
多色线性渐变示例
不同TileMode效果示例
径向渐变(Radial Gradient)
基本语法
基础径向渐变示例
多色径向渐变示例
径向渐变TileMode效果示例
渐变的实际应用示例
创建彩虹效果
创建光晕效果
注意事项和最佳实践
总结

在SkiaSharp中,渐变是一种常用的填充效果,主要包括线性渐变(Linear Gradient)和径向渐变(Radial Gradient)。本文将详细介绍这两种渐变的使用方法和实际案例。

线性渐变(Linear Gradient)

线性渐变是沿着一条直线方向进行颜色过渡的渐变效果。在SkiaSharp中,使用SKShader.CreateLinearGradient()方法来创建线性渐变。

基本语法

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景 canvas.Clear(SKColors.White); // 创建画笔 using (var paint = new SKPaint()) { // 定义渐变的起点和终点 float x1 = 0; float y1 = 0; float x2 = skControl.Width; float y2 = skControl.Height; // 创建线性渐变 using (var shader = SKShader.CreateLinearGradient( new SKPoint(x1, y1), // 起点 new SKPoint(x2, y2), // 终点 new SKColor[] { // 渐变颜色数组 SKColors.Blue, // 起始颜色 SKColors.Red // 结束颜色 }, new float[] { 0, 1 }, // 颜色位置 SKShaderTileMode.Clamp)) // 平铺模式 { // 设置画笔的着色器 paint.Shader = shader; // 绘制一个填充整个控件的矩形 canvas.DrawRect(0, 0, skControl.Width, skControl.Height, paint); } } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 300); } } }

image.png

完整示例:基础线性渐变

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 调用绘制渐变的方法 DrawBasicLinearGradient(canvas); } public void DrawBasicLinearGradient(SKCanvas canvas) { // 创建画笔 using (var paint = new SKPaint()) { // 创建线性渐变 using (var shader = SKShader.CreateLinearGradient( new SKPoint(0, 0), // 起点:左上角 new SKPoint(200, 200), // 终点:右下角 new[] { SKColors.Red, // 起始颜色:红色 SKColors.Blue // 结束颜色:蓝色 }, null, // positions为null时表示颜色均匀分布 SKShaderTileMode.Clamp )) { paint.Shader = shader; // 绘制一个矩形,填充渐变色 canvas.DrawRect(0, 0, 200, 200, paint); } } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 300); } } }

image.png

多色线性渐变示例

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 调用绘制多色渐变的方法 DrawMultiColorLinearGradient(canvas); } public void DrawMultiColorLinearGradient(SKCanvas canvas) { using (var paint = new SKPaint()) { // 创建多色线性渐变 using (var shader = SKShader.CreateLinearGradient( new SKPoint(0, 0), new SKPoint(300, 0), new[] { SKColors.Red, // 红色 SKColors.Yellow, // 黄色 SKColors.Green, // 绿色 SKColors.Blue // 蓝色 }, new float[] { 0.0f, 0.33f, 0.66f, 1.0f }, // 指定每个颜色的位置 SKShaderTileMode.Clamp )) { paint.Shader = shader; // 绘制一个矩形 canvas.DrawRect(0, 0, 300, 100, paint); } } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 300); } } }

image.png

不同TileMode效果示例

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 绘制标题文本 using (var paint = new SKPaint { Color = SKColors.Black, TextSize = 14, IsAntialias = true }) { // 为每种模式添加说明文字 canvas.DrawText("Clamp Mode:", 10, 15, paint); canvas.DrawText("Repeat Mode:", 10, 135, paint); canvas.DrawText("Mirror Mode:", 10, 255, paint); } // 向下偏移20像素以留出文字空间 canvas.Translate(0, 20); // 调用绘制不同TileMode渐变的方法 DrawTileModeLinearGradient(canvas); } public void DrawTileModeLinearGradient(SKCanvas canvas) { // 演示三种TileMode的效果 SKShaderTileMode[] tileModes = { SKShaderTileMode.Clamp, SKShaderTileMode.Repeat, SKShaderTileMode.Mirror }; for (int i = 0; i < tileModes.Length; i++) { using (var paint = new SKPaint()) { using (var shader = SKShader.CreateLinearGradient( new SKPoint(0, 0), new SKPoint(100, 0), // 注意这里渐变长度只有100 new[] { SKColors.Red, SKColors.Blue }, null, tileModes[i] )) { paint.Shader = shader; // 绘制一个300宽的矩形,观察TileMode效果 canvas.DrawRect(0, i * 120, 300, 100, paint); } } } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 400); } } }

image.png

径向渐变(Radial Gradient)

径向渐变是从一个中心点向四周扩散的渐变效果。在SkiaSharp中,使用SKShader.CreateRadialGradient()方法来创建径向渐变。

基本语法

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 绘制基本径向渐变 DrawBasicRadialGradient(canvas); } public void DrawBasicRadialGradient(SKCanvas canvas) { // 创建画笔 using (var paint = new SKPaint()) { // 计算中心点(取控件中心) float centerX = skControl.Width / 2; float centerY = skControl.Height / 2; // 设置渐变半径(取较短边的一半) float radius = Math.Min(skControl.Width, skControl.Height) / 2; // 创建径向渐变 using (var shader = SKShader.CreateRadialGradient( new SKPoint(centerX, centerY), // 渐变中心点 radius, // 渐变半径 new[] { SKColors.Yellow, // 中心颜色 SKColors.Red // 边缘颜色 }, new float[] { 0, 1 }, // 颜色位置 SKShaderTileMode.Clamp // 平铺模式 )) { paint.Shader = shader; // 绘制一个覆盖整个控件的矩形 canvas.DrawRect(0, 0, skControl.Width, skControl.Height, paint); // 可选:绘制一个圆形来更好地展示径向渐变 canvas.DrawCircle(centerX, centerY, radius, paint); } } // 可选:添加一个小圆点标记中心位置 using (var centerPaint = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill }) { canvas.DrawCircle(skControl.Width / 2, skControl.Height / 2, 5, centerPaint); } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 400); } // 可选:处理窗口大小改变事件,重绘渐变 protected override void OnResize(EventArgs e) { base.OnResize(e); } } }

image.png

基础径向渐变示例

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 调用绘制径向渐变的方法 DrawBasicRadialGradient(canvas); } public void DrawBasicRadialGradient(SKCanvas canvas) { using (var paint = new SKPaint()) { // 创建径向渐变 using (var shader = SKShader.CreateRadialGradient( new SKPoint(150, 150), // 中心点 150, // 半径 new[] { SKColors.White, // 中心颜色:白色 SKColors.Blue // 边缘颜色:蓝色 }, null, // 均匀分布 SKShaderTileMode.Clamp )) { paint.Shader = shader; // 绘制一个矩形,展示径向渐变效果 canvas.DrawRect(0, 0, 300, 300, paint); } } // 可选:添加一个小圆点标记中心位置 using (var centerPaint = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill }) { canvas.DrawCircle(150, 150, 3, centerPaint); } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 400); } } }

image.png

多色径向渐变示例

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 调用绘制多色径向渐变的方法 DrawMultiColorRadialGradient(canvas); } public void DrawMultiColorRadialGradient(SKCanvas canvas) { using (var paint = new SKPaint()) { // 创建多色径向渐变 using (var shader = SKShader.CreateRadialGradient( new SKPoint(150, 150), // 中心点 150, // 半径 new[] { SKColors.Yellow, // 中心:黄色 SKColors.Red, // 中间:红色 SKColors.Blue, // 边缘:蓝色 }, new float[] { 0.0f, 0.5f, 1.0f }, // 颜色位置 SKShaderTileMode.Clamp )) { paint.Shader = shader; // 绘制圆形 canvas.DrawCircle(150, 150, 150, paint); } } // 可选:添加一个小圆点标记中心位置 using (var centerPaint = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill }) { canvas.DrawCircle(150, 150, 3, centerPaint); } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 400); } // 可选:处理窗口大小改变事件 protected override void OnResize(EventArgs e) { base.OnResize(e); } } }

image.png

径向渐变TileMode效果示例

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 绘制标题文本 using (var paint = new SKPaint { Color = SKColors.Black, TextSize = 14, IsAntialias = true }) { // 为每种模式添加说明文字 canvas.DrawText("Clamp Mode:", 10, 15, paint); canvas.DrawText("Repeat Mode:", 10, 135, paint); canvas.DrawText("Mirror Mode:", 10, 255, paint); } // 向下偏移20像素以留出文字空间 canvas.Translate(0, 20); // 调用绘制不同TileMode渐变的方法 DrawTileModeRadialGradient(canvas); } public void DrawTileModeRadialGradient(SKCanvas canvas) { SKShaderTileMode[] tileModes = { SKShaderTileMode.Clamp, SKShaderTileMode.Repeat, SKShaderTileMode.Mirror }; for (int i = 0; i < tileModes.Length; i++) { using (var paint = new SKPaint()) { using (var shader = SKShader.CreateRadialGradient( new SKPoint(150, 50 + i * 120), // 中心点 50, // 小半径,用于观察TileMode效果 new[] { SKColors.White, SKColors.Blue }, null, tileModes[i] )) { paint.Shader = shader; // 绘制矩形 canvas.DrawRect(0, i * 120, 300, 100, paint); } // 可选:添加中心点标记 using (var centerPaint = new SKPaint { Color = SKColors.Black, Style = SKPaintStyle.Fill }) { canvas.DrawCircle(150, 50 + i * 120, 3, centerPaint); } } } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 400); } // 可选:处理窗口大小改变事件 protected override void OnResize(EventArgs e) { base.OnResize(e); } } }

image.png

渐变的实际应用示例

创建彩虹效果

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); // 创建 SKGLControl skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; // 将控件添加到窗体 this.Controls.Add(skControl); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { // 获取画布 SKCanvas canvas = e.Surface.Canvas; // 清除背景为白色 canvas.Clear(SKColors.White); // 将画布原点移动到窗体中心 canvas.Translate(25, 25); // 调用绘制彩虹的方法 DrawRainbow(canvas); } public void DrawRainbow(SKCanvas canvas) { using (var paint = new SKPaint()) { // 创建彩虹渐变 using (var shader = SKShader.CreateLinearGradient( new SKPoint(0, 0), new SKPoint(350, 0), new[] { SKColors.Red, SKColors.Orange, SKColors.Yellow, SKColors.Green, SKColors.Blue, SKColors.Indigo, SKColors.Purple }, null, // 均匀分布颜色 SKShaderTileMode.Clamp )) { paint.Shader = shader; paint.Style = SKPaintStyle.Stroke; paint.StrokeWidth = 30; paint.IsAntialias = true; // 启用抗锯齿 // 绘制半圆弧 using (var path = new SKPath()) { path.AddArc( new SKRect(0, 0, 350, 350), 180, // 起始角度 180 // 扫描角度 ); canvas.DrawPath(path, paint); } } } // 可选:添加一些装饰性云朵 DrawCloud(canvas, 0, 350); DrawCloud(canvas, 300, 350); } // 辅助方法:绘制简单的云朵 private void DrawCloud(SKCanvas canvas, float x, float y) { using (var paint = new SKPaint { Color = SKColors.White, Style = SKPaintStyle.Fill, IsAntialias = true }) { // 添加阴影效果 paint.ImageFilter = SKImageFilter.CreateDropShadow( 2, 2, 2, 2, SKColors.Gray ); // 绘制几个重叠的圆形来创建云的形状 canvas.DrawCircle(x + 30, y, 20, paint); canvas.DrawCircle(x + 50, y, 25, paint); canvas.DrawCircle(x + 70, y, 20, paint); } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // 设置窗体的初始大小 this.ClientSize = new System.Drawing.Size(400, 400); } // 可选:处理窗口大小改变事件 protected override void OnResize(EventArgs e) { base.OnResize(e); } } }

image.png

创建光晕效果

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppStyle { public partial class Form1 : Form { private SKGLControl skControl; public Form1() { InitializeComponent(); skControl = new SKGLControl(); skControl.Dock = DockStyle.Fill; skControl.PaintSurface += SkControl_PaintSurface; this.Controls.Add(skControl); this.BackColor = System.Drawing.Color.Black; InitializeAnimation(); } private void SkControl_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e) { SKCanvas canvas = e.Surface.Canvas; canvas.Clear(SKColors.Black); DrawGlowEffect(canvas); } public void DrawGlowEffect(SKCanvas canvas) { using (var paint = new SKPaint()) { // 使用 glowIntensity 来调整颜色的透明度 using (var shader = SKShader.CreateRadialGradient( new SKPoint(150, 150), 150, new[] { new SKColor(255, 255, 0, (byte)(255 * glowIntensity)), // 中心 new SKColor(255, 165, 0, (byte)(128 * glowIntensity)), // 中间 new SKColor(255, 0, 0, 0) // 边缘 }, new float[] { 0.0f, 0.5f, 1.0f }, SKShaderTileMode.Clamp )) { paint.Shader = shader; paint.IsAntialias = true; canvas.DrawCircle(150, 150, 150, paint); } // 中心光点也跟随强度变化 using (var centerPaint = new SKPaint { Color = new SKColor(255, 255, 255, (byte)(255 * glowIntensity)), IsAntialias = true }) { canvas.DrawCircle(150, 150, 10, centerPaint); } } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.ClientSize = new System.Drawing.Size(400, 400); } private float glowIntensity = 0.5f; // 初始强度设为0.5 private System.Windows.Forms.Timer animationTimer; private void InitializeAnimation() { animationTimer = new System.Windows.Forms.Timer(); animationTimer.Interval = 16; // 约60fps的更新率 animationTimer.Tick += (s, e) => { // 使用正弦函数创建平滑的强度变化 glowIntensity = (float)(0.5 + 0.5 * Math.Sin(DateTime.Now.TimeOfDay.TotalSeconds * 2)); skControl.Invalidate(); }; animationTimer.Start(); } protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); animationTimer?.Stop(); animationTimer?.Dispose(); } } }

image.png

注意事项和最佳实践

  1. 资源释放
    • 始终使用 using 语句来确保 SKShader 和 SKPaint 对象被正确释放
    • 渐变shader的创建比较消耗资源,建议在不频繁变化的场景下缓存shader对象
  2. 性能考虑
    • 渐变的计算是比较耗费性能的,应该避免在每一帧都重新创建渐变
    • 对于静态渐变,建议创建一次并重复使用
  3. TileMode的选择
    • Clamp:超出范围的部分使用边缘颜色填充
    • Repeat:超出范围的部分重复渐变图案
    • Mirror:超出范围的部分镜像重复渐变图案
  4. 颜色位置
    • positions参数为null时,颜色会均匀分布
    • 自定义positions时,值必须在0到1之间,且必须递增
  5. 内存管理
    • 及时释放不再使用的shader对象
    • 在需要频繁更新的场景中,考虑重用shader对象而不是每次都创建新的

总结

SkiaSharp的渐变系统提供了强大而灵活的功能,可以创建各种丰富的视觉效果。通过合理使用线性渐变和径向渐变,再配合不同的TileMode和颜色配置,可以实现从简单的双色过渡到复杂的多彩效果。在实际应用中,需要注意性能优化和资源管理,以确保应用程序的流畅运行。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!