鸿蒙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 组件,用于显示图表。当 showUItrue 时,会显示一个垂直线、一个包含选中点数据的文本列、一个圆形游标和一个红色的点,以突出显示选中的数据点。

页面完整代码如下:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/948829.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《新概念模拟电路》-电流源电路

电流源电路 本系列文章主要学习《新概念模拟电路》中的知识点。在工作过程中&#xff0c;碰到一些问题&#xff0c;于是又翻阅了模电这本书。我翻阅的是ADI出版的&#xff0c;西安交通大学电工中心杨建国老师编写的模电书。 本文主要是基于前文《新概念模拟电路》-三极管的基础…

Java实现下载excel模板,并实现自定义下拉框

GetMapping("excel/download")ApiOperation(value "模板下载")public void getUserRecordTemplate(HttpServletResponse response, HttpServletRequest request) throws IOException {OutputStream outputStream response.getOutputStream();InputStream…

C 实现植物大战僵尸(四)

C 实现植物大战僵尸&#xff08;四&#xff09; 音频稍卡顿问题&#xff0c;用了 SFML 三方库已优化解决 安装 SFML 资源下载 https://www.sfml-dev.org/download/sfml/2.6.2/ C 实现植物大战僵尸&#xff0c;完结撒花&#xff08;还有个音频稍卡顿的性能问题&#xff0c;待…

回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测

回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 一、方法概述 CNN-BiLSTM-Attention多输入单输出回归预测方法旨在通过融合CNN的局…

Ansible之批量管理服务器

文章目录 背景第一步、安装第二步、配置免密登录2.1 生成密钥2.2 分发公钥2.3 测试无密连接 背景 Ansible是Python强大的服务器批量管理 第一步、安装 首先要拉取epel数据源&#xff0c;执行以下命令 yum -y install epel-release安装完毕如下所示。 使用 yum 命令安装 an…

让css设置的更具有合理性

目录 一、合理性设置宽高 二、避免重叠情况&#xff0c;不要只设置最大宽 三、优先使用弹性布局特性 四、单词、数字换行处理 五、其他编码建议 平常写css时&#xff0c;除了遵循一些 顺序、简化、命名上的规范&#xff0c;让css具有合理性也是重要的一环。 最近的需求场…

【微服务】1、引入;注册中心;OpenFeign

微服务技术学习引入 - 微服务自2016年起搜索指数持续增长&#xff0c;已成为企业开发大型项目的必备技术&#xff0c;中高级java工程师招聘多要求熟悉微服务相关技术。微服务架构介绍 概念&#xff1a;微服务是一种软件架构风格&#xff0c;以专注于单一职责的多个响应项目为基…

设计模式 结构型 组合模式(Composite Pattern)与 常见技术框架应用 解析

组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。通过这种模式&#xff0c;客户端可以一致地处理单个对象和对象组合。 在软件开发中&#xff0c;我们经常会遇到处理对象的层…

抢先体验:人大金仓数据库管理系统KingbaseES V9 最新版本 CentOS 7.9 部署体验

一、简介 KingbaseES 是中国人大金仓信息技术股份有限公司自主研发的一款通用关系型数据库管理系统&#xff08;RDBMS&#xff09;。 作为国产数据库的杰出代表&#xff0c;它专为中国市场设计&#xff0c;广泛应用于政府、金融、能源、电信等关键行业&#xff0c;以高安全性…

Linux驱动开发(17):输入子系统–电阻触摸驱动实验

有关电阻触摸的基础知识内容可以参考野火STM32相关教程&#xff0c;这里只介绍电阻触摸驱动的相关内容。与一般的微处理器 不同&#xff0c;本节使用的imx6ull内自带触摸屏控制器&#xff0c;只需要把电阻触摸屏的信号线接到对应的IO即可&#xff0c;通过配置imx6ull 触摸屏控制…

8、RAG论文笔记(Retrieval-Augmented Generation检索增强生成)

RAG论文笔记 1、 **研究背景与动机**2、方法概述3、RAG 模型架构3.1总体架构3.2 Generator&#xff08;生成器&#xff09;3.3 检索器&#xff08;Retriever&#xff09;3.4训练&#xff08;Training&#xff09;3.5**解码方法**&#xff08;求近似 &#xff09;3.6微调的参数 …

简易CPU设计入门:通用寄存器的读写

项目代码下载 请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 下载本项目代码 准备好了项目源代码以后&#xff0c;我…

【动手学电机驱动】STM32-MBD(3)Simulink 状态机模型的部署

STM32-MBD&#xff08;1&#xff09;安装 Simulink STM32 硬件支持包 STM32-MBD&#xff08;2&#xff09;Simulink 模型部署入门 STM32-MBD&#xff08;3&#xff09;Simulink 状态机模型的部署 【动手学电机驱动】STM32-MBD&#xff08;3&#xff09;Simulink 状态机模型部署…

Linux运维相关基础知识(二)

系列文章目录 Linux常用命令 linux 账号管理与权限设定 Linux运维相关基础知识 文章目录 系列文章目录前言1. 自动任务执行at 与 atdcrontab 与 crond 2. SELinuxtty多任务管理与进程管理相关的命令/proc/* 文件的意义SELinux 3. 守护进程早期SystemV的init管理行为中daemon…

K8s集群平滑升级(Smooth Upgrade of K8S Cluster)

简介&#xff1a; Kubernetes ‌ &#xff08;简称K8s&#xff09;是一个开源的容器编排和管理平台&#xff0c;由Google开发并维护。它最初是为了解决谷歌内部大规模容器管理的问题而设计的&#xff0c;后来在2014年开源&#xff0c;成为云原生技术的核心组成部分。‌‌1 K8…

党员学习交流平台

本文结尾处获取源码。 本文结尾处获取源码。 本文结尾处获取源码。 一、相关技术 后端&#xff1a;Java、JavaWeb / Springboot。前端&#xff1a;Vue、HTML / CSS / Javascript 等。数据库&#xff1a;MySQL 二、相关软件&#xff08;列出的软件其一均可运行&#xff09; I…

uniapp--HBuilder开发

提示&#xff1a;本文为学习内容&#xff0c;若有错误&#xff0c;请联系作者&#xff0c;谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…

GraphRAG实践:neo4j试用

文章目录 前言欢迎界面示例数据库使用大模型生成查询语句总结 前言 上回说道&#xff0c;我们使用docker部署了一个neo4j。 我们现在对它进行一些试用。 欢迎界面 在浏览器中输入http://localhost:7474/ 输入对应的东西&#xff0c;点击connect 现在咱的数据库里什么都没有…

两种分类代码:独热编码与标签编码

目录 一、说明 二、理解分类数据 2.1 分类数据的类型&#xff1a;名义数据与序数数据 2.2 为什么需要编码 三、什么是独热编码&#xff1f; 3.1 工作原理&#xff1a;独热编码背后的机制 3.2 应用&#xff1a;独热编码的优势 四、什么是标签编码&#xff1f; 4.1 工作原理&…

【AWS SDK PHP】This operation requests `sigv4a` auth schemes 问题处理

使用AWS SDK碰到的错误&#xff0c;其实很简单&#xff0c;要装个扩展库 保持如下 Fatal error: Uncaught Aws\Auth\Exception\UnresolvedAuthSchemeException: This operation requests sigv4a auth schemes, but the client currently supports sigv4, none, bearer, sigv4-…