当前位置: 首页 > news >正文

Skia如何绘制几何图形

应用程序(网页、桌面应用或移动应用)大多数都是由基本的几何图形构成的。那我们该如何使用 Skia 绘制基本的几何图形。

画矩形

void drawRect(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorRED);paint.setStroke(true);paint.setStrokeWidth(16);SkRect rect = SkRect::MakeLTRB(w / 2 - 100, h / 2 - 100, w / 2 + 100, h / 2 + 100);bool isPointInRect = rect.contains(w / 2, h / 2);canvas->drawRect(rect, paint);
}
void paint(const HWND hWnd)
{//...省略了一些代码(前一章介绍过)drawRect(canvas.get());//...省略了一些代码(前一章介绍过)
}
  1. drawRect 方法负责在窗口中绘制矩形。 窗口重绘时执行 paint 方法,在此方法中,把画布指针传递给 drawRect 方法,让 drawRect方法在窗口中绘制矩形。

  2. 非填充绘图对象。 默认情况下绘图对象 SkPaint 为填充状态,当执行 paint.setStroke(true) 代码后,绘图对象就变成了非填充状态。 绘图对象的 setStrokeWidth 方法,用于设置边框粗细。

  3. 用另一种方式创建矩形对象。 使用 SkRect 类型的静态方法 MakeXYWH 创建矩形对象。 除了这种方式设置矩形外,还可以用 SkRect::MakeLTRB 方法创建矩形。

  4. setLTRB 方法的四个参数分别是矩形的 left(左)、top(上)、right(右)、bottom(下)四个位置。 值得注意的是此处设置的四个值,left的值不必小于right的值,top的值也不必小于bottom的值,setLTRB方法内部会安排好这些值。 此处创建的矩形(长和宽均为200)位于窗口的中心。

  5. 判断一个点是否位于矩形内部 使用矩形的contains方法来判断一个点是否在矩形中。 很多 Skia 内置的几何元素都有这个方法,比如圆,椭圆,闭合得路径等,它对于一些交互应用程序、游戏程序非常重要。

运行程序得到的结果如下图所示:

画点

使用 Skia 画一个点非常简单,只要给出点的坐标即可,如下代码所示:

void drawPoint(SkCanvas* canvas)
{SkPaint paint;paint.setColor(SK_ColorRED);paint.setStrokeWidth(16);canvas->drawPoint(w/2,h/2, paint);
}

SkCanvas 对象的 drawPoint 方法负责绘制点,这个方法的前两个参数就是点的x和y坐标。

值得注意的是 SkPaint 的 setStrokeWidth 方法同样可以应用到 点 上。

把 StrokeWidth 设置成 16 ,这样画的点就大了。

上述程序运行结果如下图所示:

要绘制一系列的点,可以让 SkCanvas 对象绘制一个 SkPoint 数组,如下代码所示:

// #include "include/core/SkPoint.h"
void drawPoint2(SkCanvas* canvas)
{SkPaint paint;paint.setColor(SK_ColorRED);paint.setStrokeWidth(16);SkPoint pts[]{ SkPoint::Make(60, 60),SkPoint::Make(w / 2, h / 2),SkPoint::Make(w - 60, h - 60) };canvas->drawPoints(SkCanvas::PointMode::kPoints_PointMode, 3, pts, paint);
}

SkPoint 类型用于表示一个点,它持有两个 float 类型的数据分别表示点的 x坐标 和 y坐标。

SkCanvas 对象的 drawPoints 方法的第一个参数为绘制点的方式,

kPoints_PointMode枚举用于表示只是绘制点,用这个参数来控制是否需要用线把点连起来或是否需要把这些点连成一个多边形等,

drawPoints方法的第二个参数为数组内包含几个点,第三个参数为SkPoint数组。

程序的运行结果如下图所示:

画线

画直线也是非常常见的需求,如下代码就是 Skia 绘制直线的示例代码:

void drawLine(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorRED);paint.setAntiAlias(true);paint.setStroke(true);paint.setStrokeWidth(16);paint.setStrokeCap(SkPaint::Cap::kRound_Cap);canvas->drawLine(80, 80, w - 80, h - 80, paint);
}

这段代码从窗口的左上角(80,80)处开始,到窗口的右下角(w - 80, h - 80)绘制了一条宽度为16的直线。

通过 paint.setStrokeCap 方法设置了直线两端的样式:让线段两端呈现一个圆帽的形式。

kRound_Cap同样可以应用到画点的工作上,这样做可以让一个方形的点,变成一个圆形的点。

程序运行结果如下图所示:

画圆

前面使用 SKRect 绘制了矩形,接下来我们绘制一个圆,如下代码所示:

void drawCircle(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorRED);auto x = w / 2;auto y = h / 2;auto r = std::min(x-10, y-10);canvas->drawCircle(x, y, r, paint); //此方法用于绘制正圆
}

其中 x 为圆心的 x 坐标,y 为圆心的 y 坐标,r 为圆的半径。

使圆的半径小于窗口宽度或高度的一半(使圆始终在窗口内)。

运行代码你将在窗口中看到一个红色的圆,如下图所示:

抗锯齿

如果你仔细观察这个圆的边缘,你会发现圆的边缘存在锯齿,如下图所示:

如果你希望消除这些锯齿,让圆的边缘更平滑,那么你就需要设置 paint 对象的抗锯齿属性,如下代码所示:

paint.setAntiAlias(true);

抗锯齿是每一个渲染引擎都要面临的问题和重要任务之一。

设置了抗锯齿之后,再运行代码,圆的边缘就平滑了,如下图所示:

抗锯齿.png

画椭圆

绘制正圆的业务场景比较少,大部分是绘制椭圆,用 Skia 绘制椭圆也非常简单,如下代码所示:

void drawEllipse(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorRED);paint.setAntiAlias(true);SkRect rect;rect.setLTRB(10, 10, w - 10, h - 10); //椭圆与窗口边缘距离10像素canvas->drawOval(rect, paint); //此方法用于绘制椭圆
}

上面代码 使用一个矩形来控制椭圆的大小和位置 。

当然如果矩形的长宽相等(正方形),那么绘制出来的就是正圆。

运行程序,如下图所示:

椭圆.png

画圆角矩形

如果你开发过前端网页,那么你肯定知道圆角矩形是非常常见的网页元素。

Skia 也为绘制圆角矩形提供了特定的 API ,如下代码所示:

#include "include/core/SkRRect.h"
void drawRRect(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorRED);paint.setAntiAlias(true);SkRect rect;rect.setLTRB(60, 60, w -60, h - 60);SkVector radii[4]{{16, 16},  // 矩形左上角圆角尺寸;{16, 16},  // 矩形右上角圆角尺寸;{16, 16},  // 矩形右下角圆角尺寸;{16, 16}   // 矩形左下角圆角尺寸;};SkRRect rr;rr.setRectRadii(rect, radii);canvas->drawRRect(rr, paint); //绘制圆角矩形
}

我们用 SKRRect 类型来表示圆角矩形。

SKRRect 是基于一个矩形(SkRect)创建的,而且开发者可以自由的定义每个角的圆角尺寸。

上述代码中 SkVector 数组 radii 中存储的是四个圆角的大小。

SkVector 实际上就是 SkPoint 。它并不是一个容器

每个圆角由两个值组成,第一个值是水平方向上的圆角半径,第二个值是垂直方向上的圆角半径,一般情况下这两个值是相同的。

上述代码运行后的效果如下图所示:

圆角矩形.png

画圆弧

使用Skia绘制圆弧也非常简单,如下代码所示:

void drawArc(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorRED);paint.setAntiAlias(true);paint.setStroke(true);paint.setStrokeWidth(16);paint.setStrokeCap(SkPaint::Cap::kRound_Cap);SkRect rect;rect.setLTRB(60, 60, w - 60, h - 60);canvas->drawArc(rect, 0, -90, false, paint); 
}

使用 canvas 的 drawArc 方法绘制圆弧,第一个参数是一个矩形(SkRect),

第二个参数是圆弧的起点角度,此处传入 0 ,代表着以矩形右侧边的中心点为起点开始绘制。

第三个参数为圆弧的终点角度,此处传入-90,代表着以矩形的顶边的中点为终点。

也就是说我们以逆时针方向绘制这段圆弧,如果传入的是90 则以顺时针方向绘制圆弧,终点将落在矩形的底边中点。

第四个参数为 是否把起点和终点与椭圆中心连接 ,如果这个参数设置为true,那么它就是一个扇形,不再仅仅是一个圆弧了。

运行代码,得到的结果如下图所示:

圆弧.png

如何使用 Skia 绘制基本的几何元素:点、线、圆、方、弧,你会了吗?

相关文章:

  • 使用xdocreport导出word
  • 【QT常用技术讲解】多线程执行后台命令行的两种方式(后台运行和返回打印信息)
  • API是什么意思?如何实现开放API?
  • 惊艳呈现:探索数据可视化的艺术与科学
  • 嵌入式开发之STM32学习笔记day21
  • 软件功能模块归属论证方法
  • C++中的概念(Concepts)
  • C++.OpenGL (11/64)材质(Materials)
  • Spring Boot 实现流式响应(兼容 2.7.x)
  • 【Redis】哨兵模式
  • 【C语言】统计孪生素数对高效解法
  • vsCode使用本地低版本node启动配置文件
  • 1panel面板中部署SpringBoot和Vue前后端分离系统 【图文教程】
  • 解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
  • 氛围编程时代来临:本地化智能分析破解老项目 AI 编程困局
  • 【Go语言基础【6】】字符串格式化说明
  • 保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
  • MySQL体系架构解析(二):MySQL目录与启动配置全解析
  • 命令行以TLS/SSL显式加密方式访问FTP服务器
  • for AC500 PLCs 3ADR025003M9903的安全说明
  • 做进料加工在哪个网站上做/网推app怎么推广
  • 手机版网站建设开发/中国时事新闻网
  • 即墨做网站的/seo外链推广平台
  • 中国糕点网页设计网站/售卖链接
  • 我国经济总量/郑州百度关键词seo
  • 罗湖网站建设报价/免费好用的网站