ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

fabric 组合group 增加边框

2022-04-28 16:33:56  阅读:247  来源: 互联网

标签:canvas group fabric top ele let 边框 left


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

大体逻辑:

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有