其他分享
首页 > 其他分享> > fabric 组合group 增加边框

fabric 组合group 增加边框

作者:互联网

本身是没有边框属性支持的,所以想要边框就得手写:

大体逻辑:

1、组合时,额外增加 rect 模拟边框样式,保存最初组合时 left top width height 属性

2、拆分时,需计算元素 top left(缩放等属性,因为group 移除元素时使用了 removeWithUpdate,故省却计算)

3、更新边框属性时,需删除对应边框(通常为组合最后一个元素),再根据当前 left top 和 历史 width height 计算出边框值添加到组合中

 

代码:

import { fabric } from "fabric";
import { KeyCode } from "./key-code";

/**
 * 组合
 * 使用添加 边框方法,模拟 group 的边框
 * 组合时,额外增加 rect 模拟边框样式,保存最初组合时 left top width height 属性
 * 拆分时,需计算元素 top left(缩放等属性,因为group 移除元素时使用了 removeWithUpdate,故省却计算)
 * 更新边框属性时,需删除对应边框(通常为组合最后一个元素),再根据当前 left top 和 历史 width height 计算出边框值添加到组合中
 */
export class GroupBoxTest {
    constructor(canvas) {
        // 创建多个 rect 对象
        let rect = new fabric.Rect(GroupBoxTest.defaultRect('red', 100));
        let rect1 = new fabric.Rect(GroupBoxTest.defaultRect('yellow', 250));
        let rect2 = new fabric.Rect(GroupBoxTest.defaultRect('blue', 400));
        canvas.add(rect, rect1, rect2);
        // 绑定键盘事件
        this.bindKeyBoard(canvas);
    }

    /**
     * 绑定键盘事件
     * @param canvas
     */
    bindKeyBoard(canvas) {
        $(document).on('keydown', (e) => {
            const key = e.originalEvent.keyCode;
            let objs = null;
            switch (key) {
                case KeyCode.Q: // 打印显示
                    console.log(canvas.getObjects());
                    break;
                case KeyCode.W: // 组合
                    // 获取选中元素
                    objs = canvas.getActiveObjects();
                    // 增加判断只能组合未组合图形
                    let hasGroup = false;
                    objs.forEach((item) => {
                        if (item.id.match(/group/)) {
                            hasGroup = true;
                            return false;
                        }
                    });
                    if (hasGroup) {
                        return false;
                    }
                    // 清除活动对象,活动对象已成组,会导致位置紊乱
                    canvas.discardActiveObject();
                    // 再进行组合
                    let group = new fabric.Group(objs, {
                        id: GroupBoxTest.getId('group'),
                        lockRotation: true, // 组合元素不给旋转
                    });
                    // 给组合增加 矩形背景,用于设置 模拟组容器边框等属性
                    let groupInfo = {
                        width: group.width - 1,
                        height: group.height - 1,
                        left: group.get('left'),
                        top: group.get('top')
                    };
                    let borderInfo = new fabric.Rect(GroupBoxTest.defaultBorder(groupInfo));
                    group.addWithUpdate(new fabric.Rect(borderInfo));
                    canvas.add(group);
                    // 删掉之前对象
                    canvas.remove(objs);
                    canvas.setActiveObject(group).renderAll();
                    break;
                case KeyCode.E: // 拆分
                    objs = canvas.getActiveObjects();
                    if (objs.length === 1 && objs[0].id.match(/group/)) {
                        // 组标志,同时拆分1 个组
                        canvas.discardActiveObject().renderAll();
                        let group = objs[0];
                        let childrenLen = group.size();
                        // 删除边框
                        group.removeWithUpdate(childrenLen - 1);
                        childrenLen -= 1;
                        // 处理内部元素
                        while (childrenLen > 0) {
                            let child = group.item(childrenLen - 1);
                            this.deleteGroup(child);
                            child.setCoords();
                            childrenLen--;
                        }
                        canvas.remove(group).renderAll();
                        canvas.discardActiveObject();
                    }
                    break;
                case KeyCode.R: // 更新表框属性
                    objs = canvas.getActiveObjects();
                    if (objs.length === 1 && objs[0].id.match(/group/)) {
                        let group = objs[0];
                        let childrenLen = group.size();
                        group.removeWithUpdate(group.item(childrenLen - 1));
                        let colorA = ['purple', 'grey', 'green', 'lightblue', 'orange', 'red'];
                        let r = Math.round(Math.random() * 20);
                        let sw = Math.round(Math.random() * 10);
                        let c = Math.round(Math.random() * 5);
                        let borderInfo = {
                            rx: r,
                            ry: r,
                            width: group.width - 1,
                            height: group.height - 1,
                            left: group.left,
                            top: group.top,
                            stroke: colorA[c],
                            strokeWidth: sw,
                        };
                        group.addWithUpdate(new fabric.Rect(GroupBoxTest.defaultBorder(borderInfo)));
                        canvas.renderAll();
                    }
                    break;
            }
        });
    }

    /**
     * 删除组信息,并计算元素相对信息数据
     * @param ele
     */
    deleteGroup(ele) {
        ele.top = ele.top + ele.group.top + ele.group.height * 0.5;
        ele.left = ele.left + ele.group.left + ele.group.width * 0.5;
        ele.width = ele.width * ele.scaleX;
        ele.height = ele.height * ele.scaleY;
        ele.scaleX = 1;
        ele.scaleY = 1;
        delete ele.group;
    }

    /**
     * 获取 id = type_time
     * @param type
     * @returns {string}
     */
    static getId(type) {
        return type + '_' + new Date().getTime();
    }

    /**
     * 获取默认测试矩形
     * @param color
     * @param left
     * @returns {{top: number, left, width: number, id: string, fill, height: number}}
     */
    static defaultRect(color, left) {
        return {
            fill: color,
            height: 100,
            left: left,
            top: 100,
            width: 100,
            id: GroupBoxTest.getId('rect'),
        }
    }

    /**
     * 获取模拟边框默认样式
     * @param info
     * @returns {{strokeWidth: number, top: number, left: number, rx: number, ry: number, width: *, fill: string, stroke: string, height: *}}
     */
    static defaultBorder(info) {
        let rx = info.rx || 0;
        let ry = info.ry || 0;
        let strokeWidth = info.strokeWidth || 1;
        let stroke =  info.stroke || '#000';
        return {
            ry: rx,
            rx: ry,
            width: info.width + rx + strokeWidth,
            height: info.height + ry + strokeWidth,
            left: info.left - rx * 0.5 - strokeWidth,
            top: info.top - ry * 0.5 - strokeWidth,
            fill: 'transparent',
            stroke: stroke,
            strokeWidth: strokeWidth,
        }
    }
}

 

标签:canvas,group,fabric,top,ele,let,边框,left
来源: https://www.cnblogs.com/guofan/p/16203373.html