普通视图

发现新文章,点击刷新页面。
昨天 — 2025年6月9日首页

✏️Canvas实现环形文字

2025年6月9日 14:09

画画.png

什么是环形文字?

搜索相关的图片可以看到

image-20250609131652149

从上面可以得知, 环形文字其实就是文字围绕一个中心点或一个圆形区域(如圆形徽章、硬币、印章、表盘、圆形按钮、图标等)进行布局.

在前端中,如果想要实现这种环形文字,我们可以借助canvas来实现,也可以用传统的css来实现。

这边采用的是cavans来实现

最终效果

image-20250609132324166

完整代码

<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>文字环绕</title>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      canvas {
        background: #1a1a1a;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas" height="800px" width="800px"></canvas>
    <script>
      const canvas = document.getElementById('canvas')
      const ctx = canvas.getContext('2d')
      const num = 360
      if (!ctx) console.log('上下文对象不存在')
      ctx.font = '24px 微软雅黑'
      ctx.fillStyle = '#fff'
      /**
       * @function 环形文本
       * @param text 文本
       * @params spacing 间距
       */
      const circularText = (
        text,
        spacing,
        options = {
          x: 400,
          y: 400,
          radius: 250
        }
      ) => {
        const num = 360
        for (let index = 0; index < num; index += spacing) {
          const startAngle = (Math.PI * index) / 180
          const angle = parseFloat(startAngle)
          ctx.save()
          ctx.beginPath()
          ctx.translate(
            options.x + Math.cos(angle) * options.radius,
            options.y + Math.sin(angle) * options.radius
          )
          ctx.rotate(Math.PI / 2 + angle)
          ctx.font = '24px 微软雅黑'
          ctx.fillStyle = '#fff'
          ctx.fillText(text, 0, 0)
          ctx.restore()
        }
      }
      circularText('/', 3.6)
      circularText('+', 10, {
        x: 400,
        y: 400,
        radius: 200
      })
      circularText('{', 20, {
        x: 400,
        y: 400,
        radius: 150
      })
      circularText('</>', 30, {
        x: 400,
        y: 400,
        radius: 100
      })
      const poetry = '桃之夭夭,灼灼其华。之子于归,宜其室家。'
      const total = num / 20
      // 汉字环绕
      for (let index = 0; index < total; index++) {
        const text = poetry.charAt(index % total)
        const startAngle = (Math.PI * index * 20) / 180
        const angle = parseFloat(startAngle)
        ctx.save()
        ctx.beginPath()
        ctx.translate(400 + Math.cos(angle) * 300, 400 + Math.sin(angle) * 300)
        ctx.rotate(Math.PI / 2 + angle)
        ctx.fillText(text, 0, 0)
        ctx.restore()
      }
      ;(function () {})()
    </script>
  </body>
</html>

实现思路

  1. 根据间距计算在环上面的位置,以及起始弧度
  2. 文字按照环形排列
  3. 对每一个字符,进行旋转
const total = num / 20
for (let index = 0; index < total; index++) {
    // 计算当前文字所在位置的角度(弧度制)。因为每个文字间隔20度,所以当前角度为`index * 20`度,然后转换为弧度(乘以π除以180)
    const startAngle = (Math.PI * index * 20) / 180
    // 确保是浮点数,可以省略
    const angle = parseFloat(startAngle)
   // 在通过sin和cos函数计算 对应的文字点在圆周上面的坐标
    ctx.fillText(
      'A',
      400 + Math.cos(angle) * 300,
      400 + Math.sin(angle) * 300
    )
  }

x=400 + Math.cos(angle) * 300

y=400 + Math.sin(angle) * 300

这个x,y就是文字坐标

公式如下:

x = 圆心的x坐标+Math.cos(弧度)*半径
y = 圆心的y坐标+Math.cos(弧度)*半径

最终画出来的效果是这样的

image-20250609134345431

这时候文字字符以及围成一个圆形了

但是文字本身还没有旋转到对应的角度,看起来就很奇怪。

这时候需要用到下面几个方法

  • save():用于存储当前绘制状态

  • translate():修改当前画布原点,这里要注意 这个方法修改的是整个画布的原点

  • rotate():根据画布原点旋转画布

  • restore():恢复最近的保存状态

旋转字符的步骤如下: 保存状态->将 字符坐标设置画布原点->旋转画布->恢复到上一次的画布绘制状态

ctx.save()
ctx.beginPath()
ctx.translate(400 + Math.cos(angle) * 300, 400 + Math.sin(angle) * 300)
ctx.rotate(Math.PI / 2 + angle)
ctx.fillText(text, 0, 0)
ctx.restore()

之前我们将文本按圆心环绕绘制了,那么这里就按前面获取到的字符坐标设置原点

完整代码如下:

<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>文字环绕</title>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      canvas {
        background: #1a1a1a;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas" height="800px" width="800px"></canvas>
    <script>
      const canvas = document.getElementById('canvas')
      const ctx = canvas.getContext('2d')
      const num = 360
      if (!ctx) console.log('上下文对象不存在')
      ctx.font = '24px 微软雅黑'
      ctx.fillStyle = '#fff'
      const total = num / 20
      // 汉字环绕
      for (let index = 0; index < total; index++) {
        const startAngle = (Math.PI * index * 20) / 180
        const angle = parseFloat(startAngle)
        ctx.save()
        ctx.beginPath()
        ctx.translate(400 + Math.cos(angle) * 300, 400 + Math.sin(angle) * 300)
        ctx.rotate(Math.PI / 2 + angle)
        ctx.fillText('A', 0, 0)
        ctx.restore()
      }
      ;(function () {})()
    </script>
  </body>
</html>

画出来的效果就是这样的

image-20250609135626030.png

结尾

到这里环形文本的实现方式已经结束了,下一篇文章我打算用这些知识实现mdn文档官网首页的这个效果

image-20250609140005614

❌
❌