在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一、前言 最近因业务需要开发了一款地产类微信小程序,开发的过程中需要实现分享给好友和分享到朋友圈的功能。好友分享可以直接调用微信小程序API来实现,调用时需提供一张5:4的图片,如果不提供则使用默认截图,为了更好的效果我们一般会选择自行生成图片。而分享到朋友圈的功能由于小程序并未开放,则需要我们生成一张长图供用户自行发送朋友圈。下面我以生成好友好享图片为例来讲讲如何在.Net Core环境中使用SkiaSharp绘制图片。
(图1:最终效果图)
二、SkiaSharp类库介绍 SkiaSharp是一个基于Google的Skia图形库(https://skia.org/)打造的供.Net平台使用的跨平台的2D绘图API类库。它提供一个全面的2D绘图API,能用在移动端、服务端和桌面端呈现图像。 目前SkiaSharp可供以下平台使用:
github地址:https://github.com/mono/SkiaSharp 三、准备工作 1、新建一个.Net Core API项目,这里我命名为ShareImage。 2、安装SkiaSharp,使用NuGet命令或者包管理器安装: nuget install SkiaSharp 3、准备底图 分析最终效果图(图1),找出不会变化的部分,让UI抠下来作为底图。可以将底图保存在项目的Images目录下,我这里存为bg.png。 (图2:底图) 4、准备字体 我这里中文部分用了PingFangSC Regular字体,数字部分用了PingFangSC Medium字体。在项目根目录下新建Fonts目录,复制这两种字体,我这里分别命名为PIngfangScRegular.ttf和PingfangScMedium.ttf。由于载入字体是一个耗时的操作,因此我们可以定义一个静态类TypeFace,预先将字体载入。 using SkiaSharp; namespace ShareImage { public static class Typeface { public static TypefaseWithMuiltWeight PingFang = new TypefaseWithMuiltWeight { Regular = SKTypeface.FromFile("Fonts/PIngfangScRegular.ttf"), Medium = SKTypeface.FromFile("Fonts/PingfangScMedium.ttf") }; } public class TypefaseWithMuiltWeight { public SKTypeface Regular { get; set; } public SKTypeface Medium { get; set; } } } 四、绘图 1、读取要写入的数据,一般这类数据从数据库读取,这里我直接定义示例数据 //示例数据 var shop = new ShopInfo { Name = "李学雯", Company = "某某地产", ViewNum = "1024", Nums = new string[] { "128", "64", "96", "48" }, Location = "广州市-黄埔区", Des = "专业为大宗资产提供中介、法律、会计服务,买卖厂房、仓库、土地请找我们为您提供更专业更安心的服务" }; 2、载入底图并初始化画布 //载入底图 var bmp = SKBitmap.Decode("Images/cardShopBg.png"); //初始化画布 var canvas = new SKCanvas(bmp); 3、画头像 //保存当前画布状态,即正常全图绘制状态 canvas.Save(); //定义圆形头像路径 var avatarPath = new SKPath(); avatarPath.AddCircle(114, 120, 70); //在当前画布上剪切出头像路径,作为当前绘制区域 canvas.ClipPath(avatarPath, SKClipOperation.Intersect, true); //载入头像图片,这里用Images/avatar0.jpg文件代替 using (var avatarImage = SKImage.FromEncodedData(SKData.Create("Images/avatar0.jpg"))) { //定义绘制头像的位置和尺寸 var rect = SKRect.Create(44, 50, 140, 140); //绘制头像 canvas.DrawImage(avatarImage, rect); } //恢复画布状态为全图绘制状态 canvas.Restore(); 由于头像是圆形,而我们获取到的头像一般是方形,所以我们需要在底图上定义一个圆形区域作为本次画图的区域,在绘制完成后需要恢复为全图绘制状态,否则就无法继续接下来的写字等操作了。 4、写单行文本(以姓名为例) //定义画笔 using (var paint = new SKPaint()) { //字体 paint.Typeface = Typeface.PingFang.Regular; //字体大小 paint.TextSize = 48; //字体颜色 paint.Color = SKColors.White; //抗锯齿不能少 paint.IsAntialias = true; //调用画单行文字扩展方法 canvas.DrawSingleLineText(shop.Name, 225, 62, paint); } //画单行文字扩展方法 public static void DrawSingleLineText(this SKCanvas canvas,string text,float x,float y,SKPaint paint) { //定义一个矩形,此矩形为计算文字区域的结果 var tRect = new SKRect(); //计算文字占用区域 paint.MeasureText(text, ref tRect); //调用画布的画字方法 canvas.DrawText(text, x - tRect.Left, y - tRect.Top, paint); } 写文字的时候需要注意有一个坐标编移量,可以直接调用canvas.DrawText(text, 0, 0, paint)来观察一下,写出文字的起点并非是0,0。所以我们在写出文字的时候要算出这个偏移量并抵消掉。这个偏移量是如何产生的本人并不知道,如果有热心网友能帮忙解答一下就好了! 5、画带色矩形背景框(见图1公司名“某某地产”黄色矩形背景) //定义画笔 using (var paint = new SKPaint()) { //字体 paint.Typeface = Typeface.PingFang.Regular; //字体大小 paint.TextSize = 26; //抗锯齿 paint.IsAntialias = true; //颜色 paint.Color = SKColor.Parse("#FFB33E"); //由于这个黄色背景矩形长度是根据文字长度而定的,所以我们需要计算文字的区域大小 var tRect = new SKRect(); //文字长度 var tWidth = paint.MeasureText(shop.Company,ref tRect); //矩形背景区域 var rect = SKRect.Create(224, 134, tWidth + 20, 40); //画矩形 canvas.DrawRect(rect, paint); } 6、写多行文字。由于本人并未在SkiaSharp文档中找到写多行文字的方法,所以写一个扩展方法来写出多行文字: /// </summary> /// <param name="canvas">画布</param> /// <param name="text">多行文字</param> /// <param name="x">x坐标</param> /// <param name="y">y坐标</param> /// <param name="paint">画笔</param> /// <param name="maxWidth">单行文字最大宽度</param> /// <param name="maxLines">最大行数,如果超出,则使用...</param> public static void DrawMuiltLineText(this SKCanvas canvas, string text, float x, float y, SKPaint paint, float maxWidth, int maxLines) { //已写出行数 int lines = 0; //省略号宽度 var ellipseWidth = paint.MeasureText("..."); //如果文字没写完且已写行数小于最大行数,则继续写出 while (!string.IsNullOrEmpty(text) && lines < maxLines) { //单行文字 string lineStr; //单行文字长度 long strLength; //非最后一行 if (lines != maxLines - 1) { //调用BreakText方法,可计算指定宽度能写出多少文字 strLength = paint.BreakText(text, maxWidth, out float ww, out lineStr); } //最后一行 else { //调用BreakText方法计算单行文字长度,这里需减去省略号宽度 strLength = paint.BreakText(text, maxWidth - ellipseWidth, out float ww, out lineStr); //假如字还没写完,需加省略号 if (strLength < text.Length) { lineStr += "..."; } } //文字矩形 var tRect = new SKRect(); //计算文字矩形 paint.MeasureText(lineStr, ref tRect); //计算坐标 var tPoint = new SKPoint { X = x - tRect.Left, //这里注意Y坐标需要加上行高 Y = y + lines * paint.FontSpacing - tRect.Top }; //写出一行文字 canvas.DrawText(lineStr, tPoint, paint); //已写出行数加1 lines++; //取剩余文字 text = text.Substring((int)strLength); } } 五、总结 SkiaSharp是一个非常强大且易用的.Net平台绘图库,这里以绘制小程序分享图为例仅列出一些基础用法。由于本人水平有限,以上代码如有纰漏、错误或有待优化之处,欢迎大家指出! 附SkiaSharp文档地址:https://docs.microsoft.com/en-us/dotnet/api/SkiaSharp
|
请发表评论