Skia如何绘制几何图形

news2025/6/7 13:10:34

应用程序(网页、桌面应用或移动应用)大多数都是由基本的几何图形构成的。那我们该如何使用 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 绘制基本的几何元素:点、线、圆、方、弧,你会了吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2402931.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring:实例化类过程中方法执行顺序。

如题。在实例化Bean时,会根据配置依次调用方法。在此测试代码如下: 在测试类中继承接口InitializingBean,接口InterfaceUserService(该接口为自定义,只是定义set方法)。 InterfaceUserService&#xff0c…

设置应用程序图标

(1)找一张图片 (2)然后转ico图片 在线生成透明ICO图标——ICO图标制作 验证16x16就可以 降低exe大小 (3) 在xxx.pro修改 添加 (4) 删除 build 和 xxxpro_user文件 (5)编译project 和运行xx.exe (6)右键 设置快捷方式

「基于连续小波变换(CWT)和卷积神经网络(CNN)的心律失常分类算法——ECG信号处理-第十五课」2025年6月6日

一、引言 心律失常是心血管疾病的重要表现形式,其准确分类对临床诊断具有关键意义。传统的心律失常分类方法主要依赖于人工特征提取和经典机器学习算法,但这些方法往往受限于特征选择的主观性和模型的泛化能力。 随着深度学习技术的发展,基于…

用go从零构建写一个RPC(4)--gonet网络框架重构+聚集发包

在追求高性能的分布式系统中,RPC 框架的底层网络能力和数据传输效率起着决定性作用。经过几轮迭代优化,我完成了第四版本的 RPC 框架。相比以往版本,这一版本的最大亮点在于 重写了底层网络框架 和 实现了发送端的数据聚集机制,这…

OpenBayes 一周速览|TransPixeler 实现透明化文本到视频生成;统一图像定制框架 DreamO 上线,一键处理多种图像生成任务

公共资源速递 2 个公共数据集: * s1K-1.1 数学推理数据集 * HPA 人类蛋白质图谱数据集 3 个公共模型: * MedGemma-4B-IT * Devstral-Small-2505 * DeepSeek-Prover-V2-7B 12 个公共教程: 视频生成 * 2 语音交互 * 3 代码生成 * 3 …

4D毫米波雷达产品推荐

供应商链接 :https://mp.weixin.qq.com/s/GYarrc9VEZS0FafxRUeG9w 大陆 ARS548 采埃孚 博世 安波福 -------- Waymo MobileEye 华为(未找到官网资料) ------- 森思泰克 http://www.whst.com/contact.html 芜湖经济技术开发区东区…

yolo 训练 中间可视化

yolo训练前几个batch&#xff0c;会可视化target: if plots and ni < 33:f save_dir / ftrain_batch{ni}.jpg # filenameplot_images(imgs, targets, paths, f, kpt_labelkpt_label)

Rust 学习笔记:关于 Cargo 的练习题

Rust 学习笔记&#xff1a;关于 Cargo 的练习题 Rust 学习笔记&#xff1a;关于 Cargo 的练习题问题一问题二问题三问题四问题五问题六问题七 Rust 学习笔记&#xff1a;关于 Cargo 的练习题 参考视频&#xff1a; https://www.bilibili.com/video/BV1xjAaeAEUzhttps://www.b…

光伏功率预测 | BiLSTM多变量单步光伏功率预测(Matlab完整源码和数据)

光伏功率预测 | BiLSTM多变量单步光伏功率预测&#xff08;Matlab完整源码和数据&#xff09; 目录 光伏功率预测 | BiLSTM多变量单步光伏功率预测&#xff08;Matlab完整源码和数据&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 光伏功率预测 | BiLSTM多变…

20250606-C#知识:委托和事件

C#知识&#xff1a;委托和事件 使用委托可以很方便地调用多个方法&#xff0c;也方便将方法作为参数进行传递 1、委托 委托是方法的容器委托可以看作一种特殊的类先定义委托类&#xff0c;再用委托类声明委托变量&#xff0c;委托变量可以存储方法 delegate int Calculate(in…

AI数字人技术革新进行时:井云数字人如何重塑人机交互未来?

老板们注意了&#xff01;不用反复真人出镜拍摄&#xff0c;AI数字人来帮你做口播&#xff0c;只需3分钟克隆你的形象和声音&#xff0c;输入文案24小时随时都能生成视频&#xff01; 在元宇宙概念持续升温、虚拟与现实加速融合的当下&#xff0c;AI数字人正以惊人的速度从科幻…

ruoyi-plus-could 负载均衡 通过 Gateway模块配置负载均衡

这个很简单的&#xff0c;其实都不用配置。 在nacos中ruoyi-gateway.yml配置文件里面&#xff1a; 其实他已经给我们配置好了&#xff0c;只要uri&#xff1a;lb有【lb】就表示负载均衡配置 我们只需要在启动服务的时候改下端口就可以。 然后通过小工具测试下&#xff1a; 结…

Matlab回归预测大合集又更新啦!新增2种高斯过程回归预测模型,已更新41个模型!性价比拉满!

Matlab回归预测大合集又更新啦&#xff01;新增2种高斯过程回归预测模型&#xff0c;已更新41个模型&#xff01;性价比拉满&#xff01; 目录 Matlab回归预测大合集又更新啦&#xff01;新增2种高斯过程回归预测模型&#xff0c;已更新41个模型&#xff01;性价比拉满&#xf…

主流 AI IDE 之一的 Cursor 介绍

一、什么是 Cursor Cursor 是由 Anysphere 公司开发的 AI 驱动的代码编辑器&#xff08;IDE&#xff09;&#xff1b;Anysphere 成立于 2022 年&#xff0c;创始团队包括来自麻省理工学院&#xff08;MIT&#xff09;的毕业生&#xff0c;如联合创始人 Aman Sanger 和 Michael …

0x-1 记一次SGA PGA设置失败,重新开库

0、生产侧定时平台上传数据库11g hang&#xff0c;修改无法startup 厂商统一发放的虚拟机作为前置机导入平台后&#xff0c;直接开机使用。主机在虚拟化平台中&#xff0c;实例卡死后&#xff0c;按照虚拟机系统64G&#xff0c;原SGA2g,不知哪个大聪明给默认设置的。保守计划修…

【科研绘图系列】R语言绘制和弦图(Chord diagram plot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理相关性计算和弦图系统信息介绍 本文介绍了一个基于R语言的数据分析和可视化流程,主要用于生成和弦图(Chord Diagram)。和弦图是一种用于展示…

PPT转图片拼贴工具 v3.0

软件介绍 这个软件就是将PPT文件转换为图片并且拼接起来。 这个代码支持导入单个文件也支持导入文件夹 但是目前还没有解决可视化界面问题。 效果展示 软件源码 import os import re import win32com.client from PIL import Image from typing import List, Uniondef con…

关于安科瑞APD局部放电监测装置解决方案的应用分析

1 什么是局部放电&#xff1f; 局部放电&#xff08;Partial Discharge, PD&#xff09;是指发生在电气设备绝缘系统局部区域的、未贯穿整个电极的微小放电现象。它通常发生在高压电气设备&#xff08;如变压器、开关柜、电缆、GIS等&#xff09;内部存在绝缘缺陷、电场集中或…

设计模式-2 结构型模式

一、代理模式 1、举例 海外代购 2、代理基本结构图 3、静态代理 1、真实类实现一个接口&#xff0c;代理类也实现这个接口。 2、代理类通过真实对象调用真实类的方法。 4、静态代理和动态代理的区别 1、静态代理在编译时就已经实现了&#xff0c;编译完成后代理类是一个实际…

大量企业系统超龄服役!R²AIN SUITE 一体化企业提效解决方案重构零售数智化基因

《中国百货商业协会2024零售IT及数字化系统需求调查报告》为我们呈现了零售企业在数字化转型中的复杂图景。数据显示&#xff0c;82%的企业高管对AI改变行业未来充满信心 source&#xff1a;中国百货商业协会 &#xff0c;零售IT及数字化系统需求调查报告 &#xff0c;2024年 但…