HarmonyOS7 用 Canvas 画柱状图并不难:CanvasBarChartBasics 全流程拆解
文章目录前言这页案例的重点是什么完整代码data 和 labels 是图表的数据骨架为什么一定要先留 padding坐标轴和基线怎么画网格线为什么很关键柱宽和间距怎么分配柱子的高度怎么从数据映射出来顶部数值和底部标签为什么值得保留颜色数组为什么也值得单独设计这个案例怎么改成业务图表常见坑提醒写在最后前言一提到数据可视化很多人第一反应就是找图表库。这个思路没问题但有些场景下你未必需要一整套库。比如只是做一个轻量周报图、设备状态面板、运营数据卡片自己用Canvas画一个简单柱状图反而更灵活依赖也更轻。问题是图表跟普通图形不一样。它不是“画几个柱子”就完了还涉及坐标区域、留白、标签、刻度、数值位置。这也是为什么不少人一开始觉得图表很难。这个案例正好给了一个很好的起点手写一张最基础的柱状图。这页案例的重点是什么它不是要做一个专业图表库而是把最基础的数据图表达清楚。里面已经包含了柱状图最关键的几块结构数据数组和标签数组画布内边距Y 轴和底部基线网格线与刻度文字柱子本身顶部数值和底部标签你把这些关系弄明白以后换成折线图、面积图、进度图思路都能迁移。完整代码import{DEMO_BG_COLOR,DEMO_CARD_COLOR,DEMO_THEME_COLOR,DEMO_SUBTEXT_COLOR}from./typesinterfacePaddingConfig{top:numberbottom:numberleft:numberright:number}EntryComponentstruct CanvasBarChartBasics{StateisShow:booleantrueprivatesettings:RenderingContextSettingsnewRenderingContextSettings(true)privatecontext:CanvasRenderingContext2DnewCanvasRenderingContext2D(this.settings)privatedata:number[][65,80,45,90,55,75,60]privatelabels:string[][周一,周二,周三,周四,周五,周六,周日]build(){Column(){if(this.isShow){Scroll(){Column({space:16}){Text(Canvas 柱状图).fontSize(16).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)Column(){Text(每周数据统计).fontSize(13).fontColor(#4D96FF).margin({bottom:8})Column(){Canvas(this.context).onReady((){constw380consth220constpadding:PaddingConfig{top:20,bottom:40,left:40,right:20}constchartWw-padding.left-padding.rightconstchartHh-padding.top-padding.bottomconstbarWchartW/this.data.length*0.6constgapchartW/this.data.length*0.4this.context.clearRect(0,0,w,h)this.context.strokeStyle#E0E0E0this.context.lineWidth1this.context.beginPath()this.context.moveTo(padding.left,padding.top)this.context.lineTo(padding.left,padding.topchartH)this.context.lineTo(w-padding.right,padding.topchartH)this.context.stroke()for(leti0;i4;i){constypadding.topchartH*(1-i/4)this.context.strokeStyle#F0F0F0this.context.beginPath()this.context.moveTo(padding.left,y)this.context.lineTo(w-padding.right,y)this.context.stroke()this.context.font10px sans-serifthis.context.fillStyle#AAAAAAthis.context.fillText(25*i,padding.left-30,y3)}constcolors[#4D96FF,#6BCB77,#FFD93D,#FF6B6B,#9B59B6,#FFA500,#4ECDC4]for(leti0;ithis.data.length;i){constxpadding.left(chartW/this.data.length)*igap/2constbarH(this.data[i]/100)*chartHconstypadding.topchartH-barHthis.context.fillStylecolors[i]this.context.fillRect(x,y,barW,barH)this.context.font10px sans-serifthis.context.fillStyle#666666this.context.textAligncenterthis.context.fillText(this.data[i],xbarW/2,y-5)this.context.fillText(this.labels[i],xbarW/2,padding.topchartH18)}}).width(100%).height(240).backgroundColor(#FAFAFA).borderRadius(8)}}.backgroundColor(DEMO_CARD_COLOR).padding(12).borderRadius(12)Column({space:6}){Text(数据详情).fontSize(14).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)Row(){ForEach(this.labels,(label:string,_:number){Text(label).fontSize(11).fontColor(#666666).layoutWeight(1).textAlign(TextAlign.Center)})}.width(100%)Row(){ForEach(this.data,(val:number,_:number){Text(val).fontSize(13).fontColor(#1A1A1A).fontWeight(FontWeight.Bold).layoutWeight(1).textAlign(TextAlign.Center)})}.width(100%)}.width(100%).backgroundColor(#E8F4FD).padding(14).borderRadius(12)}.width(100%)}}Text(CanvasBarChartBasics - 绘制每周柱状图).fontSize(12).fontColor(DEMO_SUBTEXT_COLOR).margin({top:12})}.width(100%).height(100%).backgroundColor(DEMO_BG_COLOR).padding(16)}}data和labels是图表的数据骨架案例先定义了两组数组privatedata:number[][65,80,45,90,55,75,60]privatelabels:string[][周一,周二,周三,周四,周五,周六,周日]这就是图表最基本的输入。data决定柱子的高度labels决定底部每根柱子对应的说明。很多人一开始就急着画其实真正应该先想清楚的是数据结构长什么样。如果输入结构乱后面坐标、标签、颜色都会跟着乱。为什么一定要先留padding这句是全篇里最容易被低估的代码constpadding:PaddingConfig{top:20,bottom:40,left:40,right:20}图表不是填满整块画布就完事。你必须给坐标轴、刻度、标签、顶部数值留空间。所以这里把画布总尺寸w、h再减去内边距得到真正的图表可用区域constchartWw-padding.left-padding.rightconstchartHh-padding.top-padding.bottom这个思路特别重要。以后你做任何可视化几乎都要先从“总空间”和“绘图区”拆开。坐标轴和基线怎么画案例用路径画了左侧轴线和底部基线this.context.beginPath()this.context.moveTo(padding.left,padding.top)this.context.lineTo(padding.left,padding.topchartH)this.context.lineTo(w-padding.right,padding.topchartH)this.context.stroke()这里其实把图表的边界感一下子立起来了。即使你还没画柱子用户也能感觉到“这是个数据区域”。很多轻量图表不一定要完整包围框但底线和一条纵向参考轴通常很有必要。网格线为什么很关键案例里用循环画了五条水平网格线for(leti0;i4;i){constypadding.topchartH*(1-i/4)this.context.moveTo(padding.left,y)this.context.lineTo(w-padding.right,y)}它的作用不是装饰而是帮助读数。没有网格线时用户只能看出哪根柱子高、哪根柱子低有了刻度线和左侧数值他才更容易估出这是 50、75 还是接近 100。数据图的本质不是“好看”而是“能读”。柱宽和间距怎么分配案例把每一列的总空间拆成两部分constbarWchartW/this.data.length*0.6constgapchartW/this.data.length*0.4这是一种非常实用的比例分配法。每组位置 60% 给柱子40% 给空隙。这样柱子不会挤在一起也不会显得太散。这类写法的好处是数据项数量变了整体仍然能保持相对平衡。柱子的高度怎么从数据映射出来真正的数据映射就在这两句constbarH(this.data[i]/100)*chartHconstypadding.topchartH-barH第一句把数据值映射成柱高。第二句决定柱子从哪里开始画。因为Canvas的y轴是向下增长的所以柱子要想“从底部往上长”就必须先算出顶部坐标。这一步是很多人最容易算反的地方。顶部数值和底部标签为什么值得保留案例里每根柱子都画了两个文字this.context.fillText(this.data[i],xbarW/2,y-5)this.context.fillText(this.labels[i],xbarW/2,padding.topchartH18)这两个信息点其实很关键。顶部数值让用户不必用眼睛估计底部标签让用户知道这一列到底代表哪一天。它们一上图表就从“可视块”变成了“可阅读的数据表达”。颜色数组为什么也值得单独设计案例给每根柱子配了不同颜色constcolors[#4D96FF,#6BCB77,#FFD93D,#FF6B6B,#9B59B6,#FFA500,#4ECDC4]这适合演示效果但真实业务里要看场景。如果强调每一天是独立分类多色可以如果强调同一维度的连续数据统一色系往往更专业。比如一组销售额柱子通常不必七种颜色全上。这个案例怎么改成业务图表稍微改一下这页就能变成很多业务组件。比如把labels换成设备编号做设备监测面板把labels换成月份做月度趋势卡片把data接成接口返回值做真实报表模块把颜色策略改成阈值色做异常预警图也就是说这个案例已经不是玩具了它其实是个可复用的最小图表骨架。常见坑提醒第一个坑是没有先减掉padding结果标签和柱子全贴边。第二个坑是textAlign改成center后忘了恢复不过这个案例后续没有再写别的内容所以暂时没出问题。第三个坑是数据最大值写死为 100。如果真实数据不是这个量级需要先做动态最大值计算。第四个坑是直接把太多标签塞到底部文字会重叠。数据一多布局策略要变。写在最后柱状图这件事看起来像是图形问题实际上更像空间和数据关系问题。只要你把绘图区、比例映射、标签位置和信息层级想清楚用Canvas画一张清爽的图并不难。这一页特别值得反复练因为它已经把Canvas从“画图”推进到了“表达数据”。这一步走通后面的应用场景会一下子宽很多。

相关新闻

AI智能体记忆系统:Cognee开源平台架构与LangChain集成实战

AI智能体记忆系统:Cognee开源平台架构与LangChain集成实战

1. 项目概述:当AI智能体开始拥有“记忆”最近在AI智能体(Agent)的圈子里,一个词被频繁提起:记忆。无论是构建一个能持续对话的客服助手,还是一个能根据历史交互调整策略的自动化流程,智能体如何…

2026/8/8 11:17:00 阅读更多 →
HarmonyOS7 Canvas 怎么动起来:CanvasAnimationLoop 动画循环详解

HarmonyOS7 Canvas 怎么动起来:CanvasAnimationLoop 动画循环详解

文章目录前言这页案例到底讲了什么完整代码angle 是这段动画的发动机startAnimation() 做的其实是“开循环”动画帧开始前为什么一定要 clearRect()旋转为什么要配合 translate() 使用save() 和 restore() 为什么不能少颜色跟着角度变化,是个很巧的示范stopAnimatio…

2026/8/8 11:17:00 阅读更多 →
Java 反射全套常用方法汇总

Java 反射全套常用方法汇总

反射核心围绕 Class、Constructor、Method、Field 四大API,下面分类整理,附带作用与区分要点。前提:获取类字节码对象 1.Class clazz 目标类.class;2. Class clazz Class.forName("全类名");3.对象.getClass()一、Class 类&#…

2026/8/8 11:15:59 阅读更多 →

最新新闻

客户一多就忙不过来?很多人用API做自动化了

客户一多就忙不过来?很多人用API做自动化了

把重复的客户操作交给程序处理,人只关注关键环节 能力介绍 当客户数量上来之后,很多操作都会变成重复劳动,比如:加好友、发消息、打标签、跟进记录等。如果全部依赖人工,不仅效率低,还容易遗漏。 通过API结…

2026/8/8 12:09:22 阅读更多 →
完全免费的开源下载利器,带宽拉满无负担——Free Download Manager (FDM)

完全免费的开源下载利器,带宽拉满无负担——Free Download Manager (FDM)

文章目录 完全免费的开源下载利器,带宽拉满无负担——Free Download Manager (FDM)核心定位 FDM vs. IDM:谁才是你的最佳选择?官方安全下载渠道极简安装与基础配置(核心步骤不能省)核心功能全流程实操高频刚需应用场景…

2026/8/8 12:09:22 阅读更多 →
Windows系统-应用问题全面剖析Ⅶ:德承工控机DA-1100在Windows操作系统下[时间同步]设置教程

Windows系统-应用问题全面剖析Ⅶ:德承工控机DA-1100在Windows操作系统下[时间同步]设置教程

在之前的文章中讲解到Windows操作系统的[卡顿/死机]设置教程,可参考往期文章:《Windows系统-应用问题全面剖析Ⅵ:德承工控机MD-3000在Windows操作系统下[卡顿/死机]的排查与解决方法》,而Windows操作系统还有许多应用上会面临的问…

2026/8/8 12:09:22 阅读更多 →
C语言指针与字符串拷贝核心原理及PTA实战

C语言指针与字符串拷贝核心原理及PTA实战

1. PTA指针与字符串拷贝核心原理 在C语言编程中,指针和字符串操作是基础但容易出错的重点内容。PTA(Programming Teaching Assistant)平台常见的字符串拷贝题目,主要考察对指针操作和内存管理的理解深度。我们先看一个典型错误示例…

2026/8/8 12:09:22 阅读更多 →
8个实战验证的商业分析工具提升决策效率

8个实战验证的商业分析工具提升决策效率

1. 项目概述作为一名在商业分析领域深耕多年的从业者,我经常被MBA学员问到同一个问题:"如何在实际工作中快速提升分析效率?"经过多年实践,我发现工具选型是影响分析质量和工作效率的关键因素。本文将分享8个经过实战检验…

2026/8/8 12:09:21 阅读更多 →
逆向工程入门:从CTF基础题babyre学逆向分析

逆向工程入门:从CTF基础题babyre学逆向分析

1. 逆向工程入门:从攻防世界babyre开始 第一次接触逆向工程的新手往往会被各种专业术语和复杂工具吓退,而攻防世界(CTF比赛平台)的babyre题目正是为逆向新手设计的绝佳入门练习。这道题目的名称"babyre"已经暗示了它的定…

2026/8/8 12:08:21 阅读更多 →

日新闻

AI多智能体时代来临,读懂MCP与A2A架构,抢占企业数字化新风口

AI多智能体时代来临,读懂MCP与A2A架构,抢占企业数字化新风口

当下AI应用飞速普及,无数企业下场搭建智能体系统,可落地阶段难题接踵而至:上下文无限堆积频繁爆栈、AI工具调用准确率低下、Token成本居高不下、企业数据权限混乱暗藏安全隐患……很多团队卡在架构搭建环节,空有前沿技术概念&…

2026/8/8 0:00:07 阅读更多 →
PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码

PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码

PHP二维码生成终极指南:用chillerlan/php-qrcode打造专业级二维码 【免费下载链接】php-qrcode A PHP QR Code generator and reader with a user-friendly API. 项目地址: https://gitcode.com/gh_mirrors/ph/php-qrcode 在当今数字时代,二维码已…

2026/8/8 0:00:08 阅读更多 →
UniApp微信小程序隐私保护组件开发:从原理到实战

UniApp微信小程序隐私保护组件开发:从原理到实战

1. 项目缘起:为什么我们需要一个隐私保护通用组件?最近在维护一个基于uniapp开发的微信小程序矩阵时,我遇到了一个非常棘手的问题。随着平台对用户隐私保护的要求越来越严格,几乎每一个新版本发布,或者在某些特定机型&…

2026/8/8 0:00:08 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/6 22:02:27 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/8 8:58:26 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/7 23:24:08 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/7 17:02:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/7 23:54:54 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/7 17:02:36 阅读更多 →