2025-11-18
C#
00

目录

SkiaSharp基础知识简介
画笔属性详解:线条风格的关键
线宽(StrokeWidth)
线帽(StrokeCap)
线段连接(StrokeJoin)
可视化艺术线条设计案例
艺术风格线条画
自定义画笔工具面板
炫酷的渐变线条艺术
线段连接风格展示
交互式线条设计工具
实际应用场景
性能优化建议
总结

在现代应用程序开发中,精美的视觉效果往往能提升用户体验。作为.NET平台上强大的跨平台2D图形绘图引擎,SkiaSharp提供了丰富的API来创建各种视觉效果。本文将聚焦于SkiaSharp中线条风格设计的艺术表现,通过详细的代码案例,帮助开发者掌握线宽、线帽和线段连接等关键技术,打造独具特色的视觉体验。

关键词:SkiaSharp教程、C#绘图、线条风格设计、.NET图形开发、跨平台UI、Xamarin绘图、MAUI绘图

SkiaSharp基础知识简介

SkiaSharp是Google's Skia图形库的.NET绑定,支持多平台(Windows、macOS、iOS、Android等)图形渲染。在开始线条艺术设计前,先了解几个核心概念:

C#
// SkiaSharp核心组件 // SKCanvas: 画布,提供绘图表面 // SKPaint: 画笔,定义如何绘制(颜色、线宽、线帽等) // SKPath: 路径,定义要绘制的几何形状

画笔属性详解:线条风格的关键

线宽(StrokeWidth)

线宽决定线条的粗细,单位为像素。

C#
// 创建不同线宽的画笔 SKPaint thinPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Blue, StrokeWidth = 2, // 细线 IsAntialias = true // 抗锯齿,使线条更平滑 }; SKPaint mediumPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Red, StrokeWidth = 8, // 中等线宽 IsAntialias = true }; SKPaint thickPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Green, StrokeWidth = 16, // 粗线 IsAntialias = true };

线帽(StrokeCap)

线帽定义线条两端的形状,有三种基本类型:

C#
// 线帽类型 SKPaint buttCapPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.DarkBlue, StrokeWidth = 12, StrokeCap = SKStrokeCap.Butt, // 平头线帽,线条在端点处切平 IsAntialias = true }; SKPaint roundCapPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.DarkRed, StrokeWidth = 12, StrokeCap = SKStrokeCap.Round, // 圆头线帽,线条两端为半圆形 IsAntialias = true }; SKPaint squareCapPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.DarkGreen, StrokeWidth = 12, StrokeCap = SKStrokeCap.Square, // 方头线帽,线条两端为矩形延伸 IsAntialias = true };

线段连接(StrokeJoin)

线段连接定义线段交汇处的形状:

C#
// 线段连接类型 SKPaint miterJoinPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Purple, StrokeWidth = 12, StrokeJoin = SKStrokeJoin.Miter, // 尖角连接 IsAntialias = true }; SKPaint roundJoinPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Orange, StrokeWidth = 12, StrokeJoin = SKStrokeJoin.Round, // 圆角连接 IsAntialias = true }; SKPaint bevelJoinPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Brown, StrokeWidth = 12, StrokeJoin = SKStrokeJoin.Bevel, // 斜角连接 IsAntialias = true };

可视化艺术线条设计案例

艺术风格线条画

创建一个简单但富有艺术感的线条组合,展示不同线帽和线宽的视觉效果:

C#
using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppLineStyle { public partial class Form1 : Form { private SKControl skiaControl; public Form1() { InitializeComponent(); SetupSkiaControl(); } private void SetupSkiaControl() { // 创建SkiaSharp控件 skiaControl = new SKControl(); skiaControl.Dock = DockStyle.Fill; skiaControl.PaintSurface += SkiaControl_PaintSurface; // 添加到窗体 this.Controls.Add(skiaControl); // 设置窗体属性 this.Text = "SkiaSharp 艺术线条演示"; this.Size = new System.Drawing.Size(800, 600); this.StartPosition = FormStartPosition.CenterScreen; } private void SkiaControl_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { // 调用你的绘图方法 DrawArtisticLines(e.Surface.Canvas); } public void DrawArtisticLines(SKCanvas canvas) { // 清除背景 canvas.Clear(SKColors.White); // 创建几种不同风格的画笔 SKPaint[] paints = new SKPaint[3]; // 细长线条,圆形线帽 paints[0] = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.DodgerBlue, StrokeWidth = 10, StrokeCap = SKStrokeCap.Round, IsAntialias = true }; // 中等线条,方形线帽 paints[1] = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.Crimson, StrokeWidth = 15, StrokeCap = SKStrokeCap.Square, IsAntialias = true }; // 粗线条,平头线帽 paints[2] = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.ForestGreen, StrokeWidth = 20, StrokeCap = SKStrokeCap.Butt, IsAntialias = true }; // 绘制波浪线图案 int height = canvas.DeviceClipBounds.Height; int width = canvas.DeviceClipBounds.Width; float centerY = height / 2f; for (int i = 0; i < paints.Length; i++) { using (SKPath path = new SKPath()) { path.MoveTo(0, centerY + i * 80 - 80); // 创建一个波浪形状 for (int x = 0; x < width; x += 60) { path.CubicTo( x + 15, centerY + i * 80 - 120, x + 45, centerY + i * 80 - 40, x + 60, centerY + i * 80 - 80); } canvas.DrawPath(path, paints[i]); } } // 添加说明文字 using (SKPaint textPaint = new SKPaint { Color = SKColors.Black, TextSize = 24, IsAntialias = true, Typeface= SKTypeface.FromFamilyName("Microsoft YaHei"), }) { canvas.DrawText("圆形线帽", 20, centerY - 80 + 40, textPaint); canvas.DrawText("方形线帽", 20, centerY + 40, textPaint); canvas.DrawText("平头线帽", 20, centerY + 80 + 40, textPaint); } // 记得释放画笔资源 foreach (var paint in paints) { paint?.Dispose(); } } } }

image.png

自定义画笔工具面板

创建一个模拟绘图应用的画笔选择面板,展示各种线条样式:

C#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppLineStyle { public partial class Form2 : Form { private SKControl skiaControl; public Form2() { InitializeComponent(); // 创建SkiaSharp控件 skiaControl = new SKControl(); skiaControl.Dock = DockStyle.Fill; skiaControl.PaintSurface += SkiaControl_PaintSurface; // 添加到窗体 this.Controls.Add(skiaControl); } private void SkiaControl_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { // 调用你的绘图方法 DrawBrushSelectionPanel(e.Surface.Canvas); } public void DrawBrushSelectionPanel(SKCanvas canvas) { // 你的完整绘制代码 canvas.Clear(new SKColor(240, 240, 240)); float panelWidth = canvas.DeviceClipBounds.Width * 0.9f; float panelHeight = canvas.DeviceClipBounds.Height * 0.8f; float startX = (canvas.DeviceClipBounds.Width - panelWidth) / 2; float startY = (canvas.DeviceClipBounds.Height - panelHeight) / 2; // 绘制面板背景 SKPaint panelPaint = new SKPaint { Color = SKColors.White, IsAntialias = true }; SKRect panelRect = new SKRect(startX, startY, startX + panelWidth, startY + panelHeight); canvas.DrawRoundRect(panelRect, 20, 20, panelPaint); // 添加阴影 SKPaint shadowPaint = new SKPaint { Color = new SKColor(0, 0, 0, 50), IsAntialias = true, MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 10) }; canvas.DrawRoundRect(new SKRect(startX + 5, startY + 5, startX + panelWidth + 5, startY + panelHeight + 5), 20, 20, shadowPaint); // 绘制标题 SKPaint titlePaint = new SKPaint { Color = SKColors.DarkSlateGray, TextSize = 40, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei"), }; canvas.DrawText("画笔样式选择器", startX + panelWidth / 2, startY + 60, titlePaint); // 画笔样式数组 SKStrokeCap[] caps = new SKStrokeCap[] { SKStrokeCap.Butt, SKStrokeCap.Round, SKStrokeCap.Square }; string[] capNames = new string[] { "平头", "圆头", "方头" }; SKColor[] colors = new SKColor[] { SKColors.CornflowerBlue, SKColors.Tomato, SKColors.MediumSeaGreen }; float[] lineWidths = new float[] { 4, 8, 16, 24 }; string[] widthNames = new string[] { "极细", "细", "中", "粗" }; // 绘制线帽示例 float capStartY = startY + 120; float lineLength = 200; SKPaint labelPaint = new SKPaint { Color = SKColors.DarkSlateGray, TextSize = 24, IsAntialias = true, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei"), }; canvas.DrawText("线帽样式:", startX + 30, capStartY - 20, labelPaint); for (int i = 0; i < caps.Length; i++) { float y = capStartY + i * 60; SKPaint linePaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = colors[i], StrokeWidth = 16, StrokeCap = caps[i], IsAntialias = true }; canvas.DrawLine(startX + 50, y, startX + 50 + lineLength, y, linePaint); canvas.DrawText(capNames[i], startX + 50 + lineLength + 30, y + 10, labelPaint); } // 绘制线宽示例 float widthStartY = capStartY + caps.Length * 60 + 40; canvas.DrawText("线宽选择:", startX + 30, widthStartY - 20, labelPaint); for (int i = 0; i < lineWidths.Length; i++) { float y = widthStartY + i * 60; SKPaint linePaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.SlateGray, StrokeWidth = lineWidths[i], StrokeCap = SKStrokeCap.Round, IsAntialias = true }; canvas.DrawLine(startX + 50, y, startX + 50 + lineLength, y, linePaint); canvas.DrawText(widthNames[i] + $" ({lineWidths[i]}px)", startX + 50 + lineLength + 30, y + 10, labelPaint); } } } }

image.png

炫酷的渐变线条艺术

创建带有渐变色的艺术线条,展示更高级的线条效果:

C#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppLineStyle { public partial class Form3 : Form { private SKControl skiaControl; public Form3() { InitializeComponent(); // 创建SkiaSharp控件 skiaControl = new SKControl(); skiaControl.Dock = DockStyle.Fill; skiaControl.PaintSurface += SkiaControl_PaintSurface; // 添加到窗体 this.Controls.Add(skiaControl); } private void SkiaControl_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { // 调用你的绘图方法 DrawGradientArtLines(e.Surface.Canvas); } public void DrawGradientArtLines(SKCanvas canvas) { // 设置深色背景 canvas.Clear(new SKColor(30, 30, 40)); int width = canvas.DeviceClipBounds.Width; int height = canvas.DeviceClipBounds.Height; // 创建渐变画笔 SKPaint gradientPaint = new SKPaint { Style = SKPaintStyle.Stroke, StrokeWidth = 8, StrokeCap = SKStrokeCap.Round, IsAntialias = true }; // 创建径向渐变的颜色数组 SKColor[] gradientColors = new SKColor[] { new SKColor(255, 50, 50), // 红色 new SKColor(255, 150, 0), // 橙色 new SKColor(255, 255, 0), // 黄色 new SKColor(0, 255, 0), // 绿色 new SKColor(0, 150, 255), // 青色 new SKColor(75, 0, 255), // 蓝色 new SKColor(255, 0, 255) // 紫色 }; // 路径点数量 int pathPoints = 12; float radius = Math.Min(width, height) * 0.4f; float centerX = width / 2f; float centerY = height / 2f; // 创建一个环形路径 SKPath circlePath = new SKPath(); for (int i = 0; i <= 360; i += 1) { float angle = i * (float)Math.PI / 180; float x = centerX + radius * (float)Math.Cos(angle); float y = centerY + radius * (float)Math.Sin(angle); if (i == 0) circlePath.MoveTo(x, y); else circlePath.LineTo(x, y); } // 创建渐变效果 SKPathEffect dashEffect = SKPathEffect.CreateDash( new float[] { 15, 10 }, // 线段长度和间隔 0 // 偏移 ); // 创建一个路径测量对象来测量路径长度 SKPathMeasure pathMeasure = new SKPathMeasure(circlePath); float pathLength = pathMeasure.Length; // 创建多个路径,每个路径具有不同的线宽和偏移 for (int i = 0; i < 8; i++) { // 使用径向渐变 gradientPaint.Shader = SKShader.CreateSweepGradient( new SKPoint(centerX, centerY), gradientColors, null); // 设置线条样式 gradientPaint.StrokeWidth = 20 - i * 2; gradientPaint.PathEffect = SKPathEffect.CreateDash( new float[] { 15, 5 + i * 1.5f }, i * 5 // 偏移,创造交错效果 ); // 缩放路径 SKPath scaledPath = new SKPath(circlePath); SKMatrix scaleMatrix = SKMatrix.CreateScale( 0.8f + i * 0.05f, 0.8f + i * 0.05f, centerX, centerY); scaledPath.Transform(scaleMatrix); // 绘制路径 canvas.DrawPath(scaledPath, gradientPaint); } // 添加说明文字 SKPaint textPaint = new SKPaint { Color = SKColors.White, TextSize = 30, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei"), }; canvas.DrawText("渐变线条艺术", centerX, height - 50, textPaint); } } }

image.png

线段连接风格展示

展示各种线段连接方式的视觉效果差异:

C#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppLineStyle { public partial class Form3 : Form { private SKControl skiaControl; public Form3() { InitializeComponent(); // 创建SkiaSharp控件 skiaControl = new SKControl(); skiaControl.Dock = DockStyle.Fill; skiaControl.PaintSurface += SkiaControl_PaintSurface; // 添加到窗体 this.Controls.Add(skiaControl); } private void SkiaControl_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { // 调用你的绘图方法 DrawLineJoinStyles(e.Surface.Canvas); } public void DrawLineJoinStyles(SKCanvas canvas) { // 设置背景 canvas.Clear(SKColors.White); int width = canvas.DeviceClipBounds.Width; int height = canvas.DeviceClipBounds.Height; // 创建标题文本 SKPaint titlePaint = new SKPaint { Color = SKColors.Black, TextSize = 30, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface= SKTypeface.FromFamilyName("Microsoft YaHei") }; canvas.DrawText("线段连接风格对比", width / 2, 60, titlePaint); // 创建子标题 SKPaint subtitlePaint = new SKPaint { Color = SKColors.DarkGray, TextSize = 20, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei") }; canvas.DrawText("同一形状,不同连接方式的视觉效果", width / 2, 100, subtitlePaint); // 定义线段连接类型和名称 SKStrokeJoin[] joins = new SKStrokeJoin[] { SKStrokeJoin.Miter, SKStrokeJoin.Round, SKStrokeJoin.Bevel }; string[] joinNames = new string[] { "尖角(Miter)", "圆角(Round)", "斜角(Bevel)" }; SKColor[] colors = new SKColor[] { SKColors.RoyalBlue, SKColors.Crimson, SKColors.ForestGreen }; // 绘制示例形状 float startY = 150; float shapesPerRow = 3; float shapeWidth = width / shapesPerRow; float shapeHeight = 150; // 绘制锯齿形状和星形 for (int row = 0; row < 2; row++) { for (int i = 0; i < joins.Length; i++) { float startX = i * shapeWidth; // 创建画笔 SKPaint paint = new SKPaint { Style = SKPaintStyle.Stroke, Color = colors[i], StrokeWidth = 20, StrokeJoin = joins[i], IsAntialias = true }; // 绘制路径 SKPath path = new SKPath(); if (row == 0) // 锯齿形状 { float zigzagWidth = shapeWidth * 0.7f; float zigzagHeight = shapeHeight * 0.7f; float zigzagX = startX + (shapeWidth - zigzagWidth) / 2; float zigzagY = startY + (shapeHeight - zigzagHeight) / 2; // 创建锯齿路径 path.MoveTo(zigzagX, zigzagY); for (int j = 0; j < 5; j++) { path.LineTo(zigzagX + zigzagWidth * j / 4, zigzagY + (j % 2 == 0 ? zigzagHeight : 0)); } } else // 星形 { float starRadius = Math.Min(shapeWidth, shapeHeight) * 0.35f; float centerX = startX + shapeWidth / 2; float centerY = startY + shapeHeight * 1.5f; // 创建五角星 for (int j = 0; j <= 10; j++) { float angle = (float)(Math.PI / 2 + j * Math.PI * 2 / 10); float radius = j % 2 == 0 ? starRadius : starRadius * 0.5f; float x = centerX + radius * (float)Math.Cos(angle); float y = centerY - radius * (float)Math.Sin(angle); if (j == 0) path.MoveTo(x, y); else path.LineTo(x, y); } path.Close(); } // 绘制形状 canvas.DrawPath(path, paint); // 添加标签 SKPaint labelPaint = new SKPaint { Color = SKColors.Black, TextSize = 18, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei") }; float labelY = row == 0 ? startY + shapeHeight + 25 : startY + shapeHeight * 2 + 25; canvas.DrawText(joinNames[i], startX + shapeWidth / 2, labelY, labelPaint); } } } } }

image.png

交互式线条设计工具

这里模拟一个交互式线条设计工具的界面,展示如何组合使用各种线条属性:

C#
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using SkiaSharp; using SkiaSharp.Views.Desktop; namespace AppLineStyle { public partial class Form3 : Form { private SKControl skiaControl; private int[] selectedOptions = new int[] { 2, 1, 1 }; // 10px, 圆头, 圆角 public Form3() { InitializeComponent(); // 创建SkiaSharp控件 skiaControl = new SKControl(); skiaControl.Dock = DockStyle.Fill; skiaControl.PaintSurface += SkiaControl_PaintSurface; skiaControl.MouseDown += SkiaControl_MouseDown; // 添加到窗体 this.Controls.Add(skiaControl); } private void SkiaControl_MouseDown(object sender, MouseEventArgs e) { int width = skiaControl.Width; // 工具栏区域的参数 float toolbarLeft = 20; float toolbarTop = 70; float optionHeight = 30; float spacing = 10; float optionStartX = toolbarLeft + 100; float optionWidth = 70; string[][] options = new string[][] { new string[] { "2px", "5px", "10px", "15px", "20px" }, new string[] { "平头", "圆头", "方头" }, new string[] { "尖角", "圆角", "斜角" } }; // 循环每行判断 for (int i = 0; i < options.Length; i++) { float rowY = toolbarTop + 20 + i * (optionHeight + spacing); for (int j = 0; j < options[i].Length; j++) { float optionX = optionStartX + j * (optionWidth + spacing); RectangleF rect = new RectangleF(optionX, rowY, optionWidth, optionHeight); if (rect.Contains(e.X, e.Y)) { selectedOptions[i] = j; skiaControl.Invalidate(); // 触发重绘 return; } } } } private void SkiaControl_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { // 调用你的绘图方法 DrawInteractiveLineDesigner(e.Surface.Canvas); } public void DrawInteractiveLineDesigner(SKCanvas canvas) { // 设置背景 canvas.Clear(new SKColor(245, 245, 250)); int width = canvas.DeviceClipBounds.Width; int height = canvas.DeviceClipBounds.Height; // 标题 SKPaint titlePaint = new SKPaint { Color = SKColors.DarkSlateBlue, TextSize = 32, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright) }; canvas.DrawText("交互式线条设计工具", width / 2, 50, titlePaint); // 绘制工具栏背景 SKRect toolbarRect = new SKRect(20, 70, width - 20, 200); SKPaint toolbarPaint = new SKPaint { Color = SKColors.White, IsAntialias = true }; canvas.DrawRoundRect(toolbarRect, 10, 10, toolbarPaint); // 绘制阴影 SKPaint shadowPaint = new SKPaint { Color = new SKColor(0, 0, 0, 30), IsAntialias = true, MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 5) }; canvas.DrawRoundRect(new SKRect(toolbarRect.Left + 3, toolbarRect.Top + 3, toolbarRect.Right + 3, toolbarRect.Bottom + 3), 10, 10, shadowPaint); // 定义要显示的线条属性 string[] propNames = new string[] { "线宽", "线帽", "连接" }; string[][] options = new string[][] { new string[] { "2px", "5px", "10px", "15px", "20px" }, new string[] { "平头", "圆头", "方头" }, new string[] { "尖角", "圆角", "斜角" } }; // 绘制工具栏选项 SKPaint labelPaint = new SKPaint { Color = SKColors.DarkSlateBlue, TextSize = 18, IsAntialias = true, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei"), }; SKPaint optionPaint = new SKPaint { Color = SKColors.White, IsAntialias = true }; SKPaint selectedOptionPaint = new SKPaint { Color = new SKColor(230, 240, 255), IsAntialias = true }; SKPaint optionTextPaint = new SKPaint { Color = SKColors.DarkSlateBlue, TextSize = 16, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei"), }; float startY = toolbarRect.Top + 20; float optionHeight = 30; float spacing = 10; for (int i = 0; i < propNames.Length; i++) { float rowY = startY + i * (optionHeight + spacing); // 绘制属性名称 canvas.DrawText(propNames[i] + ":", toolbarRect.Left + 20, rowY + optionHeight / 2 + 5, labelPaint); // 绘制选项 float optionStartX = toolbarRect.Left + 100; float optionWidth = 70; for (int j = 0; j < options[i].Length; j++) { float optionX = optionStartX + j * (optionWidth + spacing); SKRect optionRect = new SKRect(optionX, rowY, optionX + optionWidth, rowY + optionHeight); // 绘制选项背景(选中的和未选中的不同) canvas.DrawRoundRect(optionRect, 5, 5, j == selectedOptions[i] ? selectedOptionPaint : optionPaint); // 绘制边框 SKPaint borderPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = j == selectedOptions[i] ? SKColors.RoyalBlue : SKColors.LightGray, StrokeWidth = j == selectedOptions[i] ? 2 : 1, IsAntialias = true }; canvas.DrawRoundRect(optionRect, 5, 5, borderPaint); // 绘制选项文本 canvas.DrawText(options[i][j], optionX + optionWidth / 2, rowY + optionHeight / 2 + 5, optionTextPaint); } } // 绘制预览区域 SKRect previewRect = new SKRect(20, 220, width - 20, height - 20); canvas.DrawRoundRect(previewRect, 10, 10, toolbarPaint); canvas.DrawRoundRect(new SKRect(previewRect.Left + 3, previewRect.Top + 3, previewRect.Right + 3, previewRect.Bottom + 3), 10, 10, shadowPaint); // 绘制预览区域标题 SKPaint previewTitlePaint = new SKPaint { Color = SKColors.DarkSlateBlue, TextSize = 24, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei"), }; canvas.DrawText("预览效果", width / 2, previewRect.Top + 30, previewTitlePaint); // 根据选择的选项创建画笔 float[] strokeWidths = new float[] { 2, 5, 10, 15, 20 }; SKStrokeCap[] strokeCaps = new SKStrokeCap[] { SKStrokeCap.Butt, SKStrokeCap.Round, SKStrokeCap.Square }; SKStrokeJoin[] strokeJoins = new SKStrokeJoin[] { SKStrokeJoin.Miter, SKStrokeJoin.Round, SKStrokeJoin.Bevel }; SKPaint customPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = SKColors.MediumSlateBlue, StrokeWidth = strokeWidths[selectedOptions[0]], StrokeCap = strokeCaps[selectedOptions[1]], StrokeJoin = strokeJoins[selectedOptions[2]], IsAntialias = true }; // 在预览区域绘制一些示例形状 float centerX = previewRect.MidX; float centerY = previewRect.MidY + 50; float size = 150; // 绘制一个星形 SKPath starPath = new SKPath(); for (int i = 0; i <= 10; i++) { float angle = (float)(Math.PI / 2 + i * Math.PI * 2 / 10); float radius = i % 2 == 0 ? size : size * 0.4f; float x = centerX + radius * (float)Math.Cos(angle); float y = centerY - radius * (float)Math.Sin(angle); if (i == 0) starPath.MoveTo(x, y); else starPath.LineTo(x, y); } //starPath.Close(); canvas.DrawPath(starPath, customPaint); // 添加一些说明文字 SKPaint descPaint = new SKPaint { Color = SKColors.DarkSlateBlue, TextSize = 18, IsAntialias = true, TextAlign = SKTextAlign.Center, Typeface = SKTypeface.FromFamilyName("Microsoft YaHei"), }; // 格式化当前设置信息 string settingsText = $"当前设置: 线宽={strokeWidths[selectedOptions[0]]}px, " + $"线帽={options[1][selectedOptions[1]]}, " + $"连接={options[2][selectedOptions[2]]}"; canvas.DrawText(settingsText, centerX, previewRect.Bottom - 30, descPaint); } } }

image.png

实际应用场景

以上案例可以广泛应用于:

  1. 数据可视化应用:通过不同线条样式区分数据系列
  2. UI设计工具:为用户提供丰富的绘图选项
  3. 手绘签名功能:实现平滑、自然的手写体验
  4. 地图应用:使用不同线条样式区分道路类型
  5. 游戏开发:创建具有艺术感的游戏界面元素

性能优化建议

在实际应用中,为确保流畅体验,请注意:

  1. 合理使用 IsAntialias:抗锯齿虽能提升视觉效果,但会增加计算负担
  2. 缓存复杂路径:频繁使用的复杂路径应当缓存而非重复计算
  3. 控制绘制区域:使用 ClipRect 限制绘制范围,避免不必要的计算
  4. 注意线宽设置:过大的线宽会显著增加渲染负担
C#
// 性能优化示例:限制绘制区域 public void OptimizedDrawing(SKCanvas canvas) { // 保存当前状态 canvas.Save(); // 限制绘制区域 canvas.ClipRect(new SKRect(0, 0, 500, 500)); // 执行绘制 DrawComplexGraphics(canvas); // 恢复状态 canvas.Restore(); }

总结

SkiaSharp提供了丰富而强大的线条样式API,通过合理组合线宽、线帽和线段连接等属性,我们可以创建出各种精美的视觉效果。本文通过5个详细案例,展示了如何在实际项目中灵活运用这些功能,打造独特的视觉体验。无论是开发数据可视化应用、创意绘图工具,还是游戏界面,掌握这些技术都将极大提升产品的视觉表现力。

希望这些实例能为您的开发工作提供灵感!如有任何问题,欢迎在评论区留言。


本文作者:技术老小子

本文链接:

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