首页 > 其他分享 >鸿蒙OS开发使用Canvas组件绘制天气曲线图

鸿蒙OS开发使用Canvas组件绘制天气曲线图

时间:2024-08-07 16:53:08浏览次数:14  
标签:Canvas string 曲线图 05 number let context OS xPos

参考下文: 鸿蒙征文 | 使用Canvas组件绘制天气曲线图_harmonyos_鸑鷟407-HarmonyOS开发者社区效果图: 原理 使用贝塞尔曲线 首先可以了解一下贝塞尔曲线。 如果看不懂也没关系,这里会直接讲绘制曲线的步骤。 使用CanvasRenderingContext2D对象。 首先使用beginPath方法确定起始点。 这里会循环地用到bezierCurveTo(三次贝塞尔曲线)方法。该方法需要三个点的坐标,即图上的点1、2、3。 这里的点3就表示温度的点。为了让曲线更平滑,我们让点1的高度与起始 鸑鷟407 HarmonyOS开发者社区icon-default.png?t=N7T8https://harmonyosdev.csdn.net/660cdf2c9ab37021bfa7a47c.html

效果图:(左右可以滑动)


@Entry
@Component
struct csPage {
  tempMax : number[] = [21, 38, 17, 21, 21, 32, 24, 22, 25, 33, 24, 26, 25, 34, 28];
  tempMin : number[] = [14, 21, 12, 13, 18, 23, 17, 15, 13, 18, 18, 10, 15, 24, 20];
  weatherDates: string[] = ['05/04', '05/05', '05/06', '05/07', '05/08', '05/09', '05/10', '05/11', '05/12', '05/13', '05/14', '05/15', '05/16', '05/17', '05/18'];
  weatherConditions: string[] = ['小雨', '多云', '多云', '晴', '晴', '小雨', '大雨', '晴', '多云', '多云', '小雨', '晴', '晴', '多云', '小雨'];
  icon: string[] =              ['100', '101', '102', '103', '104', '300', '301', '302', '303', '304', '305', '306', '307', '308', '309'];
  windDirDay: string[] =              ['西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风'];
  windScaleDay: string[] =              ['1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2', '1-2'];

  // 定义左右边距
  sideMargin: number = 40; // 根据需要调整
  //使用RenderingContext在Canvas组件上进行绘制,绘制对象可以是矩形、文本、图片等。
  settings: RenderingContextSettings = new RenderingContextSettings(true);
  context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  // canvasHeight:表示曲线图高度,itemWidth:表示每两天的温度点之间的距离。
  canvasHeight: number = 250;
  itemWidth: number = 50;



  build() {
    Row() {
      Column({ space: 15 }) {
        Text('7天趋势预报')
          .fontSize(18)
          .padding(10)
          .margin({top:15})
          .fontWeight(FontWeight.Bold)
        Scroll() {
          Canvas(this.context)
            .width(this.tempMax.length * this.itemWidth + this.itemWidth + this.sideMargin * 2)
            .height('100%')
            .onReady(() => {
              //找出高温曲线的最大值,和低温曲线的最小值,用于后续确定曲线竖直方向的比例
              const maxTemperature: number = Math.max(...this.tempMax);
              const minTemperature: number = Math.min(...this.tempMin);
              //最高-最低温度的上下距离 step 表示每改变 1℃,纵坐标改变的高度
              const step: number = this.canvasHeight * 0.4 / (maxTemperature - minTemperature);
              const curveChartMargin: number = this.canvasHeight * 0.09;

              //设置曲线样式
              this.context.lineWidth = 1;
              this.context.font = '13vp sans-serif';
              this.context.fillStyle = '#000000';
              this.context.strokeStyle = 'blue'
              this.context.globalAlpha = 1;
              this.context.textAlign='start'

              //由于同一天的高温点、低温点的x坐标相同,所以x坐标使用同一组数据。
              let xPos: number[] = [];
              let tempMaxPos: number[] = [];
              let tempMin: number[] = [];
              //确定温度点的坐标,再绘制,并绘制温度文字
              for (let i: number = 0; i < this.tempMax.length; i++) {
                // 确定每个点的坐标,包括高温和低温,其中,高温和低温坐标的横坐标都是一致的
                let x: number = this.sideMargin + (i * this.itemWidth);
                let yHeight: number = this.canvasHeight - (curveChartMargin + (this.tempMax [i] - minTemperature) * step);
                let yLow: number = this.canvasHeight - (curveChartMargin + (this.tempMin[i] - minTemperature) * step);

                // 存放数据
                xPos.push(x);
                tempMaxPos.push(yHeight);
                tempMin.push(yLow);

                // 给每个点画出一个圆并填充颜色,这里设置圆的半径为2
                this.context.fillStyle = "blue"; // 设置低温点颜色为蓝色
                let region: Path2D = new Path2D();
                region.ellipse(x, yHeight, 2, 2, 0, 0, Math.PI * 2);
                region.ellipse(x, yLow, 2, 2, 0, 0, Math.PI * 2);
                this.context.fill(region);



                // 绘制日期
                this.context.fillStyle = "black"; // 可以设置文字颜色
                let dateStr: string = this.weatherDates[i];
                this.context.fillText(dateStr, x - this.context.measureText(dateStr).width / 2,  20);
                let highWindDirDayStr:string=this.windDirDay[i]
                this.context.fillText(highWindDirDayStr,x-this.context.measureText(highWindDirDayStr).width/2,35)
                // 绘制天气图标
                let icon: string = Q_Weather_Image(this.icon[i]);
                let   imgIcon = new ImageBitmap(icon)
                this.context.drawImage(imgIcon,x - this.context.measureText(dateStr).width / 2,45, 30, 30);
                // 绘制天气状态
                let  highConditionStr: string = this.weatherConditions[i];
                this.context.fillText(highConditionStr, x - this.context.measureText(highConditionStr).width / 2, 90);




                // 绘制高温低温的文字
                this.context.fillStyle = "black"; // 可以设置文字颜色
                let maxTemperatureStr: string = `${this.tempMax[i]}℃`;
                let minTemperatureStr: string = `${this.tempMin[i]}℃`;
                this.context.fillText(maxTemperatureStr, x - this.context.measureText(maxTemperatureStr).width / 2, yHeight - 6);
                this.context.fillText(minTemperatureStr, x - this.context.measureText(minTemperatureStr).width / 2, yLow + 15);


                // 绘制天气状态
                let conditionStr: string = this.weatherConditions[i];
                this.context.fillText(conditionStr, x - this.context.measureText(conditionStr).width / 2, this.canvasHeight + 60);
                //绘制风向
                let  windDirDayStr:string=this.windDirDay[i]
                this.context.fillText(windDirDayStr,x-this.context.measureText(windDirDayStr).width/2,this.canvasHeight+77)
                //绘制风向等级
                let windScaleDayStr:string= `${this.windScaleDay[i]}级`
                this.context.fillText(windScaleDayStr,x-this.context.measureText(windScaleDayStr).width/2,this.canvasHeight+95)
                // 绘制天气图标
                // 下载并绘制天气图标
                let iconUrl: string = Q_Weather_Image(this.icon[i]);
                let   img = new ImageBitmap(iconUrl)
                this.context.drawImage(img,x - this.context.measureText(windScaleDayStr).width / 2.2, this.canvasHeight+ 15, 30, 30);


              }

              // 绘制高温曲线
              this.context.beginPath();
              this.context.moveTo(xPos[0], tempMaxPos[0]);
              for (let i: number = 1; i < xPos.length; i++) {
                //let x0: number = i * this.itemWidth;
                // let x0: number = sideMargin + i * this.itemWidth;
                // let y0: number = this.canvasHeight - (curveChartMargin + (this.tempMax[i - 1] - minTemperature) * step);
                let x0: number = xPos[i - 1];
                let y0: number = tempMaxPos[i - 1];
                this.context.bezierCurveTo(x0 + (xPos[i] - x0) * 0.3, y0, xPos[i] - (xPos[i] - x0) * 0.3, tempMaxPos[i], xPos[i], tempMaxPos[i]);
              }
              this.context.stroke();

              // 绘制低温曲线
              this.context.beginPath();
              this.context.moveTo(xPos[0], tempMin[0]);
              for (let i: number = 1; i < xPos.length; i++) {
               // let x0: number = i * this.itemWidth;
               //  let x0: number = sideMargin + i * this.itemWidth;
               //  let y0: number = this.canvasHeight - (curveChartMargin + (this.tempMin[i - 1] - minTemperature) * step);
                let x0: number = xPos[i - 1];
                let y0: number = tempMin[i - 1];
                this.context.bezierCurveTo(x0 + (xPos[i] - x0) * 0.3, y0, xPos[i] - (xPos[i] - x0) * 0.3, tempMin[i], xPos[i], tempMin[i]);
              }
              this.context.stroke();
            });
        }
        .scrollable(ScrollDirection.Horizontal)
        .scrollBar(BarState.Off);
      }
      .width('100%')
      .height('60%')
      .backgroundColor($r('app.color.home_bg'))
      .borderRadius(20)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .backgroundColor($r('app.color.daily_bg'))

  }
}

function Q_Weather_Image(img: string): string {
  let url = `https://a.hecdn.net/img/common/icon/202106d/${img}.png`;
  return url;
}

标签:Canvas,string,曲线图,05,number,let,context,OS,xPos
From: https://blog.csdn.net/qq_28189091/article/details/140995699

相关文章

  • HarmonyOS DevEco Studio彻底修改工程名称
    关闭项目将项目文件夹替换为新的名称后重新打开项目将AppScope/app.json5中的bundleName改为新的包名{"app":{"bundleName":"com.example.newname",//改为新的包名"vendor":"example","versionCode":1000000,"......
  • CentOS Stream 9 安装mysql 开启远程访问 忽略大小写
     更新sudodnfupdate安装MySQL服务器:这边安装的是默认8.0sudodnfinstallmysql-server启动MySQL服务:sudosystemctlstartmysqld确保MySQL服务设置为在启动时自动启动:sudosystemctlenablemysqld运行初始安全脚本来设置root用户密码和调整安全......
  • iOS开发-属性的内存管理
    Objective-C中,类的实例变量(instancevariables)和属性(properties)是两种不同的概念,其中属性的内存管理就较为复杂。Objective-C提供了多种属性修饰符,用于管理对象的内存。这些修饰符用于控制对象的生命周期和内存管理行为。以下是一些常见的属性修饰符及其内存管理行为的详细介绍:......
  • iOS app启动优化
    app的启动阶段可分为main函数调用前和main函数调用后,分别都做了些什么呢1、pre-main阶段   1)加载应用的可执行文件(自身App的所有.o文件的集合)  2)加载动态链接器dyld(dynamicloader,是一个专门用来加载动态链接库的库)  3)dyld递归加载应用所有依赖的动态链接库dyli......
  • 石英 CMOS 振荡器 PF1612 系列(1 to 200MHz)介绍
    一、引言在现代电子技术的快速发展中,精确和稳定的时钟信号是各种电子设备正常运行的核心要素之一。石英CMOS振荡器作为一种关键的时钟源组件,以其出色的性能和可靠性在众多领域发挥着重要作用。本文将深入介绍石英CMOS振荡器PF1612系列(1to200MHz),探讨其独特的特点、......
  • EF Core连接PostgreSQL数据库
    PostgreSQL数据库介绍PostgreSQL是一个功能强大的开源对象关系型数据库管理系统(RDBMS)。最初于1986年在加州大学伯克利分校的POSTGRES项目中诞生,PostgreSQL以其稳定性、灵活性和扩展性而著称。它支持丰富的数据类型、复杂的查询、事务完整性、多版本并发控制(MVCC)、存储过程等高级......
  • OSGI
    OSGI基础概述概述:OSGI是OpenServicesGatewayinitiative的缩写,叫做开放服务网关协议,通常可能指OSGi联盟、OSGi标准或者OSGi框架。OSGI:OSGI联盟现在将OSGI定义为一种技术,该技术是指一系列用于定义Java动态化组件系统的标准。这些标准通过为大型分布式系统以及嵌入式系统提供一......
  • <转载>bios 关机过程
    [CSDNBIOS关机过程](https://blog.csdn.net/robinsongsog/article/details/50993333)热启动,冷启动,关机,这些词相信大家都很熟悉,今天就从BIOS的角度,说说这三种reset具体是怎么实现的。/**Resetthesystem.@paramResetTypewarmorcold@paramResetStatus......
  • docker启动服务,nacos注册地址默认是容器内IP
    在使用Nacos注册服务时,通常是因为Nacos在Docker中运行时,默认会使用容器的网络设置。本机ip是:192.168.16.163但发现注册到nacos上ip却变了,这样的话调用这个服务是调不同的,除非建docker网络 实现宿主机ip注册的方法:docker-compose问价设置宿主机ipversion:'3......
  • Python安装教程(含MacOS&&Linux系统)
    Python安装教程Windows用户访问Python官网:WelcometoPython.org 打开下载好的安装包根据提示安装   Pip换源(系统级别)(注:Pip在3.4以上的版本才支持,3.4之前的版本可以在cmd中输入 easy_installpip 下载pip)1.为什么要换源?Python安装......