当前位置:   article > 正文

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

鸿蒙 canvas 曲线图

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

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

  1. @Entry
  2. @Component
  3. struct csPage {
  4. tempMax : number[] = [21, 38, 17, 21, 21, 32, 24, 22, 25, 33, 24, 26, 25, 34, 28];
  5. tempMin : number[] = [14, 21, 12, 13, 18, 23, 17, 15, 13, 18, 18, 10, 15, 24, 20];
  6. 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'];
  7. weatherConditions: string[] = ['小雨', '多云', '多云', '晴', '晴', '小雨', '大雨', '晴', '多云', '多云', '小雨', '晴', '晴', '多云', '小雨'];
  8. icon: string[] = ['100', '101', '102', '103', '104', '300', '301', '302', '303', '304', '305', '306', '307', '308', '309'];
  9. windDirDay: string[] = ['西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风', '西南风'];
  10. 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'];
  11. // 定义左右边距
  12. sideMargin: number = 40; // 根据需要调整
  13. //使用RenderingContext在Canvas组件上进行绘制,绘制对象可以是矩形、文本、图片等。
  14. settings: RenderingContextSettings = new RenderingContextSettings(true);
  15. context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  16. // canvasHeight:表示曲线图高度,itemWidth:表示每两天的温度点之间的距离。
  17. canvasHeight: number = 250;
  18. itemWidth: number = 50;
  19. build() {
  20. Row() {
  21. Column({ space: 15 }) {
  22. Text('7天趋势预报')
  23. .fontSize(18)
  24. .padding(10)
  25. .margin({top:15})
  26. .fontWeight(FontWeight.Bold)
  27. Scroll() {
  28. Canvas(this.context)
  29. .width(this.tempMax.length * this.itemWidth + this.itemWidth + this.sideMargin * 2)
  30. .height('100%')
  31. .onReady(() => {
  32. //找出高温曲线的最大值,和低温曲线的最小值,用于后续确定曲线竖直方向的比例
  33. const maxTemperature: number = Math.max(...this.tempMax);
  34. const minTemperature: number = Math.min(...this.tempMin);
  35. //最高-最低温度的上下距离 step 表示每改变 1℃,纵坐标改变的高度
  36. const step: number = this.canvasHeight * 0.4 / (maxTemperature - minTemperature);
  37. const curveChartMargin: number = this.canvasHeight * 0.09;
  38. //设置曲线样式
  39. this.context.lineWidth = 1;
  40. this.context.font = '13vp sans-serif';
  41. this.context.fillStyle = '#000000';
  42. this.context.strokeStyle = 'blue'
  43. this.context.globalAlpha = 1;
  44. this.context.textAlign='start'
  45. //由于同一天的高温点、低温点的x坐标相同,所以x坐标使用同一组数据。
  46. let xPos: number[] = [];
  47. let tempMaxPos: number[] = [];
  48. let tempMin: number[] = [];
  49. //确定温度点的坐标,再绘制,并绘制温度文字
  50. for (let i: number = 0; i < this.tempMax.length; i++) {
  51. // 确定每个点的坐标,包括高温和低温,其中,高温和低温坐标的横坐标都是一致的
  52. let x: number = this.sideMargin + (i * this.itemWidth);
  53. let yHeight: number = this.canvasHeight - (curveChartMargin + (this.tempMax [i] - minTemperature) * step);
  54. let yLow: number = this.canvasHeight - (curveChartMargin + (this.tempMin[i] - minTemperature) * step);
  55. // 存放数据
  56. xPos.push(x);
  57. tempMaxPos.push(yHeight);
  58. tempMin.push(yLow);
  59. // 给每个点画出一个圆并填充颜色,这里设置圆的半径为2
  60. this.context.fillStyle = "blue"; // 设置低温点颜色为蓝色
  61. let region: Path2D = new Path2D();
  62. region.ellipse(x, yHeight, 2, 2, 0, 0, Math.PI * 2);
  63. region.ellipse(x, yLow, 2, 2, 0, 0, Math.PI * 2);
  64. this.context.fill(region);
  65. // 绘制日期
  66. this.context.fillStyle = "black"; // 可以设置文字颜色
  67. let dateStr: string = this.weatherDates[i];
  68. this.context.fillText(dateStr, x - this.context.measureText(dateStr).width / 2, 20);
  69. let highWindDirDayStr:string=this.windDirDay[i]
  70. this.context.fillText(highWindDirDayStr,x-this.context.measureText(highWindDirDayStr).width/2,35)
  71. // 绘制天气图标
  72. let icon: string = Q_Weather_Image(this.icon[i]);
  73. let imgIcon = new ImageBitmap(icon)
  74. this.context.drawImage(imgIcon,x - this.context.measureText(dateStr).width / 2,45, 30, 30);
  75. // 绘制天气状态
  76. let highConditionStr: string = this.weatherConditions[i];
  77. this.context.fillText(highConditionStr, x - this.context.measureText(highConditionStr).width / 2, 90);
  78. // 绘制高温低温的文字
  79. this.context.fillStyle = "black"; // 可以设置文字颜色
  80. let maxTemperatureStr: string = `${this.tempMax[i]}℃`;
  81. let minTemperatureStr: string = `${this.tempMin[i]}℃`;
  82. this.context.fillText(maxTemperatureStr, x - this.context.measureText(maxTemperatureStr).width / 2, yHeight - 6);
  83. this.context.fillText(minTemperatureStr, x - this.context.measureText(minTemperatureStr).width / 2, yLow + 15);
  84. // 绘制天气状态
  85. let conditionStr: string = this.weatherConditions[i];
  86. this.context.fillText(conditionStr, x - this.context.measureText(conditionStr).width / 2, this.canvasHeight + 60);
  87. //绘制风向
  88. let windDirDayStr:string=this.windDirDay[i]
  89. this.context.fillText(windDirDayStr,x-this.context.measureText(windDirDayStr).width/2,this.canvasHeight+77)
  90. //绘制风向等级
  91. let windScaleDayStr:string= `${this.windScaleDay[i]}级`
  92. this.context.fillText(windScaleDayStr,x-this.context.measureText(windScaleDayStr).width/2,this.canvasHeight+95)
  93. // 绘制天气图标
  94. // 下载并绘制天气图标
  95. let iconUrl: string = Q_Weather_Image(this.icon[i]);
  96. let img = new ImageBitmap(iconUrl)
  97. this.context.drawImage(img,x - this.context.measureText(windScaleDayStr).width / 2.2, this.canvasHeight+ 15, 30, 30);
  98. }
  99. // 绘制高温曲线
  100. this.context.beginPath();
  101. this.context.moveTo(xPos[0], tempMaxPos[0]);
  102. for (let i: number = 1; i < xPos.length; i++) {
  103. //let x0: number = i * this.itemWidth;
  104. // let x0: number = sideMargin + i * this.itemWidth;
  105. // let y0: number = this.canvasHeight - (curveChartMargin + (this.tempMax[i - 1] - minTemperature) * step);
  106. let x0: number = xPos[i - 1];
  107. let y0: number = tempMaxPos[i - 1];
  108. this.context.bezierCurveTo(x0 + (xPos[i] - x0) * 0.3, y0, xPos[i] - (xPos[i] - x0) * 0.3, tempMaxPos[i], xPos[i], tempMaxPos[i]);
  109. }
  110. this.context.stroke();
  111. // 绘制低温曲线
  112. this.context.beginPath();
  113. this.context.moveTo(xPos[0], tempMin[0]);
  114. for (let i: number = 1; i < xPos.length; i++) {
  115. // let x0: number = i * this.itemWidth;
  116. // let x0: number = sideMargin + i * this.itemWidth;
  117. // let y0: number = this.canvasHeight - (curveChartMargin + (this.tempMin[i - 1] - minTemperature) * step);
  118. let x0: number = xPos[i - 1];
  119. let y0: number = tempMin[i - 1];
  120. this.context.bezierCurveTo(x0 + (xPos[i] - x0) * 0.3, y0, xPos[i] - (xPos[i] - x0) * 0.3, tempMin[i], xPos[i], tempMin[i]);
  121. }
  122. this.context.stroke();
  123. });
  124. }
  125. .scrollable(ScrollDirection.Horizontal)
  126. .scrollBar(BarState.Off);
  127. }
  128. .width('100%')
  129. .height('60%')
  130. .backgroundColor($r('app.color.home_bg'))
  131. .borderRadius(20)
  132. }
  133. .width('100%')
  134. .height('100%')
  135. .justifyContent(FlexAlign.Center)
  136. .backgroundColor($r('app.color.daily_bg'))
  137. }
  138. }
  139. function Q_Weather_Image(img: string): string {
  140. let url = `https://a.hecdn.net/img/common/icon/202106d/${img}.png`;
  141. return url;
  142. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/971565
推荐阅读
  

闽ICP备14008679号