HarmonyOS应用《玄象》开发实战:Canvas 星空绘制:arc / fillStyle / 随机散点算法
阅读时长约 19 分钟 | 难度★★★★☆ | 篇章第 2 篇 · 启动体验Splash 与动画对应源码entry/src/main/ets/pages/SplashPage.ets中的drawStarField方法前言玄象项目启动页的星空背景是整个应用视觉调性的奠基。深邃夜空、百点繁星、银河流光——这套视觉语言用纯 Canvas API 实现未引入任何图片资源。本篇将深入剖析玄象项目drawStarField方法的实现细节从CanvasRenderingContext2DAPI、Math.random()随机散点算法、createLinearGradient银河渐变到绘制性能优化与可复用性重构。掌握这套 Canvas 绘制方法论您就能用纯代码绘制任何复杂视觉场景。提示玄象项目星空背景未引入图片是因为 Canvas 矢量绘制具有无极缩放、极小体积、动态可控三大优势。对于启动页这种轻量场景纯 Canvas 实现是最优解。一、drawStarField 完整源码1.1 源码全貌privatedrawStarField(canvas:CanvasRenderingContext2D,canvasWidth:number,canvasHeight:number){// 1. 绘制深色背景canvas.fillStyleColors.BG_DARK;canvas.fillRect(0,0,canvasWidth,canvasHeight);// 2. 绘制星星for(leti0;i100;i){constxMath.random()*canvasWidth;constyMath.random()*canvasHeight*0.7;constsizeMath.random()*20.5;constalphaMath.random()*0.80.2;canvas.fillStylergba(255, 255, 220,${alpha});canvas.beginPath();canvas.arc(x,y,size,0,Math.PI*2);canvas.fill();}// 3. 银河效果constgradientcanvas.createLinearGradient(0,0,canvasWidth,canvasHeight*0.5);gradient.addColorStop(0,rgba(212, 168, 67, 0));gradient.addColorStop(0.5,rgba(212, 168, 67, 0.05));gradient.addColorStop(1,rgba(212, 168, 67, 0));canvas.fillStylegradient;canvas.fillRect(0,0,canvasWidth,canvasHeight*0.5);}1.2 三大绘制阶段玄象项目星空绘制分为三大阶段阶段操作视觉效果背景填充fillRect全屏深色深邃夜空星点散布100 个随机星点繁星点点银河渐变线性渐变带银河流光二、CanvasRenderingContext2D 核心 API2.1 fillStyle 填充样式canvas.fillStyleColors.BG_DARK;// 字符串色值canvas.fillStylergba(255, 255, 220, 0.5);// RGBA 字符串canvas.fillStylegradient;// 渐变对象fillStyle接受三种类型的值CSS 颜色字符串#D4A843或rgba(255,255,220,0.5)CanvasGradient 对象通过createLinearGradient创建CanvasPattern 对象通过createPattern创建2.2 fillRect 绘制矩形canvas.fillRect(0,0,canvasWidth,canvasHeight);fillRect(x, y, width, height)使用当前fillStyle填充矩形区域。2.3 beginPath / arc / fill 绘制圆形canvas.beginPath();canvas.arc(x,y,size,0,Math.PI*2);canvas.fill();玄象项目用三步绘制每个星点beginPath开始一条新路径arc(x, y, radius, startAngle, endAngle)绘制圆形路径fill填充当前路径2.4 arc 角度参数详解arc的角度参数参数含义x圆心 x 坐标y圆心 y 坐标radius半径startAngle起始角度弧度endAngle结束角度弧度绘制完整圆startAngle 0endAngle Math.PI * 2。提示Math.PI * 2等于 360 度。玄象项目绘制完整星点使用此值。三、随机散点算法3.1 星点参数随机化for(leti0;i100;i){constxMath.random()*canvasWidth;constyMath.random()*canvasHeight*0.7;constsizeMath.random()*20.5;constalphaMath.random()*0.80.2;// 绘制星点}玄象项目为每个星点生成 4 个随机参数参数计算公式取值范围xMath.random() * canvasWidth[0, canvasWidth]yMath.random() * canvasHeight * 0.7[0, 0.7 × canvasHeight]sizeMath.random() * 2 0.5[0.5, 2.5]alphaMath.random() * 0.8 0.2[0.2, 1.0]3.2 y 坐标限制的设计意图constyMath.random()*canvasHeight*0.7;玄象项目刻意将星点的 y 坐标限制在屏幕上方 70% 区域原因避开底部星图区下方 40% 区域有独立的星图装饰星点不应与之重叠。模拟真实星空地平线附近星空稀疏高处星空密集。3.3 星点尺寸的分布规律constsizeMath.random()*20.5;玄象项目星点尺寸分布小星点0.5-1.0占 25%远处微星中星点1.0-2.0占 50%常态星点大星点2.0-2.5占 25%明亮主星提示Math.random()返回 [0, 1) 区间的浮点数。Math.random() * 2 0.5的取值范围是 [0.5, 2.5)。3.4 透明度的随机化constalphaMath.random()*0.80.2;canvas.fillStylergba(255, 255, 220,${alpha});玄象项目通过随机透明度营造星点闪烁感高透明度0.8-1.0明亮星点中透明度0.5-0.8常态星点低透明度0.2-0.5微弱星点3.5 模板字符串拼接 RGBAcanvas.fillStylergba(255, 255, 220,${alpha});玄象项目使用模板字符串动态拼接颜色255, 255, 220暖白色 RGB 值模拟星光色温${alpha}随机透明度提示玄象项目使用(255, 255, 220)而非(255, 255, 255)是因为暖白色更符合东方夜空的视觉调性。四、银河渐变带4.1 createLinearGradient 线性渐变constgradientcanvas.createLinearGradient(0,0,canvasWidth,canvasHeight*0.5);createLinearGradient(x0, y0, x1, y1)创建线性渐变参数含义玄象项目值x0, y0渐变起点(0, 0) 左上角x1, y1渐变终点(canvasWidth, 0.5 × canvasHeight) 右中部渐变方向从左上角到右中部斜向 45 度流向。4.2 addColorStop 颜色断点gradient.addColorStop(0,rgba(212, 168, 67, 0));gradient.addColorStop(0.5,rgba(212, 168, 67, 0.05));gradient.addColorStop(1,rgba(212, 168, 67, 0));addColorStop(offset, color)添加颜色断点offsetalpha视觉效果00完全透明0.50.05微弱金光10完全透明4.3 银河带的设计意图玄象项目银河带的设计意图强化中心渐变带从透明到微亮再到透明形成中间亮、两端暗的光带。斜向流向45 度斜向渐变模拟银河流动方向。微妙金光rgba(212, 168, 67, 0.05)透明度仅 5%避免抢夺主视觉。4.4 银河带的覆盖区域canvas.fillRect(0,0,canvasWidth,canvasHeight*0.5);银河带覆盖屏幕上方 50% 区域与星点分布区域上方 70%部分重叠营造星点在银河中漂浮的视觉。五、Canvas 绘制性能优化5.1 减少状态切换玄象项目星空绘制存在的性能优化点// 当前实现每次循环都修改 fillStylefor(leti0;i100;i){canvas.fillStylergba(255, 255, 220,${alpha});// 状态切换// ...}// 优化方案 1按 alpha 分组绘制constgroups{};for(leti0;i100;i){constalpha(Math.floor(Math.random()*8)2)/10;// 离散化if(!groups[alpha])groups[alpha][];groups[alpha].push({x,y,size});}for(constalphaingroups){canvas.fillStylergba(255, 255, 220,${alpha});// 一次设置for(conststarofgroups[alpha]){canvas.beginPath();canvas.arc(star.x,star.y,star.size,0,Math.PI*2);canvas.fill();}}5.2 使用 Path2D 批量绘制constpathnewPath2D();for(leti0;i100;i){path.arc(x,y,size,0,Math.PI*2);}canvas.fill(path);// 一次填充所有路径5.3 离屏 Canvas 预渲染对于静态星空可使用离屏 Canvas预渲染一次privateoffscreenCanvas:OffscreenCanvas;aboutToAppear():void{this.offscreenCanvasnewOffscreenCanvas(canvasWidth,canvasHeight);constctxthis.offscreenCanvas.getContext(2d);this.drawStarField(ctx,canvasWidth,canvasHeight);}// 主 Canvas 直接 drawImagemainCtx.drawImage(this.offscreenCanvas,0,0);提示玄象项目启动页仅渲染一次性能优化收益不大。但在动画场景如每帧重绘的星空中离屏 Canvas 可显著提升性能。六、绘制函数的可复用性重构6.1 当前实现的局限玄象项目drawStarField是箭头函数赋值给类成员privatedrawStarField(canvas,width,height){// ...};这种写法存在局限无法继承箭头函数无法被子类重写。无法静态化箭头函数不属于原型方法。测试困难箭头函数难以 Mock。6.2 重构为静态方法// common/utils/StarFieldRenderer.etsexportclassStarFieldRenderer{staticrender(canvas:CanvasRenderingContext2D,width:number,height:number,options:StarFieldOptions):void{canvas.fillStyleoptions.bgColor;canvas.fillRect(0,0,width,height);for(leti0;ioptions.starCount;i){constxMath.random()*width;constyMath.random()*height*options.starAreaRatio;constsizeMath.random()*options.maxStarSizeoptions.minStarSize;constalphaMath.random()*0.80.2;canvas.fillStylergba(${options.starColor},${alpha});canvas.beginPath();canvas.arc(x,y,size,0,Math.PI*2);canvas.fill();}}}6.3 使用接口定义配置interfaceStarFieldOptions{bgColor:string;// 背景色starCount:number;// 星点数量starColor:string;// 星点颜色 RGB如 255, 255, 220minStarSize:number;// 最小星点尺寸maxStarSize:number;// 最大星点尺寸starAreaRatio:number;// 星点分布区域比例hasGalaxy:boolean;// 是否绘制银河galaxyColor:string;// 银河颜色}提示玄象项目若推出星宿详情页等其他需要星空背景的页面可直接复用StarFieldRenderer传入不同配置即可。七、星空绘制的扩展方向7.1 添加流星动画privatemeteors:Meteor[][];privatedrawMeteors(canvas:CanvasRenderingContext2D){for(constmeteorofthis.meteors){constgradientcanvas.createLinearGradient(meteor.x,meteor.y,meteor.x-meteor.length*Math.cos(meteor.angle),meteor.y-meteor.length*Math.sin(meteor.angle));gradient.addColorStop(0,rgba(255, 255, 220, 1));gradient.addColorStop(1,rgba(255, 255, 220, 0));canvas.strokeStylegradient;canvas.lineWidth2;canvas.beginPath();canvas.moveTo(meteor.x,meteor.y);canvas.lineTo(meteor.x-meteor.length*Math.cos(meteor.angle),meteor.y-meteor.length*Math.sin(meteor.angle));canvas.stroke();}};7.2 添加星点闪烁动画privatestarTwinkle(canvas:CanvasRenderingContext2D,stars:Star[]){for(conststarofstars){star.alphastar.twinkleSpeed*star.twinkleDirection;if(star.alpha1||star.alpha0.2){star.twinkleDirection*-1;}canvas.fillStylergba(255, 255, 220,${star.alpha});canvas.beginPath();canvas.arc(star.x,star.y,star.size,0,Math.PI*2);canvas.fill();}};7.3 添加银河旋涡privatedrawGalaxySwirl(canvas:CanvasRenderingContext2D,centerX:number,centerY:number){constarms4;conststarsPerArm200;for(letarm0;armarms;arm){for(leti0;istarsPerArm;i){constangle(arm/arms)*Math.PI*2(i/starsPerArm)*Math.PI*4;constradius(i/starsPerArm)*200;constxcenterXMath.cos(angle)*radius;constycenterYMath.sin(angle)*radius;canvas.fillStylergba(212, 168, 67,${Math.random()*0.50.2});canvas.beginPath();canvas.arc(x,y,Math.random()*1.50.5,0,Math.PI*2);canvas.fill();}}};八、玄象项目 Canvas 绘制规范总结8.1 Canvas 绘制四步法玄象项目 Canvas 绘制遵循四步法状态设置fillStyle/strokeStyle/lineWidth路径定义beginPath/moveTo/lineTo/arc填充或描边fill/stroke状态恢复可选保存与恢复状态8.2 Canvas 绘制规范表场景API 组合绘制矩形fillStylefillRect绘制圆形fillStylebeginPatharcfill绘制线段strokeStylelineWidthbeginPathmoveTolineTostroke绘制渐变createLinearGradientaddColorStop 赋值给fillStyle绘制文本fillStylefontfillText总结本篇以玄象项目drawStarField方法为蓝本深入剖析了 HarmonyOS Canvas 绘制的实现细节从CanvasRenderingContext2D核心 API、Math.random()随机散点算法、createLinearGradient银河渐变到绘制性能优化按 alpha 分组、Path2D 批量、离屏 Canvas与可复用性重构静态方法 接口配置。掌握这套 Canvas 绘制方法论您就能用纯代码绘制任何复杂视觉场景。下一篇《13 · Canvas 太极图算法阴阳半圆 鱼眼小圆的数学推导》将带您深入玄象项目启动页中央的太极图绘制算法。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源HarmonyOS 官方文档CanvasRenderingContext2DHarmonyOS 官方文档Canvas 组件MDN Canvas APIdeveloper.mozilla.org/zh-CN/docs/Web/API/Canvas_API开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net

相关新闻

Csimplecleaner:高效管理Windows C盘空间的实用工具

Csimplecleaner:高效管理Windows C盘空间的实用工具

1. 项目概述作为一名长期与Windows系统打交道的IT从业者,我深知C盘空间管理的重要性。Csimplecleaner这个工具的出现,恰好解决了Windows用户长期面临的系统盘空间不足问题。不同于市面上那些功能繁杂却效果一般的清理工具,Csimplecleaner专注…

2026/7/26 23:00:59 阅读更多 →
Claude Code 提示词越具体,返工越少

Claude Code 提示词越具体,返工越少

今天这个主题很小,却非常容易决定 Claude Code 的工作质量。很多人把 Claude Code 当成一个更聪明的聊天窗口,输入一句「帮我修一下支付问题」,就期待它自动读懂业务、定位文件、复现 bug、写测试、修实现、跑验证。这个期待不算离谱,因为 Claude Code 确实是一个 agentic …

2026/7/26 23:00:59 阅读更多 →
为什么不建议在 Docker 中跑 MySQL?

为什么不建议在 Docker 中跑 MySQL?

为什么不建议在 Docker 中跑 MySQL? 引言:容器化的诱惑与陷阱在现代软件开发中,Docker 已经成为部署应用的标准工具。它能快速启动环境、隔离依赖、方便迁移,这让很多开发者习惯性地将所有服务都容器化,包括数据库。然…

2026/7/26 22:59:59 阅读更多 →

最新新闻

ROS2 Topic通信——发布订阅的底层机制

ROS2 Topic通信——发布订阅的底层机制

面试被问:"ROS2的Topic底层是怎么工作的?发布者和订阅者之间到底发生了什么?" 我说"就是发布订阅模式,一个发一个收"。面试官追问:"那发布者发了消息,订阅者还没启动&#xff0c…

2026/7/26 23:19:16 阅读更多 →
Java程序员如何深入浅出JDK源码?

Java程序员如何深入浅出JDK源码?

作为Java开发者,面试肯定被问过多线程。对于它,大多数好兄弟面试前都是看看八股文背背面试题以为就OK了;殊不知现在的面试官都是针对一个点往深了问,你要是不懂其中原理,面试就挂了。可能你知道什么是进程什么是线程&a…

2026/7/26 23:19:16 阅读更多 →
SDR++终极指南:如何用这款开源软件定义无线电工具改变频谱监测体验

SDR++终极指南:如何用这款开源软件定义无线电工具改变频谱监测体验

SDR终极指南:如何用这款开源软件定义无线电工具改变频谱监测体验 【免费下载链接】SDRPlusPlus Cross-Platform SDR Software 项目地址: https://gitcode.com/GitHub_Trending/sd/SDRPlusPlus SDR是一款跨平台的开源软件定义无线电(SDR&#xff0…

2026/7/26 23:19:16 阅读更多 →
UEFITool 0.28 终极指南:轻松解析和修改UEFI固件镜像

UEFITool 0.28 终极指南:轻松解析和修改UEFI固件镜像

UEFITool 0.28 终极指南:轻松解析和修改UEFI固件镜像 【免费下载链接】UEFITOOL28 UEFITOOL28 项目地址: https://gitcode.com/gh_mirrors/ue/UEFITOOL28 UEFITool是一款强大的跨平台C/Qt程序,专门用于解析、提取和修改UEFI固件镜像。这款开源工具…

2026/7/26 23:19:16 阅读更多 →
CC13x2/CC26x2无线MCU低功耗设计:PRCM时钟门控与电源模式实战解析

CC13x2/CC26x2无线MCU低功耗设计:PRCM时钟门控与电源模式实战解析

1. 项目概述与核心价值在电池供电的物联网设备开发中,功耗是决定产品生命周期的命脉。我接触过不少项目,初期功能跑通后,一测整机电流,动辄几十毫安,待机时间以天计,离“年”级续航的目标相去甚远。问题的核…

2026/7/26 23:19:16 阅读更多 →
TVA:具身智能通用视觉操作系统 (14)

TVA:具身智能通用视觉操作系统 (14)

前沿技术探索:AI智能体视觉(TVA,Transformer-based Vision Agent)是依托Transformer架构与“因式智能体”理论所构建的颠覆性工业视觉技术,是集深度强化学习(DRL)、卷积神经网络(CNN…

2026/7/26 23:18:15 阅读更多 →

日新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/26 0:00:31 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/26 0:00:31 阅读更多 →

月新闻