写点什么

鸿蒙 Next 使用 Canvas 绘制一个汽车仪表盘

作者:auhgnixgnahz
  • 2025-06-25
    北京
  • 本文字数:3288 字

    阅读完需:约 11 分钟

本文通过实现一个汽车仪表盘,介绍使用 CanvasRenderingContext2D 在 Canvas 组件上进行绘制图形。


看一下最终演示:



先了解一下 CanvasRenderingContext2D 都有哪些属性方法



本文使用的几个方法以放到前面,可以参考说明。



源码:


import { getScreenWidth } from '../utils/DisplayUtil';
@Entry@ComponentV2struct CanvasTest { private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private context2: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private context3: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); @Local centerX: number = 0 @Local centerY: number = 0 @Local currentSpeed: number = 0 @Local angle: number = 0 @Local startAngle:number= Math.PI * 140 / 180 //弧线的起始弧度 @Local endAngle:number= Math.PI * 40 / 180 //弧线的起始弧度
//绘制渐变外环 draw(){ this.context3.clearRect(0,0,2*this.centerX,2*this.centerX) this.context3.beginPath() let grad = this.context3.createLinearGradient(this.getStartX(), this.getStartY(), this.getEndX(), this.getEndY()) grad.addColorStop(0, '#0000ff00') grad.addColorStop(0.9, '#00ff00') if (this.currentSpeed>120) { grad.addColorStop(1, '#ff0000') }else { grad.addColorStop(1, '#00ff00') } this.context3.strokeStyle = grad; this.context3.lineWidth = 4; this.context3.arc(this.centerX, this.centerY, this.centerX - 4, this.startAngle, Math.PI * (140+(this.currentSpeed * 260 / 180) ) / 180) this.context3.stroke() }
build() { Column() { Stack() { Canvas(this.context) .width('100%') .height('100%') .backgroundColor("#fceb99") .onReady(() => { //绘制外环 this.context.beginPath() this.context.strokeStyle = '#0000ff'; this.context.lineWidth = 2; this.context.arc(this.centerX, this.centerY, this.centerX - 10, this.startAngle, this.endAngle) this.context.stroke() //绘制内环 this.context.beginPath() this.context.strokeStyle = '#07A6EC'; this.context.lineWidth = 8; this.context.arc(this.centerX, this.centerY, this.centerX - 16, this.startAngle, this.endAngle) this.context.stroke() //绘制刻度 this.context.save() this.context.translate(this.centerX, this.centerY); this.context.rotate(Math.PI * 50 / 180) for (let i = 0; i <= 36; i++) { if (i % 4 == 0) { this.context.beginPath() this.context.lineWidth = 4; this.context.strokeStyle = '#07A6EC'; this.context.moveTo(0, this.centerY - 34); this.context.lineTo(0, this.centerY - 12); this.context.stroke(); } else { this.context.beginPath() this.context.lineWidth = 2; this.context.strokeStyle = '#07A6EC'; this.context.moveTo(0, this.centerY - 26); this.context.lineTo(0, this.centerY - 12); this.context.stroke(); } this.context.rotate(Math.PI * (260 / 36) / 180) } this.context.restore() //绘制数字 this.context.save() this.context.translate(this.centerX, this.centerY); for (let i = 0; i < 10; i++) { // 转换为弧度 const radians = (140 + i * (260 / 9)) * Math.PI / 180; // 计算坐标 const x = (this.centerY - 60) * Math.cos(radians); const y = (this.centerY - 60) * Math.sin(radians); this.context.textAlign = 'center' this.context.textBaseline = 'middle' this.context.font = '30vp sans-serif' this.context.fillText(i * 20 + '', x, y) } //绘制中间单位 this.context.textAlign = 'center' this.context.textBaseline = 'middle' this.context.font = '30vp sans-serif' this.context.fillText('km/h', 0, -40) this.context.restore() //绘制红色圆环 this.context.translate(0, 0); this.context.beginPath() this.context.strokeStyle = Color.Red; this.context.lineWidth = 3; this.context.arc(this.centerX, this.centerY, this.centerX - 100, this.startAngle, this.endAngle) this.context.stroke() }) Canvas(this.context3) .width('100%') .height('100%')
Canvas(this.context2) .width('100%') .height('100%') .onReady(() => { this.context2.beginPath() this.context2.lineWidth = 3; this.context2.strokeStyle = "#95ff00"; this.context2.moveTo(this.centerX, this.centerY) this.context2.lineTo(this.centerX, 14) this.context2.stroke() }) .rotate({ centerX: this.centerX, centerY: this.centerY, angle: this.cacleAngle() })
Text(this.currentSpeed + '').fontColor(Color.Black).fontSize(30).offset({ y: 20 })
}.height('50%').width('100%') .onSizeChange((oldValue: SizeOptions, newValue: SizeOptions) => { this.centerX = (newValue.width as number) / 2 this.centerY = (newValue.height as number) / 2 })
Slider({ value: this.currentSpeed, min: 0, max: 180, step: 1, }) .width('80%') .blockColor("#0099ff")//设置滑块的颜色 .onChange((value: number, mode: SliderChangeMode) => { this.currentSpeed = value }) } }
cacleAngle(): number { this.draw(); // (当前速度/最大速度180)*圆环角度260- 默认其实位置从中心位置向左旋转130 return (this.currentSpeed * 260 / 180) - 130 }
getStartX() { const angleRadians = 140 * Math.PI / 180; return this.centerX + this.centerX * Math.cos(angleRadians); }
getStartY(): number { const angleRadians = 140 * Math.PI / 180; return this.centerX + this.centerX * Math.sin(angleRadians); }
getEndX() { const angleRadians = (140+(this.currentSpeed * 260 / 180) )* Math.PI / 180; return this.centerX + this.centerX * Math.cos(angleRadians); } getEndY(): number { const angleRadians = (140+(this.currentSpeed * 260 / 180))* Math.PI / 180; return this.centerX + this.centerX * Math.sin(angleRadians); }}
复制代码


发布于: 刚刚阅读数: 3
用户头像

auhgnixgnahz

关注

还未添加个人签名 2018-07-10 加入

欢迎关注:HarmonyOS开发笔记

评论

发布
暂无评论
鸿蒙Next使用Canvas绘制一个汽车仪表盘_鸿蒙Next_auhgnixgnahz_InfoQ写作社区