马黑黑 发表于 2025-6-20 17:03

动态生成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">
&lt;script type="module"&gt;
        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); // 将画布追加到页面中
&lt;/script&gt;
        </pre></div>
        <blockquote><button id="btnPrev1">运行代码</button></blockquote>
       
        <p>待输出文本支持多行,每一行字数要合适,textcanvas未做自动折行处理,其最大宽度限制为 1400px。若使用多行文本,请将文本分行,文本使用反引号 <mark>``</mark> 包裹。下面是输出多行文本的简单示例:</p>
        <div class="hEdiv"><pre class="hEpre" id="pre2">
&lt;script type="module"&gt;
        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);
&lt;/script&gt;
        </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">
&lt;script type="module"&gt;
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);
&lt;/script&gt;
        </pre></div>
        <blockquote><button id="btnPrev3">运行代码</button></blockquote>
        <p>最后再举一个应用示例,canvas文本添加到一个div中,填充+描边,没有渐变:</p>
                <div class="hEdiv"><pre class="hEpre" id="pre4">
&lt;style&gt;
        #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; }
&lt;/style&gt;

&lt;div id="papa"&gt;&lt;/div&gt;

&lt;script type="module"&gt;
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);
&lt;/script&gt;
        </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>

红影 发表于 2025-6-20 19:41

这些文字弄得都很好看啊,canvas文本真漂亮。{:4_187:}

红影 发表于 2025-6-20 19:45

value: ,这个渐变坐标的设置还需要计算一下文字的宽高才行啊,知道文字的占位,才能行的吧,这个是对角线的设置。

红影 发表于 2025-6-20 19:58

去试了一下,其实渐变好像也不需要知道文字大小,它只是规定了颜色从哪开始渲染的。

马黑黑 发表于 2025-6-20 20:09

红影 发表于 2025-6-20 19:58
去试了一下,其实渐变好像也不需要知道文字大小,它只是规定了颜色从哪开始渲染的。

在 canvas,渐变的坐标设置针对画布尺寸

马黑黑 发表于 2025-6-20 20:10

红影 发表于 2025-6-20 19:41
这些文字弄得都很好看啊,canvas文本真漂亮。

canvas 可以绘制文本,fillText 是文本填充,strokeText 是文本描边

马黑黑 发表于 2025-6-20 20:11

红影 发表于 2025-6-20 19:45
value: ,这个渐变坐标的设置还需要计算一下文字的宽高才行啊,知道文字的占位,才能行的吧 ...

示例代码中有在控制台打印 canvas 画布的语句,通过运行它,按 F12,切换到控制台,就知道 canvas 的宽高

红影 发表于 2025-6-20 21:19

马黑黑 发表于 2025-6-20 20:09
在 canvas,渐变的坐标设置针对画布尺寸

嗯嗯,我以为要知道文字尺寸呢{:4_173:}

红影 发表于 2025-6-20 21:20

马黑黑 发表于 2025-6-20 20:10
canvas 可以绘制文本,fillText 是文本填充,strokeText 是文本描边

然后渐变的时候,会让这两个失效。

红影 发表于 2025-6-20 21:21

马黑黑 发表于 2025-6-20 20:11
示例代码中有在控制台打印 canvas 画布的语句,通过运行它,按 F12,切换到控制台,就知道 canvas 的宽高

原来这两个值是这样弄出来的啊,完全没想到{:4_187:}

红影 发表于 2025-6-20 21:23

https://pic1.imgdb.cn/item/685560b658cb8da5c85ee214.png

红影 发表于 2025-6-20 21:24

上图我随手取的渐变value: , 也弄出来了{:4_173:}

杨帆 发表于 2025-6-20 21:29

讲的真好,感谢马老师经典讲解,老师您辛苦了{:4_191:}

马黑黑 发表于 2025-6-20 21:39

杨帆 发表于 2025-6-20 21:29
讲的真好,感谢马老师经典讲解,老师您辛苦了

感兴趣的话可以看看 textcanvas.js 源码,里面的核心函数也就三个(不包含导出函数)
{:4_190:}

马黑黑 发表于 2025-6-20 21:39

红影 发表于 2025-6-20 21:24
上图我随手取的渐变value: , 也弄出来了

渐变作用于你所设置的坐标数据规范的范围

马黑黑 发表于 2025-6-20 21:42

红影 发表于 2025-6-20 21:21
原来这两个值是这样弄出来的啊,完全没想到

为啥老推荐使用F12,这就是

马黑黑 发表于 2025-6-20 21:43

红影 发表于 2025-6-20 21:20
然后渐变的时候,会让这两个失效。
fillStyle 和 strokeStyle 可以是颜色,也可以是渐变,模块设定,如果使用渐变,那么,填充和描边方式就是渐变

杨帆 发表于 2025-6-20 21:43

红影 发表于 2025-6-20 21:24
上图我随手取的渐变value: , 也弄出来了

哇,学的又快又好,赞一个{:4_187:}

马黑黑 发表于 2025-6-20 21:44

红影 发表于 2025-6-20 21:19
嗯嗯,我以为要知道文字尺寸呢

这个模块根据文本决定画布的宽高,所以,这个说法也对

杨帆 发表于 2025-6-20 21:46

马黑黑 发表于 2025-6-20 21:39
感兴趣的话可以看看 textcanvas.js 源码,里面的核心函数也就三个(不包含导出函数)

知道了,谢谢老师,需要学的东西太多,慢慢跟老师学吧{:4_190:}
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 动态生成canvas文本模块