SVG.NET是一个强大的开源库,专门用于在.NET应用程序中处理SVG(Scalable Vector Graphics)文件。本文将详细介绍如何在WinForm应用程序中使用SVG.NET库来显示和操作SVG图片。
环境准备
安装SVG.NET库
在Visual Studio中,通过NuGet包管理器安装Svg包:
或在包管理器控制台中执行:
添加必要的引用
using Svg;
using System.Drawing;
using System.Drawing.Imaging;
基础使用
加载并显示SVG
private void btnLoad_Click(object sender, EventArgs e)
{
var svgDocument = SvgDocument.Open("1.svg");
var bitmap = svgDocument.Draw();
pictureBox1.Image = bitmap;
}
1.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>
高级功能
SVG缩放控制
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();
}
}
}
SVG颜色修改
SvgColorManager 类
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;
}
}
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();
}
}
SVG元素操作
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
}
}
总结
使用SVG.NET库在WinForm中处理SVG文件是一个强大而灵活的解决方案。通过本文提供的示例和最佳实践,开发者可以轻松实现SVG文件的加载、显示、缩放和颜色修改等功能。记住要注意性能优化和资源管理,以确保应用程序的稳定性和效率。
该文章在 2024/11/13 14:56:22 编辑过