js+canvas實(shí)現(xiàn)繪制正方形并插入文字效果(居中顯示)
一、實(shí)現(xiàn)效果

二、實(shí)現(xiàn)思路
1.先根據(jù)傳入的文本內(nèi)容,計(jì)算出文本的寬度。
2.文本寬度+左右間距,得到正方形的邊長(zhǎng)、畫(huà)布寬度。
3.在(0,0)坐標(biāo)處,繪制正方形。
4.計(jì)算文本居中的起始坐標(biāo),填充文本。
三、代碼實(shí)現(xiàn)
<template>
<div>
<canvas id="canvas" style="margin:10px;></canvas>
</div>
</template>
<script>
export default {
mounted() {
this.drawSquare(20, 'Microsoft YaHei', '我是居中的文字..')
},
methods: {
/**
* 繪制正方形并添加文本
* @param {Number} fonSize // 字號(hào)
* @param {String} fontFace // 字體
* @param {String} text // 文本
*/
drawSquare(fonSize, fontFace, text) {
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
// 1.計(jì)算文本寬度
let txtWidth = this.getFontWidth(fonSize, fontFace, ctx, text)
// 2.設(shè)置畫(huà)布寬度
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 // 文本內(nèi)容
*/
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 // 字號(hào)
* @param {String} fontFace // 字體
* @param {Number} txtWidth // 文本寬度
* @param {Object} ctx // CanvasRenderingContext2D
* @param {String} text // 文本
* @param {Number} width // 畫(huà)布的寬度
* @param {Number} height // 畫(huà)布的高度
*/
fillTextCenter(
fonSize,
fontFace,
txtWidth,
ctx,
text,
width
) {
// 1.設(shè)置文本對(duì)齊方式
ctx.textBaseline = 'middle'
ctx.textAlign = 'center'
// 2.設(shè)置起始坐標(biāo)
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個(gè)字符寬度
xL += s
ctx.font = fonSize + 'px ' + fontFace
ctx.fillText(text[i], xL, yL)
}
}
}
}
</script>
四、代碼解析
- canvas語(yǔ)法全解析:HTML Canvas 參考手冊(cè)
getContext():Document.getElementById() 方法獲取 HTML 元素的引用。接著,HTMLCanvasElement.getContext() 方法獲取這個(gè)元素的 context——圖像稍后將在此被渲染。measureText():返回包含指定文本寬度的對(duì)象textBaseline:設(shè)置或返回在繪制文本時(shí)使用的當(dāng)前文本基線textAlign: 設(shè)置或返回文本內(nèi)容的當(dāng)前對(duì)齊方式font:設(shè)置或返回文本內(nèi)容的當(dāng)前字體屬性strokeRect():繪制矩形(無(wú)填充)
五、問(wèn)題
- 問(wèn)題:文本顯示不居中;文本顯示疊在一起;具體可見(jiàn)下圖。
- 原因:好像是通過(guò)
measureText測(cè)量出的文本寬度和實(shí)際渲染有差異導(dǎo)致的,但是沒(méi)有找到解決辦法。如果有解決方法可以在評(píng)論區(qū)留言,謝謝。 - 效果圖:

六、改進(jìn)后的代碼
1.效果圖

2.思路
1)去掉 textAlign='center'
2)使用 measureText 方法返回的 textMetrics 對(duì)象的 actualBoundingBoxLeft + actualBoundingBoxRight 屬性來(lái)計(jì)算文字的寬度。這兩個(gè)屬性表示文字的最左邊和最右邊界,可以更準(zhǔn)備地計(jì)算文字的寬度。
3)填充文字時(shí),字符坐標(biāo)應(yīng)該是加上前一字符寬度,代碼中加的是當(dāng)前字符寬度。改進(jìn)后代碼已修改。
3.代碼實(shí)現(xiàn)
<template>
<div>
<canvas id="canvas" style="margin:10px;"></canvas>
</div>
</template>
<script>
export default {
mounted() {
this.drawSquare(20, 'Microsoft YaHei', '我是居中的文字..')
},
methods: {
/**
* 繪制正方形并添加文本
* @param {Number} fonSize // 字號(hào)
* @param {String} fontFace // 字體
* @param {String} text // 文本
*/
drawSquare(fonSize, fontFace, text) {
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
// 1.計(jì)算文本寬度
let txtWidth = this.getFontWidth(fonSize, fontFace, ctx, text)
// 2.設(shè)置畫(huà)布寬度
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 // 文本內(nèi)容
*/
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 // 字號(hào)
* @param {String} fontFace // 字體
* @param {Number} txtWidth // 文本寬度
* @param {Object} ctx // CanvasRenderingContext2D
* @param {String} text // 文本
* @param {Number} width // 畫(huà)布的寬度
* @param {Number} height // 畫(huà)布的高度
*/
fillTextCenter(
fonSize,
fontFace,
txtWidth,
ctx,
text,
width
) {
// 1.設(shè)置文本對(duì)齊方式
ctx.textBaseline = 'middle'
// 2.設(shè)置起始坐標(biāo)
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
// 前一個(gè)字符寬度
}
}
}
}
</script>總結(jié)
到此這篇關(guān)于js+canvas實(shí)現(xiàn)繪制正方形并插入文字效果的文章就介紹到這了,更多相關(guān)js canvas繪制正方形插入文字內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ajax請(qǐng)求前端跨域問(wèn)題原因及解決方案
這篇文章主要為大家介紹了ajax請(qǐng)求前端跨域問(wèn)題原因及解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10
Bootstrap基本插件學(xué)習(xí)筆記之輪播幻燈片(23)
這篇文章主要為大家詳細(xì)介紹了Bootstrap基本插件學(xué)習(xí)筆記之輪播幻燈片的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
JavaScript前端靜態(tài)資源加載失敗的多級(jí)解決方案
這篇文章主要為大家詳細(xì)介紹了JavaScript前端靜態(tài)資源加載失敗的多級(jí)解決方案,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2025-07-07
前端常見(jiàn)問(wèn)答之flat()和flatMap()有哪些不同
這篇文章主要介紹了JavaScript中的flat()和flatMap()方法,解釋了它們的功能、使用方法和應(yīng)用場(chǎng)景,flat()用于將嵌套數(shù)組壓平,而flatMap()則是在壓平的同時(shí)對(duì)每個(gè)元素進(jìn)行轉(zhuǎn)換,需要的朋友可以參考下2024-11-11
網(wǎng)頁(yè)運(yùn)行時(shí)提示對(duì)象不支持abigimage屬性或方法
網(wǎng)頁(yè)中用了一個(gè)js插件,js文件引用的沒(méi)有錯(cuò)但是運(yùn)行時(shí)ie的調(diào)試工具報(bào)了一個(gè)錯(cuò),提示對(duì)象不支持abigimage屬性或方法2014-08-08
浮動(dòng)的div自適應(yīng)居中顯示的js代碼
這篇文章主要介紹了浮動(dòng)的div自適應(yīng)居中顯示的js代碼,有需要的朋友可以參考一下2013-12-12
利用JavaScript構(gòu)建樹(shù)形圖的方法詳解
?樹(shù)形圖可視化廣泛用于分層數(shù)據(jù)分析。如果你沒(méi)有經(jīng)驗(yàn)還想創(chuàng)建一個(gè),那將會(huì)有些復(fù)雜。下面是一個(gè)詳細(xì)教程,教你如何使用JavaScript創(chuàng)建交互式樹(shù)形圖2022-06-06
js通過(guò)location.search來(lái)獲取頁(yè)面?zhèn)鱽?lái)的參數(shù)
js獲取通過(guò)window.location.search來(lái)獲取頁(yè)面?zhèn)鱽?lái)的參數(shù),經(jīng)測(cè)試可用,大家可以學(xué)習(xí)下2014-09-09

