✏️Canvas实现环形文字

什么是环形文字?

搜索相关的图片可以看到

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

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

这边采用的是cavans来实现

最终效果

完整代码

html 复制代码
<!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. 对每一个字符,进行旋转
js 复制代码
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就是文字坐标

公式如下:

js 复制代码
x = 圆心的x坐标+Math.cos(弧度)*半径
y = 圆心的y坐标+Math.cos(弧度)*半径

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

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

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

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

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

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

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

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

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

js 复制代码
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()

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

完整代码如下:

html 复制代码
<!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>

画出来的效果就是这样的

结尾

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

相关推荐
开发加微信:hedian11634 分钟前
短剧小程序开发全攻略:从技术选型到核心实现(前端+后端+运营干货)
前端·微信·小程序
徐小夕@趣谈前端2 小时前
如何实现多人协同文档编辑器
javascript·vue.js·设计模式·前端框架·开源·编辑器·github
YCOSA20253 小时前
ISO 雨晨 26200.6588 Windows 11 企业版 LTSC 25H2 自用 edge 140.0.3485.81
前端·windows·edge
小白呀白3 小时前
【uni-app】树形结构数据选择框
前端·javascript·uni-app
吃饺子不吃馅3 小时前
深感一事无成,还是踏踏实实做点东西吧
前端·svg·图形学
90后的晨仔4 小时前
Mac 上配置多个 Gitee 账号的完整教程
前端·后端
少年阿闯~~4 小时前
CSS——实现盒子在页面居中
前端·css·html
开发者小天4 小时前
uniapp中封装底部跳转方法
前端·javascript·uni-app
阿波罗尼亚4 小时前
复杂查询:直接查询/子查询/视图/CTE
java·前端·数据库
正义的大古5 小时前
OpenLayers地图交互 -- 章节九:拖拽框交互详解
前端·vue.js·openlayers