编辑
2025-02-11
C# 应用
00
请注意,本文编写于 84 天前,最后修改于 84 天前,其中某些信息可能已经过时。

目录

简介
环境准备
安装SVG.NET库
添加必要的引用
基础使用
加载并显示SVG
4. 高级功能
4.1 SVG缩放控制
4.2 SVG颜色修改
4.3 SVG元素操作
6. 总结

简介

SVG.NET是一个强大的开源库,专门用于在.NET应用程序中处理SVG(Scalable Vector Graphics)文件。本文将详细介绍如何在WinForm应用程序中使用SVG.NET库来显示和操作SVG图片。

环境准备

安装SVG.NET库

在Visual Studio中,通过NuGet包管理器安装Svg包:

PowerShell
Install-Package Svg

或在包管理器控制台中执行:

C#
dotnet add package Svg

image.png

添加必要的引用

C#
using Svg; using System.Drawing; using System.Drawing.Imaging;

基础使用

加载并显示SVG

C#
private void btnLoad_Click(object sender, EventArgs e) { var svgDocument = SvgDocument.Open("1.svg"); var bitmap = svgDocument.Draw(); pictureBox1.Image = bitmap; }

1.svg文件

SVG
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"[]><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="64px" viewBox="0 0 125.921 121.105" enable-background="new 0 0 125.921 121.105" xml:space="preserve"> <g id="Group_OutletPort"> <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="119.3706" y1="-412.0227" x2="119.3706" y2="-361.6145" gradientTransform="matrix(1 0 0 -1 0 -360.895)"> <stop offset="0" style="stop-color:#4D4D4D" /> <stop offset="0.21" style="stop-color:#717171" /> <stop offset="0.54" style="stop-color:#A6A6A6" /> <stop offset="0.64" style="stop-color:#9F9F9F" /> <stop offset="0.79" style="stop-color:#8C8C8C" /> <stop offset="0.97" style="stop-color:#6D6D6D" /> <stop offset="1" style="stop-color:#666666" /> </linearGradient> <rect x="112.821" y="0.719" fill="url(#SVGID_1_)" stroke="#B3B3B3" stroke-width="0.5" width="13.101" height="50.408" /> <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="83.0708" y1="76.9197" x2="83.0708" y2="115.9207" gradientTransform="matrix(1 0 0 -1 0 122.105)"> <stop offset="0" style="stop-color:#4D4D4D" /> <stop offset="0.52" style="stop-color:#B2B2B2" /> <stop offset="1" style="stop-color:#666666" /> </linearGradient> <polyline fill="url(#SVGID_2_)" points="53.235,6.184 112.907,6.184 112.907,45.185 102.517,45.185 " /> </g> <g id="Group_Legs"> <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="52.5283" y1="1094.1335" x2="52.5283" y2="1058.2527" gradientTransform="matrix(1 0 0 1 0 -973.75)"> <stop offset="0" style="stop-color:#999999" /> <stop offset="1" style="stop-color:#666666" /> </linearGradient> <path fill="url(#SVGID_3_)" stroke="#999999" stroke-width="0.396" d="M11.321,120.384l10.254-35.881h61.908l10.252,35.881H72.966 L52.462,89.497l-20.769,30.887H11.321z" /> </g> <g id="Group_LegBase"> <path fill="#999999" stroke="#B3B3B3" stroke-width="0.5" d="M0.76,115.851h37.533v5.254H0.76V115.851z" /> <path fill="#999999" stroke="#B3B3B3" stroke-width="0.5" d="M66.603,115.851h37.929v5.254H66.603V115.851L66.603,115.851z" /> </g> <g id="Group_PumpBody"> <radialGradient id="SVGID_4_" cx="126.48" cy="837.1521" r="51.5659" gradientTransform="matrix(0.9999 0.0069 -0.0069 0.9999 -67.9976 -780.2224)" gradientUnits="userSpaceOnUse"> <stop offset="0.18" style="stop-color:#333333" /> <stop offset="0.26" style="stop-color:#383838" /> <stop offset="0.35" style="stop-color:#454545" /> <stop offset="0.44" style="stop-color:#5C5C5C" /> <stop offset="0.54" style="stop-color:#7B7B7B" /> <stop offset="0.64" style="stop-color:#A4A4A4" /> <stop offset="0.72" style="stop-color:#CCCCCC" /> <stop offset="0.81" style="stop-color:#B1B1B1" /> <stop offset="0.99" style="stop-color:#6B6B6B" /> <stop offset="1" style="stop-color:#666666" /> </radialGradient> <path fill="url(#SVGID_4_)" d="M53.047,6.158c28.477,0.196,51.402,23.439,51.207,51.917c-0.195,28.475-23.438,51.398-51.914,51.204 C23.862,109.086,0.938,85.841,1.133,57.364C1.326,28.889,24.573,5.963,53.047,6.158z" /> </g> <g id="Group_CenterShade"> <radialGradient id="SVGID_5_" cx="52.4468" cy="-418.7268" r="27.2441" gradientTransform="matrix(1 0 0 -1 0 -360.895)" gradientUnits="userSpaceOnUse"> <stop offset="0" style="stop-color:#000000" /> <stop offset="1" style="stop-color:#333333" /> </radialGradient> <path fill="url(#SVGID_5_)" d="M38.399,81.168C25.508,73.407,21.35,56.67,29.111,43.78c7.762-12.888,24.502-17.045,37.385-9.285 c12.891,7.761,17.047,24.498,9.289,37.393C68.021,84.769,51.286,88.928,38.399,81.168z" /> </g> <g id="Group_Impeller"> <linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="101.9819" y1="125.5398" x2="106.1411" y2="125.5342" gradientTransform="matrix(0.9889 0.1484 0.1484 -0.9889 -69.6528 166.4384)"> <stop offset="0.01" style="stop-color:#666666" /> <stop offset="0.51" style="stop-color:#B8B8B8" /> <stop offset="1" style="stop-color:#666666" /> </linearGradient> <path fill="url(#SVGID_6_)" d="M51.014,77.055c-0.642,4.14-2.024,7.351-3.166,7.187c-1.139-0.165-1.545-3.651-0.902-7.789 l0.014-0.081l5.874-37.983c0.64-4.139,1.986-7.314,3.125-7.149c1.142,0.163,1.507,3.623,0.866,7.76L51.014,77.055z" /> <linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-277.9653" y1="21.0618" x2="-273.8071" y2="21.0562" gradientTransform="matrix(0.6317 -0.7752 -0.7752 -0.6317 243.0495 -142.3917)"> <stop offset="0.01" style="stop-color:#666666" /> <stop offset="0.51" style="stop-color:#B8B8B8" /> <stop offset="1" style="stop-color:#666666" /> </linearGradient> <path fill="url(#SVGID_7_)" d="M68.625,68.765c3.234,2.659,5.291,5.485,4.57,6.387c-0.724,0.895-3.931-0.533-7.162-3.193 l-0.063-0.053L36.284,47.493c-3.234-2.66-5.28-5.437-4.559-6.333c0.722-0.898,3.884,0.55,7.117,3.21L68.625,68.765z" /> <linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="216.7651" y1="433.1179" x2="220.9233" y2="433.1123" gradientTransform="matrix(0.4225 0.9064 0.9064 -0.4225 -432.8737 42.0522)"> <stop offset="0.01" style="stop-color:#666666" /> <stop offset="0.51" style="stop-color:#B8B8B8" /> <stop offset="1" style="stop-color:#666666" /> </linearGradient> <path fill="url(#SVGID_8_)" d="M35.58,67.368c-3.803,1.752-7.245,2.373-7.739,1.332c-0.491-1.041,2.193-3.306,5.994-5.057 l0.076-0.033L68.82,47.527c3.805-1.752,7.195-2.384,7.686-1.345c0.494,1.041-2.188,3.258-5.99,5.008L35.58,67.368z" /> <radialGradient id="SVGID_9_" cx="51.9766" cy="64.4246" r="6.541" gradientTransform="matrix(1 0 0 -1 0 122.105)" gradientUnits="userSpaceOnUse"> <stop offset="0" style="stop-color:#B8B8B8" /> <stop offset="0.47" style="stop-color:#B6B6B6" /> <stop offset="0.64" style="stop-color:#AFAFAF" /> <stop offset="0.76" style="stop-color:#A3A3A3" /> <stop offset="0.85" style="stop-color:#929292" /> <stop offset="0.94" style="stop-color:#7D7D7D" /> <stop offset="1" style="stop-color:#666666" /> </radialGradient> <path fill="url(#SVGID_9_)" d="M53.274,51.269c3.543,0.718,5.829,4.168,5.11,7.709c-0.717,3.544-4.167,5.83-7.71,5.113 c-3.536-0.719-5.824-4.171-5.105-7.711C46.284,52.844,49.739,50.552,53.274,51.269z" /> </g> </svg>

image.png

4. 高级功能

4.1 SVG缩放控制

C#
public partial class Form1 : Form { private SvgDocument svgDoc; private float currentScale = 1.0f; private PictureBox pictureBox; private TrackBar scaleTrackBar; private Label scaleLabel; private int originalWidth; private int originalHeight; public Form1() { InitializeComponent(); // 创建PictureBox用于显示SVG pictureBox = new PictureBox { Dock = DockStyle.Fill, SizeMode = PictureBoxSizeMode.Normal, // 更改为Normal以便更好地控制缩放 BackColor = Color.White }; // 创建TrackBar用于控制缩放 scaleTrackBar = new TrackBar { Dock = DockStyle.Bottom, Minimum = 10, // 10% 的缩放 Maximum = 400, // 400% 的缩放 Value = 100, // 默认100% TickFrequency = 10 }; scaleTrackBar.ValueChanged += ScaleTrackBar_ValueChanged; // 创建标签显示当前缩放比例 scaleLabel = new Label { Text = "缩放: 100%", Dock = DockStyle.Bottom, TextAlign = ContentAlignment.MiddleCenter, Height = 30 }; // 添加控件到窗体 this.Controls.Add(pictureBox); this.Controls.Add(scaleLabel); this.Controls.Add(scaleTrackBar); LoadSvg(); } private void LoadSvg() { try { // 加载SVG文件 svgDoc = SvgDocument.Open("1.svg"); // 保存原始尺寸 originalWidth = (int)svgDoc.Width.Value; originalHeight = (int)svgDoc.Height.Value; // 初始显示 UpdateSvgDisplay(); } catch (Exception ex) { MessageBox.Show($"加载SVG文件时出错: {ex.Message}"); } } private void ScaleTrackBar_ValueChanged(object sender, EventArgs e) { currentScale = scaleTrackBar.Value / 100f; scaleLabel.Text = $"缩放: {scaleTrackBar.Value}%"; UpdateSvgDisplay(); } private void UpdateSvgDisplay() { if (svgDoc != null) { try { // 计算缩放后的尺寸 int scaledWidth = (int)(originalWidth * currentScale); int scaledHeight = (int)(originalHeight * currentScale); // 创建新的位图 var bitmap = new Bitmap(scaledWidth, scaledHeight); using (Graphics graphics = Graphics.FromImage(bitmap)) { // 设置高质量绘制 graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.Clear(Color.White); // 创建缩放矩阵 graphics.ScaleTransform(currentScale, currentScale); // 绘制SVG svgDoc.Draw(graphics, new SizeF(originalWidth, originalHeight)); } // 更新PictureBox if (pictureBox.Image != null) { pictureBox.Image.Dispose(); } pictureBox.Image = bitmap; pictureBox.Refresh(); } catch (Exception ex) { MessageBox.Show($"更新SVG显示时出错: {ex.Message}"); } } } protected override void OnFormClosing(FormClosingEventArgs e) { base.OnFormClosing(e); // 清理资源 if (pictureBox.Image != null) { pictureBox.Image.Dispose(); } } }

image.png

4.2 SVG颜色修改

SvgColorManager 类

C#
public class SvgColorManager { private SvgDocument svgDocument; private PictureBox pictureBox; private Dictionary<SvgVisualElement, ColorInfo> originalColors; // 修改存储结构 // 用于存储颜色信息的类 private class ColorInfo { public SvgPaintServer Fill { get; set; } public SvgPaintServer Stroke { get; set; } public float? StrokeWidth { get; set; } } public SvgColorManager(PictureBox pictureBox) { this.pictureBox = pictureBox ?? throw new ArgumentNullException(nameof(pictureBox)); this.originalColors = new Dictionary<SvgVisualElement, ColorInfo>(); } public bool LoadSvg(string filePath) { try { svgDocument = SvgDocument.Open(filePath); StoreOriginalColors(); UpdateDisplay(); return true; } catch (Exception ex) { MessageBox.Show($"加载SVG文件失败: {ex.Message}"); return false; } } private void StoreOriginalColors() { originalColors.Clear(); foreach (var element in svgDocument.Descendants()) { if (element is SvgVisualElement visual) { // 存储每个元素的原始颜色信息 originalColors[visual] = new ColorInfo { Fill = visual.Fill, Stroke = visual.Stroke, StrokeWidth = visual.StrokeWidth }; } } } public void ChangeElementColor(Color newColor, Type elementType = null) { if (svgDocument == null) return; foreach (var element in svgDocument.Descendants()) { if (elementType != null && element.GetType() != elementType) continue; if (element is SvgVisualElement visual) { visual.Fill = new SvgColourServer(newColor); } } UpdateDisplay(); } public void ChangeStrokeColor(Color newColor, float? strokeWidth = null) { if (svgDocument == null) return; foreach (var element in svgDocument.Descendants()) { if (element is SvgVisualElement visual) { visual.Stroke = new SvgColourServer(newColor); if (strokeWidth.HasValue) { visual.StrokeWidth = strokeWidth.Value; } } } UpdateDisplay(); } public void RestoreOriginalColors() { if (svgDocument == null) return; foreach (var element in svgDocument.Descendants()) { if (element is SvgVisualElement visual && originalColors.ContainsKey(visual)) { var originalColor = originalColors[visual]; visual.Fill = originalColor.Fill; visual.Stroke = originalColor.Stroke; if (originalColor.StrokeWidth.HasValue) { visual.StrokeWidth = originalColor.StrokeWidth.Value; } } } UpdateDisplay(); } public void ChangeElementColorById(string elementId, Color fillColor, Color? strokeColor = null) { if (svgDocument == null) return; var element = svgDocument.Descendants() .FirstOrDefault(e => e is SvgVisualElement && e.ID == elementId) as SvgVisualElement; if (element != null) { element.Fill = new SvgColourServer(fillColor); if (strokeColor.HasValue) { element.Stroke = new SvgColourServer(strokeColor.Value); } UpdateDisplay(); } } private void UpdateDisplay() { try { if (pictureBox.Image != null) { var oldImage = pictureBox.Image; pictureBox.Image = svgDocument.Draw(); oldImage.Dispose(); } else { pictureBox.Image = svgDocument.Draw(); } pictureBox.Refresh(); } catch (Exception ex) { MessageBox.Show($"更新显示失败: {ex.Message}"); } } public bool SaveSvg(string filePath) { try { svgDocument.Write(filePath); return true; } catch (Exception ex) { MessageBox.Show($"保存SVG文件失败: {ex.Message}"); return false; } } public void Dispose() { if (pictureBox?.Image != null) { pictureBox.Image.Dispose(); pictureBox.Image = null; } originalColors.Clear(); pictureBox = null; svgDocument = null; } }
C#
public partial class Form2 : Form { private SvgColorManager colorManager; public Form2() { InitializeComponent(); // 初始化ColorManager colorManager = new SvgColorManager(pictureBox1); // 加载SVG文件 colorManager.LoadSvg("1.svg"); // 确保文件存在 } private void btnChangeFill_Click(object sender, EventArgs e) { using (ColorDialog colorDialog = new ColorDialog()) { if (colorDialog.ShowDialog() == DialogResult.OK) { colorManager.ChangeElementColor(colorDialog.Color); } } } private void btnChangeStroke_Click(object sender, EventArgs e) { using (ColorDialog colorDialog = new ColorDialog()) { if (colorDialog.ShowDialog() == DialogResult.OK) { colorManager.ChangeStrokeColor(colorDialog.Color); } } } private void btnRestore_Click(object sender, EventArgs e) { colorManager.RestoreOriginalColors(); } }

image.png

4.3 SVG元素操作

C#
using Svg.Transforms; using Svg; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AppSvg01 { public class SvgElementManager { private SvgDocument svgDocument; private PictureBox pictureBox; public SvgElementManager(PictureBox pictureBox) { this.pictureBox = pictureBox ?? throw new ArgumentNullException(nameof(pictureBox)); } /// <summary> /// 加载SVG文件 /// </summary> public bool LoadSvg(string filePath) { try { svgDocument = SvgDocument.Open(filePath); UpdateDisplay(); return true; } catch (Exception ex) { MessageBox.Show($"加载SVG文件失败: {ex.Message}"); return false; } } /// <summary> /// 修改特定元素 /// </summary> public void ModifyElement(string elementId, float opacity = 1.0f, float rotation = 0, float? scaleX = null, float? scaleY = null, Color? fillColor = null) { if (svgDocument == null) return; var element = svgDocument.GetElementById(elementId); if (element != null && element is SvgVisualElement visual) { // 设置透明度 visual.Opacity = opacity; // 创建变换集合 if (visual.Transforms == null) visual.Transforms = new SvgTransformCollection(); else visual.Transforms.Clear(); // 添加旋转 if (rotation != 0) { visual.Transforms.Add(new SvgRotate(rotation)); } // 添加缩放 if (scaleX.HasValue || scaleY.HasValue) { visual.Transforms.Add(new SvgScale( scaleX ?? 1.0f, scaleY ?? scaleX ?? 1.0f )); } // 设置填充颜色 if (fillColor.HasValue) { visual.Fill = new SvgColourServer(fillColor.Value); } UpdateDisplay(); } } /// <summary> /// 添加新元素 /// </summary> public void AddElement(SvgElementType elementType, float x, float y, float width, float height, Color fillColor, Color? strokeColor = null, float strokeWidth = 1) { if (svgDocument == null) return; SvgVisualElement element = null; switch (elementType) { case SvgElementType.Rectangle: element = new SvgRectangle { X = new SvgUnit(x), Y = new SvgUnit(y), Width = new SvgUnit(width), Height = new SvgUnit(height) }; break; case SvgElementType.Circle: element = new SvgCircle { CenterX = new SvgUnit(x + width / 2), CenterY = new SvgUnit(y + height / 2), Radius = new SvgUnit(Math.Min(width, height) / 2) }; break; case SvgElementType.Ellipse: element = new SvgEllipse { CenterX = new SvgUnit(x + width / 2), CenterY = new SvgUnit(y + height / 2), RadiusX = new SvgUnit(width / 2), RadiusY = new SvgUnit(height / 2) }; break; case SvgElementType.Line: element = new SvgLine { StartX = new SvgUnit(x), StartY = new SvgUnit(y), EndX = new SvgUnit(x + width), EndY = new SvgUnit(y + height) }; break; } if (element != null) { element.Fill = new SvgColourServer(fillColor); if (strokeColor.HasValue) { element.Stroke = new SvgColourServer(strokeColor.Value); element.StrokeWidth = strokeWidth; } svgDocument.Children.Add(element); UpdateDisplay(); } } /// <summary> /// 删除元素 /// </summary> public void RemoveElement(string elementId) { if (svgDocument == null) return; var element = svgDocument.GetElementById(elementId); if (element != null) { element.Parent?.Children.Remove(element); UpdateDisplay(); } } /// <summary> /// 移动元素 /// </summary> public void MoveElement(string elementId, float deltaX, float deltaY) { if (svgDocument == null) return; var element = svgDocument.GetElementById(elementId); if (element is SvgVisualElement visual) { if (visual.Transforms == null) visual.Transforms = new SvgTransformCollection(); visual.Transforms.Add(new SvgTranslate(deltaX, deltaY)); UpdateDisplay(); } } /// <summary> /// 更新显示 /// </summary> private void UpdateDisplay() { try { if (pictureBox.Image != null) { var oldImage = pictureBox.Image; pictureBox.Image = svgDocument.Draw(); oldImage.Dispose(); } else { pictureBox.Image = svgDocument.Draw(); } pictureBox.Refresh(); } catch (Exception ex) { MessageBox.Show($"更新显示失败: {ex.Message}"); } } /// <summary> /// 清理资源 /// </summary> public void Dispose() { pictureBox.Image?.Dispose(); pictureBox = null; svgDocument = null; } } // SVG元素类型枚举 public enum SvgElementType { Rectangle, Circle, Ellipse, Line } }

6. 总结

使用SVG.NET库在WinForm中处理SVG文件是一个强大而灵活的解决方案。通过本文提供的示例和最佳实践,开发者可以轻松实现SVG文件的加载、显示、缩放和颜色修改等功能。记住要注意性能优化和资源管理,以确保应用程序的稳定性和效率。

本文作者:rick

本文链接:

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