HarmonyOS鸿蒙自定义绘图波浪球起伏

1732686680530.jpg
 // 三条波浪的配置
  private waves: PathClass[] = [
  // 最后面的波浪
    new PathClass(
      30,
      600 * 0.7,
      1,
      '#4Db4a4F7',
      '#4Db4a4F7'
    ),
    // 中间的波浪
    new PathClass(
      30,
      600 * 0.35,
      1,
      '#528A73F5',
      '#528A73F5'
    ),
    // 最前面的波浪
    new PathClass(
      30,
      0,
      1,
      '#b4a4F7',
      '#b4a4F7'
    )
  ]
  @State gradientColor: LinearGradient = new LinearGradient([
    { color: "#62D586", offset: 0.2 },
    { color: "#F5C743", offset: 0.5 },
    { color: "#D22C7D", offset: 0.8 },
  ]); 

Stack() {
        Canvas(this.context)
          .width(AppConstants.FULL_PERCENT)
          .height(AppConstants.FULL_PERCENT)
          .onReady(() => {
            // 初始化参数
            const canvasWidth = this.context.width;
            const canvasHeight = this.context.height;

            const animate = () => {
              this.context.clearRect(0, 0, canvasWidth, canvasHeight);
              const waveLength = 600;
              const cycles = Math.ceil(canvasWidth / waveLength) + 2;
              const totalWidth = cycles * waveLength;

              // 计算圆的参数
              const centerX = canvasWidth / 2;
              const centerY = canvasHeight / 2;
              let radius = (Math.min(canvasWidth, canvasHeight) * 0.7 / 2); // 圆的半径

              // 创建圆形裁剪区域,边框改为白色
              this.context.save();
              this.context.beginPath();
              this.context.arc(centerX, centerY, radius, 0, Math.PI * 2);
              this.context.strokeStyle = '#FFFFFF'; // 改为白色
              this.context.lineWidth = 2;
              this.context.stroke();
              this.context.clip();

              // 绘制每条波浪
              this.waves.forEach(wave => {
                this.context.beginPath();
                this.context.moveTo(-waveLength * 2, centerY + radius);

                for (let x = -waveLength * 2; x <= totalWidth; x += 2) {
                  const normalY = Math.sin((x + this.offsets + wave.phase) * (2 * Math.PI / waveLength));
                  // 波高从 radius/6.1 稍微增加到 radius/6
                  const y = normalY * (radius / 6) + centerY + (radius / 3);
                  this.context.lineTo(x, y);
                }

                this.context.lineTo(totalWidth, centerY + radius);
                this.context.lineTo(-waveLength * 2, centerY + radius);

                this.context.fillStyle = wave.color;
                this.context.strokeStyle = wave.stroke;
                this.context.lineWidth = 2;

                this.context.fill();
                this.context.stroke();
              });

              // 方案3:缩放画布来实现更大的字体
              this.context.save();
              this.context.scale(2, 2); // 整体放大2倍
              this.context.font = 'bold 62px Arial';
              this.context.fillStyle = '#000000';
              this.context.textAlign = 'center';
              this.context.textBaseline = 'middle';
              this.context.fillText(this.homeWaveView.toString(), centerX / 2, (centerY - radius / 3) / 2); // 注意坐标需要除以2

              // 第二行文字
              this.context.font = '20px Arial'; // 因为整体放大了2倍,所以这里设置20px最终显示就是40px
              this.context.fillStyle = '#8557FF';
              this.context.textAlign = 'center';
              this.context.textBaseline = 'middle';
              this.context.fillText(this.homeBarTextView, centerX / 2, (centerY - radius / 3) / 2 + 15); // 位置也需要考虑缩放


              this.context.restore();

              this.offsets = (this.offsets - 1.3) % waveLength;
              this.animationId = setTimeout(animate, 16);
            }

            // 启动动画
            animate();

          })
        Progress({ value: this.values, total: 360, type: ProgressType.Ring })
          .width('78%')
          .height('78%')
          .style({ strokeWidth: 7 })
          .color(this.gradientColor)
          .onClick(() => {
            this.bottomController.open()
          })
      }
      .width(AppConstants.FULL_PERCENT)
      .height('50%')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容