鸿蒙开发-实战:用Path画矢量图标(心形、星星、齿轮)
本文介绍了使用Path绘制四种常见SVG图标的方法:心形使用贝塞尔曲线绘制优美弧线,星星通过交替连接内外顶点形成五角形,齿轮利用布尔运算创建锯齿状外圈和挖空内圈,箭头则用简单直线连接顶点。每种图标都展示了Path的不同功能特性,包括cubicTo贝塞尔曲线、lineTo直线连接、addCircle圆形绘制以及Path布尔运算,这些技术可以灵活组合用于创建各种矢量图形。文章提供了完整的代码示例,帮助
实战:用 Path 绘制 SVG 风格图标
APP 里的图标通常用 SVG 格式,因为矢量图可以无损缩放。但有时候你需要动态生成图标——比如根据用户设置改变颜色、大小,或者做一些简单的图标动画。
HarmonyOS 的 Path 可以绘制任意形状,今天我们来用它画几个常见的图标。
Path绘制图标整体流程
下面是用Path绘制矢量图标的基本流程:
图标 1:心形
心形是经典的 Path 练习,用两个贝塞尔曲线就能画出来。
import { common } from '@kit.AbilityKit';
import { Canvas, CanvasRenderingContext2D, Path } from '@kit.ArkGraphics2D';
导入需要的模块。
drawHeart() {
const ctx = this.context;
const centerX = 100;
const centerY = 100;
const size = 40;
ctx.clearRect(0, 0, 200, 200);
清空画布,准备绘制。
// 创建心形 Path
let path = new Path();
path.moveTo(centerX, centerY + size * 0.7); // 底部尖点
从心形的底部尖点开始。
// 左半边
path.cubicTo(
centerX - size * 1.5, centerY - size * 0.3, // 控制点1
centerX - size * 0.5, centerY - size * 1.2, // 控制点2
centerX, centerY - size * 0.3 // 终点(顶部凹点)
);
cubicTo 是三次贝塞尔曲线,需要两个控制点和一个终点。这里画的是心形的左半边——从底部尖点到顶部凹点。
两个控制点的位置决定了曲线的形状。控制点 1 在左下方,控制点 2 在左上方,这样曲线就会形成心形的左半边弧线。
// 右半边
path.cubicTo(
centerX + size * 0.5, centerY - size * 1.2, // 控制点1
centerX + size * 1.5, centerY - size * 0.3, // 控制点2
centerX, centerY + size * 0.7 // 终点(底部尖点)
);
右半边和左半边对称,只是控制点的 x 坐标翻转了。
// 填充心形
ctx.fillStyle = '#ff4081';
ctx.fillPath(path);
}
用心形路径填充粉色。
图标 2:星星
五角星用 lineTo 就能画出来,关键是计算 5 个顶点和 5 个凹点的坐标。
drawStar() {
const ctx = this.context;
const centerX = 100;
const centerY = 100;
const outerRadius = 50; // 外圈半径
const innerRadius = 20; // 内圈半径
const points = 5; // 5 个角
ctx.clearRect(0, 0, 200, 200);
定义星星的参数:外圈半径、内圈半径、角的数量。
let path = new Path();
let startAngle = -Math.PI / 2; // 从顶部开始
for (let i = 0; i < points * 2; i++) {
// 奇数次是外圈顶点,偶数次是内圈顶点
let radius = i % 2 === 0 ? outerRadius : innerRadius;
let angle = startAngle + (i * Math.PI / points);
let x = centerX + radius * Math.cos(angle);
let y = centerY + radius * Math.sin(angle);
if (i === 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
path.close();
星星有 10 个顶点(5 个外圈 + 5 个内圈),交替排列。循环 10 次,每次计算一个顶点的坐标。
i 是偶数时用外圈半径(顶点),i 是奇数时用内圈半径(凹点)。角度从 -90 度(顶部)开始,每步转 36 度(π/5)。
ctx.fillStyle = '#ffc107';
ctx.fillPath(path);
}
填充金黄色。
图标 3:齿轮
齿轮图标稍微复杂一点——外圈是锯齿状的,内圈是圆形。
drawGear() {
const ctx = this.context;
const centerX = 100;
const centerY = 100;
const outerRadius = 50;
const innerRadius = 35;
const teeth = 8; // 8 个齿
ctx.clearRect(0, 0, 200, 200);
定义齿轮参数。
// 画外圈锯齿
let path = new Path();
let startAngle = -Math.PI / 2;
for (let i = 0; i < teeth; i++) {
let angle1 = startAngle + (i * 2 * Math.PI / teeth);
let angle2 = angle1 + (Math.PI / teeth);
let angle3 = angle1 + (2 * Math.PI / teeth);
let x1 = centerX + outerRadius * Math.cos(angle1);
let y1 = centerY + outerRadius * Math.sin(angle1);
let x2 = centerX + outerRadius * Math.cos(angle2);
let y2 = centerY + outerRadius * Math.sin(angle2);
let x3 = centerX + innerRadius * Math.cos(angle2);
let y3 = centerY + innerRadius * Math.sin(angle2);
let x4 = centerX + innerRadius * Math.cos(angle3);
let y4 = centerY + innerRadius * Math.sin(angle3);
if (i === 0) {
path.moveTo(x1, y1);
}
path.lineTo(x2, y2);
path.lineTo(x3, y3);
path.lineTo(x4, y4);
}
path.close();
齿轮的外圈由 8 个"齿"组成,每个齿是一个梯形。计算每个齿的 4 个顶点,用 lineTo 连接。
// 画内圈(挖空)
let holePath = new Path();
holePath.addCircle(centerX, centerY, 15, Path.Direction.CW);
// 用 Path 的布尔运算挖空
path.op(holePath, Path.Op.DIFFERENCE);
内圈用 addCircle 画一个圆形,然后用 Path.Op.DIFFERENCE 布尔运算把内圈挖空。
ctx.fillStyle = '#607d8b';
ctx.fillPath(path);
}
填充蓝灰色。
图标 4:箭头
箭头图标简单但实用——返回按钮、前进按钮、方向指示等。
drawArrow() {
const ctx = this.context;
ctx.clearRect(0, 0, 200, 200);
let path = new Path();
// 箭头主体
path.moveTo(50, 100); // 左侧顶点
path.lineTo(120, 100); // 右侧水平线
path.lineTo(120, 85); // 右上
path.lineTo(160, 100); // 箭头尖端
path.lineTo(120, 115); // 右下
path.lineTo(120, 100); // 回到右侧
ctx.fillStyle = '#2196f3';
ctx.fillPath(path);
}
箭头由 6 个点组成:左侧起点、右侧水平线、右上角、箭头尖端、右下角、回到右侧。用 lineTo 依次连接。
四种图标绘制方法对比
不同图标使用不同的Path绘制技巧:
组合使用:动态图标
你可以把多个图标组合起来,根据状态切换:
@State iconType: string = 'heart';
drawIcon() {
switch (this.iconType) {
case 'heart':
this.drawHeart();
break;
case 'star':
this.drawStar();
break;
case 'gear':
this.drawGear();
break;
case 'arrow':
this.drawArrow();
break;
}
}
根据 iconType 状态绘制不同的图标。
动态图标切换流程
可以根据状态动态切换不同图标:
小结
用 Path 绘制图标的核心技巧:
- 简单形状:用
moveTo+lineTo画直线轮廓 - 曲线形状:用
cubicTo/quadTo画贝塞尔曲线 - 圆形元素:用
arcTo或addCircle - 复杂形状:用
Path.Op布尔运算组合 - 闭合路径:用
close()封闭路径
掌握了这些,你就能画出大部分矢量图标了。比加载 SVG 文件更灵活——颜色、大小、形状都可以动态调整。
更多推荐

所有评论(0)