NEWS DETAIL

HarmonyOS应用《玄象》开发实战:Canvas 星空绘制:arc / fillStyle / 随机散点算法

发布时间:2026/10/15 7:23:43 · 栏目:资讯中心

尧图网络原创建站知识分享正文
阅读时长约 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
✦

本文为尧图网络原创建站知识分享。想针对自身行业获取定制化建站方案?欢迎咨询,资深顾问免费为你出思路。

RELATED

相关 资讯推荐

MORE

更多 新鲜资讯

JMeter入门实战:从零构建HTTP接口性能测试脚本与结果分析
2026/10/13 20:48:30

JMeter入门实战:从零构建HTTP接口性能测试脚本与结果分析

1. 项目概述:从零开始,用JMeter搞定HTTP性能测试 刚接触性能测试的新手,或者是从功能测试转过来的朋友,一听到“压测”两个字,心里可能就有点发怵。工具那么多,概念那么杂,从哪儿下手呢&#xf…

Earendel: 一个纯TS写的POSIX兼容的微内核Web操作系统
2026/10/13 20:48:30

Earendel: 一个纯TS写的POSIX兼容的微内核Web操作系统

最近我用TypeScript写了一个运行在浏览器里的Web操作系统 Earendel(目前已知的距离地球最遥远的恒星)。开发它的初衷主要是为了Linux和操作系统课程的教学。市面上绝大多数Web OS项目,要么只是做了一个长得像Windows/macOS的网页UI拼盘&#…

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形[特殊字符]
2026/10/13 20:48:30

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形[特殊字符]

5分钟掌握Windows防撤回神器:让微信QQ撤回消息无处遁形🚀 【免费下载链接】RevokeMsgPatcher :trollface: A hex editor for WeChat/QQ/TIM - PC版微信/QQ/TIM防撤回补丁(我已经看到了,撤回也没用了) 项目地址: http…

从零制作同人动画:技术路线、流程与实战避坑指南
2026/10/14 17:19:19

从零制作同人动画:技术路线、流程与实战避坑指南

1. 先搞清楚这个“粉丝动画”到底是什么,以及它能解决什么问题看到“五条悟VS宿傩/咒术回战粉丝动画”这个标题,很多人的第一反应可能是去找一个现成的视频。但如果你是一个想自己动手创作、或者想了解这类作品背后技术流程的创作者,这个标题…

闭源降价80%,开源却在涨价:AI定价的交叉路口
2026/10/15 5:55:41

闭源降价80%,开源却在涨价:AI定价的交叉路口

8月6日,两条价格曲线悄然交汇。 一条向下:OpenAI把GPT-5.6 Luna的输出价格从6美元砍到1.2美元/百万Token,降幅80%。另一条向上:同一天,DeepSeek公告全线涨价,措辞是"涨幅较大",非试探…

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买
2026/10/13 20:48:29

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买

产线三防平板选哪个牌子?5个品牌实测告诉你别瞎买经常有工厂朋友拿着网上的"三防平板十大品牌排行榜"来问我:到底选哪个?说实话排行榜看看就行,真正选型得看你产线什么场景。今天挑五个在产线数字化里用得比较多的品牌—…

看完这篇,还想了解更多?

预约尧图网络顾问一对一沟通,针对你的行业与现状给出建站建议,全程免费。

免费咨询