持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
阅读本文大概需要 5 分钟
前言
甲方提了个需求,要求应用上加上水印。
水印中文字的排布比较有规律,想出了两个方案
- 使用网格布局,在特定的位置填入水印文字
- Canvas 自己画文字
代码实现
使用网格布局
新建一个 UserControl,因为水印的特性,我们选择继承 UniformGrid,这样添加元素简单方便。
public class WatermarkControl : UniformGrid
{
public WatermarkControl()
{
// 初始化参数
InitDefaultParams();
// 初始化水印内容,并添加到布局中
InitWatermarkContent();
// 初始化旋转角度
InitRotate();
}
}
因为这种方法可控性不强,且旋转的时候不太好看,最终没有采用该方法,感兴趣的朋友可以通过文末的 Gitee 地址自行查看
自己 Canvas 画
项目最终用了这种方法,灵活的一批。 总共分为以下几个部分
- 设置水印透过点击事件
- 计算控件的宽高,用于后续写字
- 计算水印文字的宽度,用于计算下一个文字的偏移量
- 一个循环,遍历画水印文字
成品的使用方法,可以自定义以下属性:
- FontSize
- Angle
- Foreground
- Text
- row space
- column space
<Grid>
<!--... layout yourself-->
<local:WatermarkCanvas x:Name="watermarkCanvas"
WatermarkFontSize="14"
WatermarkAngle="-15"
WatermarkForeground="#6666"
WatermarkText="Hello BigFlowerFat"
WatermarkTextWidthSpaceMultiple="2"
WatermarkTextHeightSpaceMultiple="8"/>
</Grid>
1. 水印透过点击事件
// 初始化默认参数让
private void InitDefaultParams()
{
// 因为水印要覆盖到界面上层,所以需要让水印能透过鼠标点击
this.IsHitTestVisible = false;
}
2. 界面渲染时,获取基本参数
protected override void OnRender(DrawingContext drawingContext)
{
// 获取该控件的基本参数:宽、高、文字占用的宽度
InitSizeParams();
// 画水印文字
DrawTexts(drawingContext);
}
3. 画水印文字
画水印文字就比较简单了,先算出 水印有多少列 = 布局宽度 / 文字宽度,然后循环画就完了。使用方法也很简单 DrawText(文字,坐标)
drawingContext.DrawText(ft, point);
/// <summary>
/// draw the watermark text
/// </summary>
/// <param name="drawingContext"></param>
private void DrawTexts(DrawingContext drawingContext)
{
// rotate 旋转
drawingContext.PushTransform(new RotateTransform(WatermarkAngle, 0, 0));
FormattedText ft = new FormattedText(WatermarkText,
CultureInfo.InvariantCulture,
FlowDirection.LeftToRight,
new Typeface(WatermarkFontFamily),
WatermarkFontSize, WatermarkForeground);
// calculate the the text's row and column number 根据文字宽高、布局宽高,计算要画多少个水印字
int rowNumber = (int)(mHeight / WatermarkFontSize / 10) + 5;
int columnNumber = (int)(mWidth / mTextWidth) + 2;
// draw text 写字
for (int row = -5; row < rowNumber; row++)
{
for (int column = -1; column < columnNumber; column++)
{
// Stagger adjacent rows
double offset = row % 2 == 0 ? 0 : mTextWidth / 2;
Point point = new Point(mTextWidth * column - offset, WatermarkFontSize * row * WatermarkTextHeightSpaceMultiple);
drawingContext.DrawText(ft, point);
}
}
}
后记
文章代码已经上传到 gitee.com/bigflowerfa…
该项目中也还有其他有意思的 Demo