js+canvas实现绘制正方形并插入文字,实现文字居中显示。

news/2024/7/9 23:49:29 标签: javascript, 开发语言, canva可画, vue

目录

  • 一、实现效果
  • 二、实现思路
  • 三、代码实现
  • 四、代码解析
  • 五、问题
  • 六、改进后的代码
    • 1.效果图
    • 2.思路
    • 3.代码实现

一、实现效果

在这里插入图片描述

二、实现思路

1.先根据传入的文本内容,计算出文本的宽度。
2.文本宽度+左右间距,得到正方形的边长、画布宽度。
3.在(0,0)坐标处,绘制正方形。
4.计算文本居中的起始坐标,填充文本。

三、代码实现

javascript"><template>
  <div>
    <canvas id="canvas" style="margin:10px;></canvas>
  </div>
</template>

<script>
export default {
  mounted() {
    this.drawSquare(20, 'Microsoft YaHei', '我是居中的文字..')
  },
  methods: {
    /**
     * 绘制正方形并添加文本
     * @param {Number} fonSize // 字号
     * @param {String} fontFace // 字体
     * @param {String} text // 文本
     */
    drawSquare(fonSize, fontFace, text) {
      var canvas = document.getElementById('canvas')
      var ctx = canvas.getContext('2d')
      // 1.计算文本宽度
      let txtWidth = this.getFontWidth(fonSize, fontFace, ctx, text)
      // 2.设置画布宽度
      let ctxWidth = txtWidth + 20
      canvas.width = ctxWidth
      canvas.height = ctxWidth
      console.log(txtWidth,'txtWidth');
      // 3.绘制正方形
      ctx.strokeRect(0, 0, txtWidth + 10, txtWidth + 10)
      // 4.填充文字
      this.fillTextCenter(
        fonSize,
        fontFace,
        txtWidth,
        ctx,
        text,
        txtWidth + 10
      )
    },
    /**
     * 获取文本宽度
     * @param {Object} ctx // CanvasRenderingContext2D
     * @param {String} text // 文本内容
     */
    getFontWidth(fonSize, fontFace, ctx, text) {
      ctx.font = fonSize + 'px ' + fontFace
      let txtWidth = 0
      for (let i = 0; i < text.length; i++) {
        txtWidth += ctx.measureText(text[i]).width
      }
      return txtWidth
    },

    /**
     * 在图形中心位置添加文本
     * @param {Number} fonSize // 字号
     * @param {String} fontFace // 字体
     * @param {Number} txtWidth // 文本宽度
     * @param {Object} ctx // CanvasRenderingContext2D
     * @param {String} text // 文本
     * @param {Number} width // 画布的宽度
     * @param {Number} height // 画布的高度
     */
    fillTextCenter(
      fonSize,
      fontFace,
      txtWidth,
      ctx,
      text,
      width
    ) {
      // 1.设置文本对齐方式
      ctx.textBaseline = 'middle'
      ctx.textAlign = 'center'
      // 2.设置起始坐标
      let s = 0
      let xL = (width - txtWidth-2) / 2 + s
      let yL = width / 2
      // 3.绘制文本
      for (let i = 0; i < text.length; i++) {
        s = ctx.measureText(text[i]).width  // 第i个字符宽度
        xL += s
        ctx.font = fonSize + 'px ' + fontFace 
        ctx.fillText(text[i], xL, yL)
      }
    }
  }
}
</script>

四、代码解析

  1. canvas语法全解析:HTML Canvas 参考手册
  2. getContext():Document.getElementById() 方法获取 HTML 元素的引用。接着,HTMLCanvasElement.getContext() 方法获取这个元素的 context——图像稍后将在此被渲染。
  3. measureText():返回包含指定文本宽度的对象
  4. textBaseline:设置或返回在绘制文本时使用的当前文本基线
  5. textAlign: 设置或返回文本内容的当前对齐方式
  6. font:设置或返回文本内容的当前字体属性
  7. strokeRect():绘制矩形(无填充)

五、问题

  • 问题:文本显示不居中;文本显示叠在一起;具体可见下图。
  • 原因:好像是通过 measureText 测量出的文本宽度和实际渲染有差异导致的,但是没有找到解决办法。如果有解决方法可以在评论区留言,谢谢。
  • 效果图:
    在这里插入图片描述

六、改进后的代码

1.效果图

在这里插入图片描述

2.思路

1)去掉 textAlign='center'
2)使用 measureText 方法返回的 textMetrics 对象的 actualBoundingBoxLeft + actualBoundingBoxRight 属性来计算文字的宽度。这两个属性表示文字的最左边和最右边界,可以更准备地计算文字的宽度。
3)填充文字时,字符坐标应该是加上前一字符宽度,代码中加的是当前字符宽度。改进后代码已修改。

3.代码实现

javascript"><template>
  <div>
    <canvas id="canvas" style="margin:10px;"></canvas>
  </div>
</template>

<script>
export default {
  mounted() {
    this.drawSquare(20, 'Microsoft YaHei', '我是居中的文字..')
  },
  methods: {
    /**
     * 绘制正方形并添加文本
     * @param {Number} fonSize // 字号
     * @param {String} fontFace // 字体
     * @param {String} text // 文本
     */
    drawSquare(fonSize, fontFace, text) {
      var canvas = document.getElementById('canvas')
      var ctx = canvas.getContext('2d')
      // 1.计算文本宽度
      let txtWidth = this.getFontWidth(fonSize, fontFace, ctx, text)
      // 2.设置画布宽度
      let ctxWidth = txtWidth + 20
      canvas.width = ctxWidth
      canvas.height = ctxWidth
      // 3.绘制正方形
      ctx.strokeRect(0, 0, txtWidth + 10, txtWidth + 10)
      // 4.填充文字
      this.fillTextCenter(
        fonSize,
        fontFace,
        txtWidth,
        ctx,
        text,
        txtWidth + 10
      )
    },
    /**
     * 获取文本宽度
     * @param {Object} ctx // CanvasRenderingContext2D
     * @param {String} text // 文本内容
     */
    getFontWidth(fonSize, fontFace, ctx, text) {
      ctx.font = fonSize + 'px ' + fontFace
      let txtWidth = 0
      for (let i = 0; i < text.length; i++) {
        txtWidth += (ctx.measureText(text[i]).actualBoundingBoxLeft + ctx.measureText(text[i]).actualBoundingBoxRight)
      }
      return txtWidth
    },

    /**
     * 在图形中心位置添加文本
     * @param {Number} fonSize // 字号
     * @param {String} fontFace // 字体
     * @param {Number} txtWidth // 文本宽度
     * @param {Object} ctx // CanvasRenderingContext2D
     * @param {String} text // 文本
     * @param {Number} width // 画布的宽度
     * @param {Number} height // 画布的高度
     */
    fillTextCenter(
      fonSize,
      fontFace,
      txtWidth,
      ctx,
      text,
      width
    ) {
      // 1.设置文本对齐方式
      ctx.textBaseline = 'middle'
      // 2.设置起始坐标
      let s = 0
      let xL = (width - txtWidth - 2) / 2 + s
      let yL = width / 2
      // 3.绘制文本
      for (let i = 0; i < text.length; i++) {
        xL += s
        ctx.font = fonSize + 'px ' + fontFace
        ctx.font = fonSize + 'px ' + fontFace
        ctx.fillText(text[i], xL, yL)
        s = ctx.measureText(text[i]).actualBoundingBoxLeft + ctx.measureText(text[i]).actualBoundingBoxRight
        // 前一个字符宽度
      }
    }
  }
}
</script>


http://www.niftyadmin.cn/n/4994440.html

相关文章

PY32F003F18滴答定时器

PY32F003F18滴答定时器使用HAL库函数 //函数功能:配置"SysTick计数器"每1ms中断一次,优先级为最低 HAL_StatusTypeDef HAL_Init(void) {HAL_StatusTypeDef status HAL_OK;/* Configure Flash prefetch, Instruction cache *//* Default configuration…

Python学习 -- 异常堆栈追踪技术

在编写Python代码时&#xff0c;出现异常是不可避免的。异常堆栈追踪是一种强大的工具&#xff0c;可以帮助我们定位错误发生的位置以及调用栈信息。Python的traceback模块提供了多种方法来获取和展示异常的堆栈信息。本文将详细介绍traceback模块中的print_exc()方法&#xff…

一个月能做什么?成长感悟分享

一个月做了什么&#xff1f; 八月做了些什么&#xff1f; 单词打卡 第一件事情就是单词打卡 英语很差的我&#xff0c;一样继续打卡&#xff0c;今天是第736天 当你还在纠结扇贝和不背、可可英语哪一个好的时候&#xff0c;别人已经同时使用了 当你还在咨询学编程、敲代码需…

无涯教程-JavaScript - QUARTILE函数

QUARTILE函数取代了Excel 2010中的QUARTILE.INC函数。 描述 该函数返回数据集的四分位数。四分位数通常用于销售和调查数据中,以将人群分为几类。 语法 QUARTILE (array,quart)争论 Argument描述Required/OptionalArrayThe array or cell range of numeric values for whi…

基于深度学习的三维重建从入门实战教程 原理讲解 源码解析 实操教程课件下载

传统的重建方法是使用光度一致性等来计算稠密的三维信息。虽然这些方法在理想的Lambertian场景下,精度已经很高。 但传统的局限性,例如弱纹理,高反光和重复纹理等,使得重建困难或重建的结果不完整。 基于学习的方法可以引入比如镜面先验和反射先验等全局语义信息,使匹配…

MySQL高阶语句之常用查询

目录 常用查询 按关键字排序 区间判断及查询不重复记录 对结果进行分组 限制结果条目 设置别名 通配符 子查询 常用查询 &#xff08;增、删、改、查&#xff09; 对 MySQL 数据库的查询&#xff0c;除了基本的查询外&#xff0c;有时候需要对查询的结果集进行处理。 …

AWK语言第二版 1.4 选择

1.4 选择 Awk的样式很适合将输入行中感兴趣的行选取出来&#xff0c;用于后续处理。由于不含动作的样式会将所有匹配该样式的行都打印出来&#xff0c;因此很多Awk程序仅仅就包含一个样式。本节给出一些有用的样式。 通过比较来选择 这个程序使用了一个比较样式&#xff0c;…

MySQL 使用规范 —— 如何建好字段和索引

一、案例背景 二、库表规范 1. 建表相关规范 2. 字段相关规范 3. 索引相关规范 4. 使用相关规范 三、建表语句 三、语句操作 1. 插入操作 2. 查询操作 四、其他配置 1. 监控活动和性能&#xff1a; 2. 连接数查询和配置 本文的宗旨在于通过简单干净实践的方式教会读…