第07章 - 样式系统详解
第07章:样式系统详解
7.1 样式系统概述
7.1.1 样式类型体系
Mapsui 提供了丰富的样式类型来定义要素的视觉外观:
IStyle (接口)
│
BaseStyle (基类)
│
┌───────────────────┼───────────────────┐
│ │ │
VectorStyle SymbolStyle LabelStyle
│ │
│ ┌──────┼──────┐
│ │ │ │
│ ImageStyle │ CalloutStyle
│ │
└──────────────RasterStyle
7.1.2 IStyle 接口
public interface IStyle
{
/// <summary>
/// 最小可见分辨率
/// </summary>
double MinVisible { get; set; }
/// <summary>
/// 最大可见分辨率
/// </summary>
double MaxVisible { get; set; }
/// <summary>
/// 是否启用
/// </summary>
bool Enabled { get; set; }
/// <summary>
/// 不透明度 (0-1)
/// </summary>
double Opacity { get; set; }
}
7.2 VectorStyle - 矢量样式
7.2.1 基本属性
VectorStyle 用于线和面要素的样式定义:
var vectorStyle = new VectorStyle
{
// 填充样式
Fill = new Brush(new Color(255, 0, 0, 128)), // 半透明红色
// 边框/轮廓样式
Outline = new Pen(Color.Black, 2),
// 线样式(用于线要素)
Line = new Pen(Color.Blue, 3)
{
PenStyle = PenStyle.Dash,
StrokeCap = PenStrokeCap.Round,
StrokeJoin = StrokeJoin.Round
}
};
7.2.2 Brush - 画刷
// 纯色画刷
var solidBrush = new Brush(Color.Red);
// 带透明度的画刷
var transparentBrush = new Brush(new Color(255, 0, 0, 128));
// 从十六进制颜色创建
var hexBrush = new Brush(Color.FromString("#FF5722"));
// 使用图片填充
var imageBrush = new Brush
{
FillStyle = FillStyle.Bitmap,
// BitmapId = ... // 设置图片 ID
};
7.2.3 Pen - 画笔
// 基本画笔
var basicPen = new Pen(Color.Blue, 2);
// 自定义画笔
var customPen = new Pen
{
Color = Color.Green,
Width = 3,
PenStyle = PenStyle.Dash, // 虚线
StrokeCap = PenStrokeCap.Round, // 圆形线帽
StrokeJoin = StrokeJoin.Round, // 圆形连接
DashArray = new float[] { 5, 3 } // 自定义虚线模式
};
// 画笔样式枚举
public enum PenStyle
{
Solid, // 实线
Dash, // 虚线
Dot, // 点线
DashDot, // 点划线
DashDotDot, // 双点划线
UserDefined // 自定义
}
7.2.4 多边形和线样式示例
// 多边形样式
public static VectorStyle CreatePolygonStyle()
{
return new VectorStyle
{
Fill = new Brush(new Color(66, 133, 244, 100)),
Outline = new Pen(new Color(66, 133, 244), 2)
{
StrokeJoin = StrokeJoin.Round
}
};
}
// 线样式
public static VectorStyle CreateLineStyle()
{
return new VectorStyle
{
Line = new Pen(Color.Orange, 4)
{
StrokeCap = PenStrokeCap.Round,
StrokeJoin = StrokeJoin.Round
}
};
}
// 道路样式(带边框效果)
public static IStyle[] CreateRoadStyle()
{
return new IStyle[]
{
// 底层(边框)
new VectorStyle
{
Line = new Pen(Color.Gray, 8)
{
StrokeCap = PenStrokeCap.Round
}
},
// 顶层(填充)
new VectorStyle
{
Line = new Pen(Color.White, 6)
{
StrokeCap = PenStrokeCap.Round
}
}
};
}
7.3 SymbolStyle - 符号样式
7.3.1 基本属性
SymbolStyle 用于点要素的样式定义:
var symbolStyle = new SymbolStyle
{
// 大小缩放
SymbolScale = 1.0,
// 填充
Fill = new Brush(Color.Red),
// 轮廓
Outline = new Pen(Color.White, 2),
// 偏移
SymbolOffset = new Offset(0, 10),
// 旋转角度(度)
SymbolRotation = 45,
// 是否随地图旋转
RotateWithMap = false
};
7.3.2 符号类型
// 圆形符号(默认)
var circleSymbol = new SymbolStyle
{
SymbolScale = 0.5,
Fill = new Brush(Color.Blue),
Outline = new Pen(Color.White, 1)
};
// 方形符号
var squareSymbol = new SymbolStyle
{
SymbolScale = 0.5,
SymbolType = SymbolType.Rectangle,
Fill = new Brush(Color.Green)
};
// 三角形符号
var triangleSymbol = new SymbolStyle
{
SymbolScale = 0.5,
SymbolType = SymbolType.Triangle,
Fill = new Brush(Color.Yellow)
};
7.3.3 Offset - 偏移
// 绝对偏移(像素)
var absoluteOffset = new Offset(0, -20); // 向上偏移 20 像素
// 相对偏移
var relativeOffset = new RelativeOffset(0, -0.5); // 相对于符号高度偏移
7.4 ImageStyle - 图像样式
7.4.1 使用图像作为符号
// 从嵌入资源加载图像
var imageStyle = new ImageStyle
{
ImageSource = "embedded://MyApp.Resources.marker.png"
};
// 从 URL 加载图像
var urlImageStyle = new ImageStyle
{
ImageSource = "https://example.com/marker.png"
};
// 从文件加载图像
var fileImageStyle = new ImageStyle
{
ImageSource = "file://path/to/marker.png"
};
7.4.2 配置图像样式
var imageStyle = new ImageStyle
{
ImageSource = "embedded://MyApp.Resources.marker.png",
// 缩放
SymbolScale = 0.5,
// 偏移(使图像底部对准点位置)
SymbolOffset = new Offset(0, -16),
// 旋转
SymbolRotation = 0,
// 是否随地图旋转
RotateWithMap = false
};
7.4.3 SVG 图像支持
// 使用 SVG 图像
var svgStyle = new ImageStyle
{
ImageSource = "embedded://MyApp.Resources.icon.svg",
SymbolScale = 1.0
};
7.5 LabelStyle - 标签样式
7.5.1 基本标签样式
var labelStyle = new LabelStyle
{
// 文本内容
Text = "北京",
// 字体设置
Font = new Font
{
FontFamily = "Microsoft YaHei",
Size = 14,
Bold = false,
Italic = false
},
// 颜色
ForeColor = Color.Black,
BackColor = new Brush(Color.White),
// 偏移
Offset = new Offset(0, -25),
// 对齐
HorizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center,
VerticalAlignment = LabelStyle.VerticalAlignmentEnum.Top,
// 光晕效果
Halo = new Pen(Color.White, 2)
};
7.5.2 动态标签文本
// 使用要素属性作为标签文本
var dynamicLabelStyle = new LabelStyle
{
LabelColumn = "name", // 使用 "name" 属性的值作为标签
Font = new Font { Size = 12 },
ForeColor = Color.Black
};
// 使用格式化委托
var formattedLabelStyle = new LabelStyle
{
LabelMethod = feature =>
{
var name = feature["name"]?.ToString() ?? "";
var pop = feature["population"];
return $"{name}\n人口: {pop:N0}";
},
Font = new Font { Size = 10 }
};
7.5.3 标签优化
// 避免标签重叠
var optimizedLabelStyle = new LabelStyle
{
Text = "Label",
CollisionDetection = true, // 启用碰撞检测
// 优先级(数值越高越优先显示)
Priority = 1
};
7.6 CalloutStyle - 气泡样式
7.6.1 基本气泡样式
var calloutStyle = new CalloutStyle
{
// 标题和副标题
Title = "北京",
Subtitle = "中国首都",
// 气泡外观
BalloonDefinition = new CalloutBalloonDefinition
{
RectRadius = 10,
ShadowOffset = new Offset(4, 4),
Padding = 8
},
// 箭头位置
ArrowAlignment = ArrowAlignment.Bottom,
// 锚点偏移
Offset = new Offset(0, -20),
// 颜色
TitleFontColor = Color.Black,
SubtitleFontColor = Color.Gray,
Color = Color.White,
StrokeColor = Color.LightGray
};
7.6.2 自定义内容气泡
// 使用自定义内容
var customCallout = new CalloutStyle
{
Type = CalloutType.Custom,
Content = CreateCustomCalloutContent(), // 返回 SKImage
ArrowAlignment = ArrowAlignment.Bottom,
Offset = new Offset(0, -10)
};
private SKImage CreateCustomCalloutContent()
{
// 使用 SkiaSharp 创建自定义内容
var info = new SKImageInfo(200, 100);
using var surface = SKSurface.Create(info);
var canvas = surface.Canvas;
// 绘制背景
canvas.Clear(SKColors.White);
// 绘制文本
using var paint = new SKPaint
{
Color = SKColors.Black,
TextSize = 14,
IsAntialias = true
};
canvas.DrawText("自定义气泡内容", 10, 50, paint);
return surface.Snapshot();
}
7.7 样式集合与分层样式
7.7.1 StyleCollection - 样式集合
// 使用样式集合为要素应用多个样式
var styleCollection = new StyleCollection
{
// 底层样式 - 阴影效果
new SymbolStyle
{
SymbolScale = 0.6,
Fill = new Brush(new Color(0, 0, 0, 100)),
SymbolOffset = new Offset(3, -3)
},
// 主体样式
new SymbolStyle
{
SymbolScale = 0.5,
Fill = new Brush(Color.Red),
Outline = new Pen(Color.White, 2)
},
// 标签样式
new LabelStyle
{
LabelColumn = "name",
Font = new Font { Size = 12 },
ForeColor = Color.Black,
Offset = new Offset(0, -20)
}
};
7.7.2 要素级别样式
// 在要素上设置样式
var feature = new PointFeature(point);
feature.Styles = new List<IStyle>
{
new SymbolStyle
{
SymbolScale = 0.5,
Fill = new Brush(Color.Blue)
},
new LabelStyle
{
Text = "Feature Label",
Offset = new Offset(0, -20)
}
};
7.8 专题样式
7.8.1 ThemeStyle - 专题样式
using Mapsui.Styles.Thematics;
// 创建专题样式
var themeStyle = new ThemeStyle(feature =>
{
var value = Convert.ToDouble(feature["value"]);
return new VectorStyle
{
Fill = new Brush(GetColorForValue(value))
};
});
private Color GetColorForValue(double value)
{
if (value < 100) return Color.Green;
if (value < 500) return Color.Yellow;
if (value < 1000) return Color.Orange;
return Color.Red;
}
7.8.2 分级符号
// 根据属性值设置不同大小的符号
var graduatedStyle = new ThemeStyle(feature =>
{
var population = Convert.ToDouble(feature["population"]);
var scale = Math.Log10(population) / 10; // 对数缩放
return new SymbolStyle
{
SymbolScale = Math.Max(0.2, Math.Min(scale, 2.0)),
Fill = new Brush(Color.Blue),
Outline = new Pen(Color.White, 1)
};
});
7.8.3 分类样式
// 根据类别显示不同样式
var categoryStyle = new ThemeStyle(feature =>
{
var category = feature["type"]?.ToString();
return category switch
{
"restaurant" => CreateRestaurantStyle(),
"hotel" => CreateHotelStyle(),
"shop" => CreateShopStyle(),
_ => CreateDefaultStyle()
};
});
private IStyle CreateRestaurantStyle()
{
return new ImageStyle
{
ImageSource = "embedded://MyApp.Resources.restaurant.png",
SymbolScale = 0.5
};
}
7.9 样式工厂
7.9.1 创建样式工厂类
public static class StyleFactory
{
public static IStyle CreatePointStyle(
Color fillColor,
Color? outlineColor = null,
double scale = 0.5,
double outlineWidth = 1)
{
return new SymbolStyle
{
SymbolScale = scale,
Fill = new Brush(fillColor),
Outline = outlineColor.HasValue
? new Pen(outlineColor.Value, outlineWidth)
: null
};
}
public static IStyle CreateLineStyle(
Color color,
double width = 2,
PenStyle penStyle = PenStyle.Solid)
{
return new VectorStyle
{
Line = new Pen(color, width)
{
PenStyle = penStyle,
StrokeCap = PenStrokeCap.Round,
StrokeJoin = StrokeJoin.Round
}
};
}
public static IStyle CreatePolygonStyle(
Color fillColor,
Color? outlineColor = null,
double outlineWidth = 1)
{
return new VectorStyle
{
Fill = new Brush(fillColor),
Outline = outlineColor.HasValue
? new Pen(outlineColor.Value, outlineWidth)
: null
};
}
public static IStyle CreateLabelStyle(
string text,
Color? foreColor = null,
double fontSize = 12,
Offset? offset = null)
{
return new LabelStyle
{
Text = text,
ForeColor = foreColor ?? Color.Black,
Font = new Font { Size = fontSize },
Offset = offset ?? Offset.Zero,
Halo = new Pen(Color.White, 2)
};
}
public static IStyle CreateMarkerStyle(
string imageSource,
double scale = 1.0,
Offset? offset = null)
{
return new ImageStyle
{
ImageSource = imageSource,
SymbolScale = scale,
SymbolOffset = offset ?? Offset.Zero
};
}
}
7.9.2 使用样式工厂
// 使用样式工厂创建样式
var pointLayer = new MemoryLayer
{
Features = pointFeatures,
Style = StyleFactory.CreatePointStyle(
Color.Red,
Color.White,
scale: 0.6
)
};
var lineLayer = new MemoryLayer
{
Features = lineFeatures,
Style = StyleFactory.CreateLineStyle(
Color.Blue,
width: 3,
penStyle: PenStyle.Dash
)
};
7.10 本章小结
本章详细介绍了 Mapsui 的样式系统:
- 样式类型体系:IStyle 接口和各种样式类
- VectorStyle:矢量样式,用于线和面
- SymbolStyle:符号样式,用于点
- ImageStyle:图像样式,使用图片作为符号
- LabelStyle:标签样式,显示文本标注
- CalloutStyle:气泡样式,显示信息气泡
- 样式集合:组合多个样式
- 专题样式:根据属性值动态设置样式
- 样式工厂:统一创建样式的工厂类
在下一章中,我们将学习 Mapsui 的小部件(Widget)系统。
7.11 思考与练习
- 创建一个根据数值显示渐变色的专题样式。
- 实现一个带有阴影效果的自定义标签样式。
- 设计一个支持多种符号类型的 POI 图层。
- 创建一个道路分级显示的样式(不同等级道路不同宽度和颜色)。
- 实现一个交通状态可视化样式(根据拥堵程度显示不同颜色)。

浙公网安备 33010602011771号