学习整理Fabric.js 实现文本文字加粗、下划线、斜体、竖排、字体对齐代码

本文介绍如何使用Fabric.js实现文本的多种样式编辑功能,包括加粗、下划线、斜体等,并提供了完整的HTML和JavaScript代码示例。

原图

在这里插入图片描述

效果图

在这里插入图片描述

代码

index.html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">

    <title>Fabric.js 加粗、下划线、斜体、竖排、字体对齐</title>

    <script src="../fabric5.2.1.js"></script>

    <style>
        div#container {
            padding: 30px;
            font-family: 'verdana', lucida;
        }

        input {
            background-color: #ccc;
            padding: 0;
            width: 300px;
            color: #777;
        }

        a {
            color: #777;
            display: block;
            background-color: #ccc;
            width: 300px;
            padding: 0;
            margin-top: 2px;
            text-decoration: none;
        }
    </style>

</head>
<body>

<div id="container">

    <p>
        <input type="color" id="color" name="color" onchange="changeColor(value)"/>
    </p>
    <p>
        <button onclick="bold()">加粗</button>
        <button onclick="overline()">上划线</button>
        <button onclick="linethrough()">中划线</button>
        <button onclick="underline()">下划线</button>
        <button onclick="italic()">斜体</button>
        <button onclick="textalign('left')">字体左对齐</button>
        <button onclick="textalign('right')">字体右对齐</button>
        <button onclick="textalign('center')">字体居中对齐</button>
    </p>

    <canvas id="imageCanvas" width="300" height="300"></canvas>
    <a id="lnkDownload" href="#">点我保存图片</a>
</div>

<script src="script.js"></script>

</body>
</html>

script.js 代码

 var canvas = new fabric.Canvas('imageCanvas', {
    backgroundColor: 'rgb(240,240,240)',
    includeDefaultValues: false,// 指示toObject/toDatalessObject是否应该包含默认值,如果设置为false,则优先于对象值
    perPixelTargetFind: true, //这一句说明选中的时候以图形的实际大小来选择而不是以边框来选择
    hasBorders: false,
});

canvas.setWidth(500);
canvas.setHeight(800);

// 使用 IText,可编辑文本
var text_1 = new fabric.IText(
    '《天净沙·秋思》\n枯藤老树昏鸦,\n小桥流水人家,\n古道西风瘦马。\n夕阳西下,\n断肠人在天涯。',
    {
        width: 300,
        fontSize: 14,
        fontFamily: 'Comic Sans',
        left: 50,
        top: 100,
        fill: 'blue',
        splitByGrapheme: true, // 自动换行
    }
);
canvas.add(text_1);


// 使用 IText,可编辑文本
var text_2 = new fabric.Textbox(
    '《奇葩天地网》www.qipa250.com',
    {
        width: 300, // 建议设置 textbox 的宽度
        fontSize: 14,
        fontFamily: 'Comic Sans',
        left: 50,
        top: 400,
        fill: 'red',
    }
);
//禁止用户调整文本框高度
/*
setControlVisible 第一个参数是操作点(控件)的键,分别有 tl, tr, br, bl, ml, mt, mr, mb, mtr
mt 表示中间顶部的操作点,mb 表示中间底部的操作点。
第二个参数设置控件是否可见。true 是默认值,表示可见;设置成 false 代表指定控件不可见。
*/
//禁止下拉,防止字体变形
text_2.setControlVisible('mt', false);
text_2.setControlVisible('mb', false);
// splitByGrapheme 为 true 时,Textbox 里的文本就会实时根据宽度进行换行。
text_2.splitByGrapheme = true;
canvas.add(text_2);


function changeColor(value) {

    console.log('changeColor--value=', value);

    let activeTxt = canvas.getActiveObject();

    if (!activeTxt) return;

    if (activeTxt.isEditing) {
        console.log('选中,修改单个文字的颜色');
        // 编辑状态
        activeTxt.setSelectionStyles({'fill': value});
    } else {
        console.log('选中整体,修改所有文字的颜色');
        activeTxt.fill = value;
        let s = activeTxt.styles;
        for (let i in s) {
            for (let j in s[i]) {
                s[i][j].fill = value;
            }
        }
    }
    canvas.renderAll();
}


// 加粗
function bold() {

    let activeTxt = canvas.getActiveObject();

    if (!activeTxt) return;

    if (activeTxt.isEditing) {
        // 编辑状态
        const state = activeTxt.getSelectionStyles().find(item => item.fontWeight !== 'bold');

        if (!state || (JSON.stringify(state) === '{}' && activeTxt['fontWeight'] === 'bold')) {
            activeTxt.setSelectionStyles({'fontWeight': 'normal'});
        } else {
            activeTxt.setSelectionStyles({'fontWeight': 'bold'});
        }
    } else {
        // 选择状态
        if (activeTxt['fontWeight'] === 'bold') {
            activeTxt.fontWeight = 'normal';
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].fontWeight = 'normal';
                }
            }
        } else {
            activeTxt.fontWeight = 'bold';
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].fontWeight = 'bold';
                }
            }
        }
    }

    canvas.renderAll();
}


//上划线
function overline() {

    let activeTxt = canvas.getActiveObject(); // 获取当前选中的文字


    // 如果当前没选中文字,那什么都不操作

    if (!activeTxt) return;


    // 判断当前是否进入编辑状态

    if (activeTxt.isEditing) {

        // 编辑状态
        const state = activeTxt.getSelectionStyles().find(item => item.overline !== true);

        // 如果当前
        if (!state || (JSON.stringify(state) === '{}' && activeTxt['overline'] === true)) {
            // 如果当前已经设置了上划线,那就把全局上划线取消
            activeTxt.setSelectionStyles({'overline': false});
        } else {
            // 如果当前没设置上划线,那就添加上上划线
            activeTxt.setSelectionStyles({'overline': true});
        }
    } else {
        // 选择状态
        if (activeTxt['overline'] === true) {
            activeTxt.overline = false;
            activeTxt.dirty = true;
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].overline = false;
                }
            }
        } else {
            activeTxt.overline = true;
            activeTxt.dirty = true;
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].overline = true;
                }
            }
        }
    }
    canvas.renderAll();
}


//中划线
function linethrough() {
    //获取当前选中的文字
    let activeTxt = canvas.getActiveObject();
    // 如果当前没选中文字,那什么都不操作
    if (!activeTxt) return;

    // 判断当前是否进入编辑状态
    if (activeTxt.isEditing) {
        // 编辑状态
        const state = activeTxt.getSelectionStyles().find(item => item.linethrough !== true);
        // 如果当前
        if (!state || (JSON.stringify(state) === '{}' && activeTxt['linethrough'] === true)) {
            // 如果当前已经设置了中划线,那就把全局中划线取消
            activeTxt.setSelectionStyles({'linethrough': false});
        } else {
            // 如果当前没设置中划线,那就添加上中划线
            activeTxt.setSelectionStyles({'linethrough': true});
        }
    } else {
        // 选择状态
        if (activeTxt['linethrough'] === true) {
            activeTxt.linethrough = false;
            activeTxt.dirty = true;
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].linethrough = false;
                }
            }
        } else {
            activeTxt.linethrough = true;
            activeTxt.dirty = true;
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].linethrough = true;
                }
            }
        }
    }
    canvas.renderAll();
}


//下划线
function underline() {
    //获取当前选中的文字
    let activeTxt = canvas.getActiveObject();
    // 如果当前没选中文字,那什么都不操作
    if (!activeTxt) return;
    // 判断当前是否进入编辑状态
    if (activeTxt.isEditing) {
        // 编辑状态
        const state = activeTxt.getSelectionStyles().find(item => item.underline !== true);
        // 如果当前
        if (!state || (JSON.stringify(state) === '{}' && activeTxt['underline'] === true)) {
            // 如果当前已经设置了下划线,那就把全局下划线取消
            activeTxt.setSelectionStyles({'underline': false});
        } else {
            // 如果当前没设置下划线,那就添加上下划线
            activeTxt.setSelectionStyles({'underline': true});
        }

    } else {
        // 选择状态
        if (activeTxt['underline'] === true) {
            activeTxt.underline = false;
            activeTxt.dirty = true;
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].underline = false;
                }
            }
        } else {
            activeTxt.underline = true;
            activeTxt.dirty = true;
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].underline = true;
                }
            }
        }
    }
    canvas.renderAll();
}

//斜体
function italic() {
    let activeTxt = canvas.getActiveObject();

    if (!activeTxt) return;

    if (activeTxt.isEditing) {
        // 编辑状态
        const state = activeTxt.getSelectionStyles().find(item => item.fontStyle !== 'italic');

        if (!state || (JSON.stringify(state) === '{}' && activeTxt['fontStyle'] === 'italic')) {
            activeTxt.setSelectionStyles({'fontStyle': 'normal'});
        } else {
            activeTxt.setSelectionStyles({'fontStyle': 'italic'});
        }
    } else {
        // 选择状态
        if (activeTxt['fontStyle'] === 'italic') {
            activeTxt.fontStyle = 'normal';
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].fontStyle = 'normal';
                }
            }
        } else {
            activeTxt.fontStyle = 'italic';
            let s = activeTxt.styles;
            for (let i in s) {
                for (let j in s[i]) {
                    s[i][j].fontStyle = 'italic';
                }
            }
        }
    }

    canvas.renderAll();
}


//文字对齐
function textalign(align_value) {

    canvas.getActiveObject().textAlign = align_value;

    canvas.renderAll();
}


var imageSaver = document.getElementById('lnkDownload');
imageSaver.addEventListener('click', saveImage, false);

function saveImage(e) {

    console.log('toJSON==', canvas.toJSON());

    console.log('toObject==', canvas.toObject()); // 输出序列化的内容

    this.href = canvas.toDataURL({
        format: 'png',
        quality: 0.8
    });
    this.download = 'canvas.png';

}
<think>好的,我现在需要帮助用户解决如何在Fabric.js中设置Textbox文本斜体样式。首先,我得回忆一下Fabric.js的相关知识。用户提到了IText和Textbox,我之前知道IText可以通过设置fontStyle属性为'italic'来实现斜体,但Textbox可能类似? 用户提供的引用里,引用[1]提到IText手动设置斜体的方法,所以可能Textbox也适用同样的方式。不过Textbox和IText在Fabric.js中是不同的类,可能需要确认。 接下来,我需要查阅Fabric.js的官方文档或者相关资料,确认Textbox是否支持fontStyle属性。根据引用[2],Fabric.js是一个Canvas库,官网可能有详细说明。访问官网后,发现Textbox继承自Text,而Text对象有fontStyle属性,可以设置为'italic'、'normal'等值。 所以,用户的问题应该是通过设置Textbox的fontStyle属性为'italic'来实现斜体。同时,需要注意可能需要调用set方法或者直接修改属性后触发渲染更新。 另外,用户提供的引用[3]中有template布局,涉及canvas的缩放和添加文字的操作,这可能影响实际显示效果,但问题核心还是设置斜体样式。 总结步骤:创建Textbox实例,设置fontStyle为'italic',然后添加到画布。或者动态修改已有Textbox的fontStyle并刷新画布。 还需要考虑用户可能遇到的常见问题,比如属性设置后没有立即生效,可能需要调用canvas.renderAll()方法。 最后,生成相关问题,比如如何加粗、如何动态切换样式等,帮助用户扩展知识。</think>### 如何设置 Fabric.js Textbox 文本斜体样式 在 Fabric.js 中,为 Textbox 设置斜体样式可通过以下两种方式实现: --- #### **1. 创建时直接设置斜体** 在初始化 Textbox 对象时,通过 `fontStyle` 属性指定为 `'italic'`: ```javascript const textbox = new fabric.Textbox('Hello World', { left: 50, top: 50, fontStyle: 'italic', // 关键属性 fontSize: 20 }); canvas.add(textbox); ``` --- #### **2. 动态修改现有文本样式** 通过 `set()` 方法修改已有 Textbox 对象的属性,并刷新画布: ```javascript textbox.set('fontStyle', 'italic'); // 切换为斜体 textbox.setCoords(); // 更新坐标 canvas.renderAll(); // 强制渲染 ``` --- #### **关键属性说明** - `fontStyle`: 控制字体样式,可选项为 `'normal'`(默认)、`'italic'`、`'oblique'`[^1] - 需注意字体本身需支持斜体变体,否则可能显示异常 --- #### **操作演示** ```javascript // 创建画布 const canvas = new fabric.Canvas('canvas'); // 添加可编辑的Textbox const textbox = new fabric.Textbox('点击编辑文字', { width: 200, fontFamily: 'Arial', fontSize: 20, fontStyle: 'italic' // 初始设置为斜体 }); canvas.add(textbox); // 按钮切换斜体 document.getElementById('toggleItalic').addEventListener('click', () => { const currentStyle = textbox.fontStyle; textbox.set('fontStyle', currentStyle === 'italic' ? 'normal' : 'italic'); canvas.requestRenderAll(); }); ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值