DEV Community

HarmonyOS
HarmonyOS

Posted on

Smart Watch - Stage - Smart Watch Circle Encircling Text Effect

Read the original article:Smart Watch - Stage - Smart Watch Circle Encircling Text Effect

Problem Description

How to implement the text effect around the circle of the smart watch?

Background Knowledge

Canvas or RichText can be used. Canvas is recommended (the drawing method is simple).

kbs--0be95b953fd24b5681211929171dfedc-9e8.png

Solution

1、Use Canvas to implement the function.

@Entry
@Component
@Preview
export struct Index {
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  // Convert to radian value
  private getAngle(n: number) {
    return Math.PI / 180 * n;
  }

  private drawCircleText(text: string) {
    const width = this.context.width, height = this.context.height;
    const fontSize = 14;
    const r = width / 2 - fontSize;
    this.context.clearRect(0, 0, width, height); // Clear canvas
    this.context.save();
    this.context.font = `${fontSize}vp`
    this.context.textBaseline = 'top';
    const charRadius = 360 / text.length; // Arc length per character
    this.context.translate(width / 2, height / 2);
    for (let i = 0; i < text.length; i++) {
      this.context.fillText(text.charAt(i), 0, -r);
      this.context.rotate(this.getAngle(charRadius));
    }
    this.context.restore();
  }

  build() {
    Row() {
      Column() {
        Canvas(this.context)
          // .margin({top:50})
          .width(200)
          .height(200)
          .borderColor('green')
          .borderWidth(1)
          .onReady(() => this.drawCircleText('Hello,World!Hello,World!'))
      }
      .width('100%')
    }
    .height('100%')
    .backgroundColor(Color.White)
  }
}
Enter fullscreen mode Exit fullscreen mode

2、Implemented by using RichText

interface RichTextProps {
  width: number;
  height: number;
  fontSize: number;
  fontColor: string;
  text: string;
}

function getRichTextStr(props: RichTextProps) {
  const width = props.width, height = props.height;
  const fontSize = props.fontSize, fontColor = props.fontColor;
  const str = `<div style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;">
          <svg style="overflow: visible; display: inline-block;" viewBox="0 0 100 100" width="${width}" height="${height}">
             <path fill='none' d="M 0,50 a 50,50 0 1, 1 0, 1 z" id="circle"></path>
             <text font-size='${fontSize}'  fill='${fontColor}'>
               <textPath xlink:href="#circle">
                  ${props.text}
               </textPath>
             </text>
          </svg>
        </div>`;
  return str;
};

@Entry
@Component
@Preview
export struct Index {
  defaultRichTextProps: RichTextProps = {
    width: 600,
    height: 600,
    fontSize: 14,
    fontColor: 'red',
    text: 'Hello,World!Hel!Hello,World!HelHello,World!HelWorld!Hel',
  };

  build() {
      Row() {
          Column() {
            Text('Implemented using RichText') // Implemented using RichText
              .width('100%')
              .margin({ bottom: 10, left: 10 })
            RichText(getRichTextStr(this.defaultRichTextProps))
              .borderColor('green')
              .borderWidth(1)
              .width(300)
              .height(300)

          }
          .width('100%')
      }
  }
}
Enter fullscreen mode Exit fullscreen mode

Written by Ahmet Furkan Sevim

Top comments (0)