动态生成canvas文本模块
本帖最后由 马黑黑 于 2025-6-20 17:09 编辑 <br /><br /><style>.artBox { font-size: 18px; }
.artBox > p { margin: 10px 0; line-height: 30px; }
.artBox mark { padding: 4px 6px; background: lightblue; }
#prevBox { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: #eee; display: none; padding: 0; overflow: hidden; z-index: 1000; margin: 0; }
#prevBox::after { position: absolute; content: '关闭预览'; bottom: 10px; left: calc(50% - 40px); padding: 0 4px; width: 80px; height: 30px; line-height: 30px; text-align: center; border: 1px solid #efe; border-radius: 6px; background: #eee; font-size: 14px; box-shadow: 2px 2px 6px rgba(0,0,0,.25); cursor: pointer; }
iframe { position: relative; width: 100%; height: 100%; border: none; outline: none; box-sizing: border-box; margin: 0; }
</style>
<div id="prevBox"></div>
<div class="artBox">
<p>textcanvas.js是一个ES6 module模块,使用它可以方便地在Web页中插入绘制在canvas画布上的文本,支持文本填充、描边和渐变,默认支持文本阴影(可自行设置)。</p>
<p>使用方法:在 type="module" 的 script 标签里使用 <mark> import { textcanvas } from 'https://638183.freep.cn/638183/3dev/3/textcanvas.js' </mark> 导入模块,之后使用指令 <mark> const mycanv = textcanvas(str, config); </mark> 获取canvas画布元素 mycanv,最后将 mycanv 元素 appendChild 到指定父元素中即可。textcanvas() 函数需要两个参数,str 必须,为要输出的文本, config 可选,为相关配置。</p>
<p>以下是一个完整的应用示例,属于简单应用:</p>
<div class="hEdiv"><pre class="hEpre" id="pre1">
<script type="module">
import { textcanvas } from 'https://638183.freep.cn/638183/3dev/3/textcanvas.js';
var text = `〇一二三四五六七八九`; // 输出文本
// 简单配置
var config = {
font: 'bold 60px "黑体"', // 字体 : 粗体、60像素、黑体
fill: true, // 填充开关
fillColor: 'olive' // 填充颜色
};
var canv = textcanvas(text, config); // 绘制文本并将canvas画布返回给 canv 变量
document.body.appendChild(canv); // 将画布追加到页面中
</script>
</pre></div>
<blockquote><button id="btnPrev1">运行代码</button></blockquote>
<p>待输出文本支持多行,每一行字数要合适,textcanvas未做自动折行处理,其最大宽度限制为 1400px。若使用多行文本,请将文本分行,文本使用反引号 <mark>``</mark> 包裹。下面是输出多行文本的简单示例:</p>
<div class="hEdiv"><pre class="hEpre" id="pre2">
<script type="module">
import { textcanvas } from 'https://638183.freep.cn/638183/3dev/3/textcanvas.js';
// 多行文本
var text = `
ABCDEFG
abcdefg
一二三四五六
123456`;
// 配置
var config = {
font: 'bold 30px sans-serif', // 字体
fill: true, // 填充开关
fillColor: '#ff662c' // 填充颜色
};
var canv = textcanvas(text, config);
document.body.appendChild(canv);
</script>
</pre></div>
<blockquote><button id="btnPrev2">运行代码</button></blockquote>
<p>完整配置包含的内容相对较多,主要分五个层面:字体相关、填充相关、描边相关、渐变相关、阴影相关。下面是配置示例代码+说明:</p>
<div class="hEdiv"><pre class="hEpre">
const config = {
// 1. 字体相关
font: 'bold 80px sans-serif', // 字体
align: 'center', // 文本对齐,可选值 :left, center, right
// 2. 填充相关
fill: true, // 是否填充,true 或 false
fillColor: 'yellow', // 填充颜色
// 3. 描边相关
stroke : false, // 是否描边,true 或 false
strokeColor: 'gold', // 描边颜色
// 4. 渐变相关
//不用渐变可不设置,若设置则 fillColor 和 strokeColor 将被渐变取代
gradient: {
type: 'radial', // 渐变类型,可选值有 linear 或 radial
// 渐变坐标
// linear 使用 ,radial 使用
value: ,
// 渐变偏移和颜色
color:[
{ offset: 0, color: 'purple' },
{ offset: 0.5, color: 'yellow' },
{ offset: 1, color: 'green' }
]
},
// 5. 阴影相关
shadow: 'gray', // 文本阴影色
shadowX: 1, // 阴影X偏移量(支持负数值)
shadowY: 1, // 文本Y偏移量(支持负数值)
shadowBlur: 2 // 阴影模糊度
};
</pre></div>
<p>渐变的设置相对复杂,共三个内容:其一,渐变类型,字符型,二选一,linear 或 radial,名称放在小角引号内,拼写不能有错;其二,渐变坐标数据,数组型,数组元素为数值型,基于线性渐变 linear 共四个,<mark></mark>,基于径向渐变 radial 共六个,<mark></mark>,要齐全且不能有错。数组元素内各值与canvas画布宽高尺寸有关,是n个像素值但不能要 px 单位;其三,渐变偏移和色标,数组型,至少需要两组数组元素,数组内元素的内容是对象<mark>{...}</mark>,对象内容是canvas设置渐变偏移和色标的基本表达,例如上面代码中,offset: 0.5 表示颜色渐变的边界在中心处,color: 'yellow' 表示该处的颜色是黄色。offset 从 0~1 设置偏移量,含 0 和 1,不能超出范围。设置合适的渐变,可以创建出漂亮的文本,所以,如果对canvas渐变不太熟悉,可访问 <a href="https://www.cainiaojc.com/html5/html5-canvas-gradients.html" target="_blank">HTML5 Canvas 渐变</a> 补补课。</p>
<p>下面给出一个渐变的应用示例:</p>
<div class="hEdiv"><pre class="hEpre" id="pre3">
<script type="module">
import { textcanvas } from 'https://638183.freep.cn/638183/3dev/3/textcanvas.js';
const str = `你站在桥上看风景\n看风景的人在楼上看你\n明月装饰了你的窗子\n你装饰了别人的梦`;
const setting = {
font: 'bold 120px "KaiTi", sans-serif',
align: 'right', // 右对齐
gradient: {
type: 'linear', // 线性渐变
value: , // 渐变坐标
// 渐变色标
color:[
{ offset: 0, color: 'purple' },
{ offset: 0.5, color: 'yellow' },
{ offset: 1, color: 'green' }
]
},
fill: true, // 开启填充功能(将用渐变填充)
shadow: 'gray', // 文本阴影色
shadowX: 5, // 阴影X偏移量
shadowY: 5, // 文本Y偏移量
};
const mycanv = textcanvas(str, setting);
// console.log(mycanv); // 查看canvas画布(含宽高尺寸)
document.body.appendChild(mycanv);
</script>
</pre></div>
<blockquote><button id="btnPrev3">运行代码</button></blockquote>
<p>最后再举一个应用示例,canvas文本添加到一个div中,填充+描边,没有渐变:</p>
<div class="hEdiv"><pre class="hEpre" id="pre4">
<style>
#papa { margin: 30px auto;width: 1024px; height: 640px; background: #eee; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; z-index: 1; position: relative; }
</style>
<div id="papa"></div>
<script type="module">
import { textcanvas } from 'https://638183.freep.cn/638183/3dev/3/textcanvas.js';
const mystr = `大漠沙如雪,\n燕山月似钩。\n何当金络脑,\n快走踏清秋。`;
const myconfig = {
font: 'bold 100px "Microsoft Yahei", sans-serif',
fill: true,
fillColor: 'white',
stroke: true,
strokeColor: 'yellow',
shadowX: 4,
shadowY: 3,
shadowBlur: 2
};
const mycanv = textcanvas(mystr, myconfig);
papa.appendChild(mycanv);
</script>
</pre></div>
<blockquote><button id="btnPrev4">运行代码</button></blockquote>
<p>顺便提一下:canvas生成的文本,可以存为背景透明的 .png 图片,方法是右击、另存为。</p>
</div>
<script type="module">
import hlight from 'https://638183.freep.cn/638183/web/helight/helight1.js';
const pres = document.querySelectorAll('.hEpre');
const divs = document.querySelectorAll('.hEdiv');
divs.forEach( (div, key) => hlight.hl(div, pres));
const preView = (htmlCode, targetBox) => {
if (targetBox.innerHTML) return;
const iframe = document.createElement('iframe');
htmlCode = htmlCode + '<style>body {margin: 0; }</style>';
iframe.srcdoc = htmlCode;
targetBox.appendChild(iframe);
targetBox.style.display = 'block';
targetBox.onclick = () => {
targetBox.innerHTML = '';
targetBox.style.display = 'none';
}
};
const btns = ;
const idPrevs = ;
btns.forEach( (btn, key) => {
btn.onclick = () => preView(idPrevs.textContent, prevBox);
});
</script> 这些文字弄得都很好看啊,canvas文本真漂亮。{:4_187:} value: ,这个渐变坐标的设置还需要计算一下文字的宽高才行啊,知道文字的占位,才能行的吧,这个是对角线的设置。 去试了一下,其实渐变好像也不需要知道文字大小,它只是规定了颜色从哪开始渲染的。 红影 发表于 2025-6-20 19:58
去试了一下,其实渐变好像也不需要知道文字大小,它只是规定了颜色从哪开始渲染的。
在 canvas,渐变的坐标设置针对画布尺寸 红影 发表于 2025-6-20 19:41
这些文字弄得都很好看啊,canvas文本真漂亮。
canvas 可以绘制文本,fillText 是文本填充,strokeText 是文本描边 红影 发表于 2025-6-20 19:45
value: ,这个渐变坐标的设置还需要计算一下文字的宽高才行啊,知道文字的占位,才能行的吧 ...
示例代码中有在控制台打印 canvas 画布的语句,通过运行它,按 F12,切换到控制台,就知道 canvas 的宽高 马黑黑 发表于 2025-6-20 20:09
在 canvas,渐变的坐标设置针对画布尺寸
嗯嗯,我以为要知道文字尺寸呢{:4_173:} 马黑黑 发表于 2025-6-20 20:10
canvas 可以绘制文本,fillText 是文本填充,strokeText 是文本描边
然后渐变的时候,会让这两个失效。 马黑黑 发表于 2025-6-20 20:11
示例代码中有在控制台打印 canvas 画布的语句,通过运行它,按 F12,切换到控制台,就知道 canvas 的宽高
原来这两个值是这样弄出来的啊,完全没想到{:4_187:} https://pic1.imgdb.cn/item/685560b658cb8da5c85ee214.png 上图我随手取的渐变value: , 也弄出来了{:4_173:} 讲的真好,感谢马老师经典讲解,老师您辛苦了{:4_191:} 杨帆 发表于 2025-6-20 21:29
讲的真好,感谢马老师经典讲解,老师您辛苦了
感兴趣的话可以看看 textcanvas.js 源码,里面的核心函数也就三个(不包含导出函数)
{:4_190:} 红影 发表于 2025-6-20 21:24
上图我随手取的渐变value: , 也弄出来了
渐变作用于你所设置的坐标数据规范的范围 红影 发表于 2025-6-20 21:21
原来这两个值是这样弄出来的啊,完全没想到
为啥老推荐使用F12,这就是 红影 发表于 2025-6-20 21:20
然后渐变的时候,会让这两个失效。
fillStyle 和 strokeStyle 可以是颜色,也可以是渐变,模块设定,如果使用渐变,那么,填充和描边方式就是渐变 红影 发表于 2025-6-20 21:24
上图我随手取的渐变value: , 也弄出来了
哇,学的又快又好,赞一个{:4_187:} 红影 发表于 2025-6-20 21:19
嗯嗯,我以为要知道文字尺寸呢
这个模块根据文本决定画布的宽高,所以,这个说法也对 马黑黑 发表于 2025-6-20 21:39
感兴趣的话可以看看 textcanvas.js 源码,里面的核心函数也就三个(不包含导出函数)
知道了,谢谢老师,需要学的东西太多,慢慢跟老师学吧{:4_190:}