鸿蒙MPChart图表自定义(六)在图表中绘制游标
在鸿蒙开发中,MPChart 是一个非常强大的图表库,它可以帮助我们创建各种精美的图表。今天,我们将继续探索鸿蒙MPChart的自定义功能,重点介绍如何在图表中绘制游标。
OpenHarmony三方库中心仓
一、效果演示
以下是效果演示图,从动图可以看出,这是一个渐变蓝色的曲线图表,通过手指在图表上点击或者长按住滑动,可以在图表顶部展示出数据点的基本信息。这个效果也比较简单,只需要通过自定义UI就可以轻松实现。
二、绘制游标的步骤
在鸿蒙MPChart中,绘制游标可以通过以下步骤实现:
1. 页面组件定义
@Entry
@Component
struct LongPressSlideCursorPage {
这里定义了一个名为 LongPressSlideCursorPage
的页面组件,使用了 @Entry
和 @Component
装饰器,表示这是一个可以独立运行的页面组件。
2. 状态变量定义
@State private lineChartModel: LineChartModel = new LineChartModel();
@State positionX: number = 0;
@State positionY: number = 0;
@State cursorPositionX: number = 0;
@State cursorPositionY: number = 0;
@State dataX: number = 0;
@State dataY: number = 0;
@State showUI: boolean = false;
@State uiWidth: number = 0;
cursorSize: number = 100;
这些是页面的状态变量,用于存储图表模型、选中点的位置信息、游标位置信息、选中点的数据信息、是否显示UI、UI的宽度和游标的大小。
3. 数据选择监听器
@State private valueSelectedListener: OnChartValueSelectedListener = {onValueSelected: (e: EntryOhos, h: Highlight) => {this.showUI = true;this.dataX = Number(e.getX().toFixed(1));this.dataY = Number(e.getY().toFixed(1));let x = this.lineChartModel.getTransformer(AxisDependency.LEFT)?.getPixelForValues(e.getX(), e.getY()).x ?? 0;let y = this.lineChartModel.getTransformer(AxisDependency.LEFT)?.getPixelForValues(e.getX(), e.getY()).y ?? 0;this.positionX = x;this.positionY = y;if (x > this.uiWidth - this.cursorSize / 2 - 10) {x = this.uiWidth - this.cursorSize / 2 - 10;} else if (x < this.cursorSize / 2 + 10) {x = this.cursorSize / 2 + 10;}this.cursorPositionX = x;},onNothingSelected: () => {this.showUI = false;}
}
这是一个数据选择监听器,用于处理图表上的数据选中事件。当用户选中一个数据点时,会显示一个UI来显示选中点的详细信息。同时,会计算并设置游标的位置。
4. 数据初始化
aboutToAppear() {this.uiWidth = px2vp(display.getDefaultDisplaySync().width);let values: JArrayList<EntryOhos> = new JArrayList<EntryOhos>();for (let i = 1; i <= 30; i++) {values.add(new EntryOhos(i, Math.random() * 100));}let lineDataSet = new LineDataSet(values, 'DataSet');lineDataSet.setMode(Mode.CUBIC_BEZIER);lineDataSet.setDrawCircles(false);let lineDataSetList: JArrayList<ILineDataSet> = new JArrayList<ILineDataSet>();//渐变色填充let gradientFillColor = new JArrayList<ChartColorStop>();gradientFillColor.add(["#0099CC", 0.2]);gradientFillColor.add(["#7F0099CC", 0.4]);gradientFillColor.add(["#ffffff", 1.0]);lineDataSet.setGradientFillColor(gradientFillColor);lineDataSet.setDrawFilled(true);//不显示数值lineDataSet.setDrawValues(false);//设置线条颜色lineDataSet.setColorByColor(0x0099cc);//设置不显示指示线lineDataSet.setDrawHighlightIndicators(false);lineDataSetList.add(lineDataSet);let lineData: LineData = new LineData(lineDataSetList);this.lineChartModel?.setData(lineData);this.lineChartModel.setOnChartValueSelectedListener(this.valueSelectedListener);this.lineChartModel.setHighlightPerLongPressEnabled(false);this.lineChartModel.setVisibleXRangeMaximum(10);this.lineChartModel.setSwipeEnabled(true);//设置长按出游标 和 触发长按的时长this.lineChartModel.setLongPressCursorEnabled(true);this.lineChartModel.setLongPressDuration(160);}
在页面即将显示时,这段代码会初始化图表的数据。它创建了一个包含随机数据的 LineDataSet
,设置了数据集的样式,如渐变填充颜色、不显示数据点等。然后将数据集添加到 LineData
对象中,并将其设置到图表模型中。同时,设置了图表的一些属性,如最大显示X轴范围、是否允许滑动、长按持续时间等。
5. 页面构建
build() {Stack() {LineChart({ model: this.lineChartModel }).width('100%').height('50%').backgroundColor(Color.White).margin({ top: 100 })if (this.showUI) {Line().startPoint([0, 0]).endPoint([0, this.lineChartModel.getContentRect().height()+ 100]).stroke(Color.Yellow).strokeWidth(4).position({ x: this.positionX }).opacity(0.5)Column() {Text(`x = ${this.dataX.toFixed(1).toString()}`).fontSize(20).fontWeight(FontWeight.Bolder)Text(`y = ${this.dataY.toString()}`).fontSize(20).fontWeight(FontWeight.Bolder)}.alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center).backgroundColor('#F2F2F2').position({ x: this.cursorPositionX - this.cursorSize / 2 }).width(this.cursorSize).aspectRatio(1).borderRadius(5)Circle({ width: 14, height: 14 }).position({ x: this.positionX - 7, y: this.positionY + 100 - 7}).fill(Color.White)Circle({ width: 10, height: 10 }).position({ x: this.positionX - 5, y: this.positionY + 100 - 5}).fill(Color.Red)}}
}
这段代码构建了页面的布局。首先是一个 LineChart
组件,用于显示图表。当 showUI
为 true
时,会显示一个垂直线、一个包含选中点数据的文本列、一个圆形游标和一个红色的点,以突出显示选中的数据点。
页面完整代码如下:
import {JArrayList,EntryOhos,ILineDataSet,LineData,LineChart,LineChartModel,Mode,LineDataSet,XAxisPosition,OnChartValueSelectedListener,Highlight,AxisDependency,ChartColorStop,
} from '@ohos/mpchart';
import display from '@ohos.display';/** CursorPage组件 */
@Entry
@Component
struct LongPressSlideCursorPage {/** LineChart 图表配置构建类 */@State private lineChartModel: LineChartModel = new LineChartModel();/** 选中点位置信息 */@State positionX: number = 0;@State positionY: number = 0;/**游标位置信息*/@State cursorPositionX: number = 0;@State cursorPositionY: number = 0;/** 选中点X轴数据信息*/@State dataX: number = 0;/** 选中点Y轴数据信息 */@State dataY: number = 0;/** 是否展示UI */@State showUI: boolean = false;/** UI宽度 */@State uiWidth: number = 0;/** UI高度 */@State uiHeight: number = 0;/**游标宽高**/cursorSize: number = 100;/** 数据选择监听 */private valueSelectedListener: OnChartValueSelectedListener = {onValueSelected: (e: EntryOhos, h: Highlight) => {/** 数据选中时显示气泡UI */this.showUI = true;/** 设置选中点的位置信息和数据信息 */this.dataX = Number(e.getX().toFixed(1));this.dataY = Number(e.getY().toFixed(1));let x = this.lineChartModel.getTransformer(AxisDependency.LEFT)?.getPixelForValues(e.getX(), e.getY()).x ?? 0;let y = this.lineChartModel.getTransformer(AxisDependency.LEFT)?.getPixelForValues(e.getX(), e.getY()).y ?? 0;this.positionX = x;this.positionY = y;if (x > this.uiWidth - this.cursorSize / 2 - 10) {x = this.uiWidth - this.cursorSize / 2 - 10;} else if (x < this.cursorSize / 2 + 10) {x = this.cursorSize / 2 + 10}this.cursorPositionX = x;},onNothingSelected: () => {/** 去除气泡UI */this.showUI = false;}}/** 数据初始化 */aboutToAppear() {this.uiWidth = px2vp(display.getDefaultDisplaySync().width);/** 创建一个 JArrayList 对象,用于存储 EntryOhos 类型的数据 */let values: JArrayList<EntryOhos> = new JArrayList<EntryOhos>();/** 循环生成 1 到 20 的随机数据,并添加到 values 中 */for (let i = 1; i <= 30; i++) {values.add(new EntryOhos(i, Math.random() * 100));}/** 创建 LineDataSet 对象,使用 values 数据,并设置数据集的名称为 'DataSet' */let lineDataSet = new LineDataSet(values, 'DataSet');lineDataSet.setMode(Mode.CUBIC_BEZIER);lineDataSet.setDrawCircles(false);let lineDataSetList: JArrayList<ILineDataSet> = new JArrayList<ILineDataSet>();//渐变色填充let gradientFillColor = new JArrayList<ChartColorStop>();gradientFillColor.add(["#0099CC", 0.2]);gradientFillColor.add(["#7F0099CC", 0.4]);gradientFillColor.add(["#ffffff", 1.0]);lineDataSet.setGradientFillColor(gradientFillColor);lineDataSet.setDrawFilled(true);lineDataSet.setDrawValues(false);lineDataSet.setColorByColor(0x0099cc);lineDataSet.setDrawHighlightIndicators(false);lineDataSetList.add(lineDataSet);/** 创建 LineData 对象,使用 lineDataSetList 数据,并将其传递给 lineChartModel */let lineData: LineData = new LineData(lineDataSetList);this.lineChartModel?.setData(lineData);this.lineChartModel.setOnChartValueSelectedListener(this.valueSelectedListener);this.lineChartModel.setHighlightPerLongPressEnabled(false);this.lineChartModel.setVisibleXRangeMaximum(10);this.lineChartModel.setSwipeEnabled(true);this.lineChartModel.setLongPressDuration(160);this.lineChartModel.setLongPressCursorEnabled(true);}build() {Stack() {LineChart({ model: this.lineChartModel }).width('100%').height('50%').backgroundColor(Color.White).margin({ top: 100 })if (this.showUI) {Line().startPoint([0, 0]).endPoint([0, this.lineChartModel.getContentRect().height()+ 100]).stroke(Color.Yellow).strokeWidth(4).position({ x: this.positionX }).opacity(0.5)Column() {Text(`x = ${this.dataX.toFixed(1).toString()}`).fontSize(20).fontWeight(FontWeight.Bolder)Text(`y = ${this.dataY.toString()}`).fontSize(20).fontWeight(FontWeight.Bolder)}.alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center).backgroundColor('#F2F2F2').position({ x: this.cursorPositionX - this.cursorSize / 2 }).width(this.cursorSize).aspectRatio(1).borderRadius(5)Circle({ width: 14, height: 14 }).position({ x: this.positionX - 7, y: this.positionY + 100 - 7}).fill(Color.White)Circle({ width: 10, height: 10 }).position({ x: this.positionX - 5, y: this.positionY + 100 - 5}).fill(Color.Red)}}}
}
三、总结
这段代码通过定义状态变量、数据选择监听器、数据初始化和页面构建,实现了在鸿蒙应用中绘制带有游标的折线图。用户可以通过长按图表来选中数据点,并显示相关的详细信息。这种交互方式提高了图表的可用性和用户体验。希望这篇文章能帮助你在鸿蒙开发中更好地使用MPChart图表库。
有疑问或者感兴趣的朋友,可以加QQ群沟通交流:274130009
相关文章:

鸿蒙MPChart图表自定义(六)在图表中绘制游标
在鸿蒙开发中,MPChart 是一个非常强大的图表库,它可以帮助我们创建各种精美的图表。今天,我们将继续探索鸿蒙MPChart的自定义功能,重点介绍如何在图表中绘制游标。 OpenHarmony三方库中心仓 一、效果演示 以下是效果演示图&…...

poi-tl+kkviewfile实现生成pdf业务报告
需求背景,需要把ai生成的一些业务数据,生成一份pdf报告 需求分析 简单来说,就是json生成pdf的方案。 直接生成pdf。适合一些pdf样式简单的场景,一般就是纯文本按序渲染,或者是纯表格。如果需要一些复杂的排布&#x…...

【Uniapp-Vue3】scroll-view可滚动视图区域组件
如果我们有一个区域有限的大盒子(黑),而我们要在盒子中装的东西(灰)过多,我们就会用到滚动视图: 表现在代码上就是下面这个样子: <template><view class"scrollView&…...
asp.net core webapi中的数据注解与数据验证
在这一课中,主要讲解了如何在 Web API 中使用数据注解(Data Annotations)和进行数据验证,以确保请求数据的有效性和完整性。 在 Web API 中,数据验证是确保客户端传递的数据符合业务规则和格式要求的关键步骤。数据注…...
PixPin—— 高效截图工具的下载与使用攻略
在日常的工作和学习中,一款好用的截图工具能极大地提高我们的效率。今天就来给大家介绍一款功能强大的截图工具 ——PixPin。 下载篇 PixPin 的下载非常简单,只需访问下载网站,在首页就能找到适合你操作系统的下载链接。如果你使用的是 Win…...
Go语言的 的多态性(Polymorphism)基础知识
Go语言的多态性(Polymorphism)基础知识 在编程语言中,多态性是一个核心概念,它允许同一接口被不同的数据类型所实现,从而在不影响代码结构的情况下增强代码的灵活性和可扩展性。在Go语言中,多态性通过接口…...

Vue框架主要用来做什么?Vue框架的好处和特性.
在快速发展的互联网时代,前端开发技术的变革日新月异,为开发者带来了前所未有的机遇与挑战。Vue.js,作为前端开发领域的一颗璀璨新星,以其轻量级、高效灵活的特性,赢得了广大开发者的青睐。本文将深入探讨Vue框架的主要…...

科普CMOS传感器的工作原理及特点
在当今数字化成像的时代,图像传感器无疑是幕后的关键 “功臣”,它宛如一位神奇的 “光影魔法师”,通过光电效应这一奇妙的物理现象,将光子巧妙地转换成电荷,为图像的诞生奠定基础。而在众多类型的图像传感器中…...
tensorflow 内存错误
使用tensorflow训练多个模型时,训练过程中容易出现内存错误,在这里记录一下解决办法。希望能帮到各位。 2025-01-02 22:31:03.489713: W tensorflow/core/common_runtime/bfc_allocator.cc:275] Allocator (GPU_0_bfc) ran out of memory trying to all…...

spring boot解决swagger中的v2/api-docs泄露漏洞
在配置文件中添加以下配置 #解决/v2/api-docs泄露漏洞 springfox:documentation:swagger-ui:enabled: falseauto-startup: false 处理前: 处理后:...

计算机网络 (25)IPV6
前言 IPv6,全称为“互联网协议第6版”(Internet Protocol Version 6),是由互联网工程任务组(IETF)设计的用于替代IPv4的下一代IP协议。 一、产生背景 IPv4,即互联网协议第4版,是现行…...
小程序组件 —— 30 组件 - 背景图片的使用
在编写小程序的样式文件时,可以使用 background-image 属性来设置元素的背景图像;但是这个属性在微信小程序中使用时存在坑; 注意事项:微信小程序中的 background-iamge 不支持本地路径!需要使用网络图片,…...

《Opencv》信用卡信息识别项目
目录 一、项目介绍 二、数据材料介绍 1、模板图片(1张) 2、需要处理的信用卡图片(5张) 三、实现过程 1、导入需要用到的库 2、设置命令行参数 3、模板图像中数字的定位处理 4、信用卡图像处理 5、模板匹配 四、总结 一…...

Matlab贝叶斯估计MCMC分析药物对不同种群生物生理指标数据评估可视化
全文链接:https://tecdat.cn/?p38756 摘要:本文着重探讨了如何利用Matlab实现贝叶斯估计。阐述了具体的实现流程,涵盖数据加载、先验常数设定、马尔可夫链蒙特卡洛(MCMC)属性指定、模型构建、运行链条以及结果查看等环…...

java 转义 反斜杠 Unexpected internal error near index 1
代码: String str"a\\c"; //出现异常,Unexpected internal error near index 1 //System.out.println(str.replaceAll("\\", "c"));//以下三种都正确 System.out.println(str.replace(\\, c)); System.out.println(str.r…...
网络安全常见的问题
1. 什么是 DDoS 攻击?如何防范? 答:DDoS 攻击是指利用大量的计算机或者其他网络设备,同时向目标网络或者服务器 发送 大量的数据流量,以致其无法正常工作,从而导致网络瘫痪或者服务器宕机的攻击行 为。 …...

在ubuntu22.04中使用bear命令追踪内核编译报错的原因分析和解决方案
1.说明 我在ubuntu22.04中使用bear命令追踪内核编译时发生如下报错: 如图,在链接名为libexec.so的动态库时发生错误 2 分析及解决过程 打印变量 LIB 发现其为空,也就是说 bear会去 /usr/bear/ 去找 libexec.so 去看一下 /usr/bear/是否存…...

【软考网工笔记】操作系统管理与配置——Windows
1-域名解析 Cache 域名解析 Cache 即 DNS 快取,DNS 快取需要应用客户机域名解析服务 DNSClient,其进程名为 svchost.exe -k NetworkService,可以输入命令:net stop dnscache 将其结束。原理是在 Windows 系统中,加入了…...

vue3 css实现文字输出带光标显示,文字输出完毕,光标消失的效果
Vue实现过程如下: <template><div ><p ref"dom_element" class"typing" :class"{over_fill: record_input_over}"></p></div> </template> <script setup> import {onMounted, ref} from…...

什么情况会导致JVM退出?
大家好,我是锋哥。今天分享关于【什么情况会导致JVM退出?】面试题。希望对大家有帮助; 什么情况会导致JVM退出? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 JVM(Java Virtual Machine)在不同情况下可能会退出&am…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...