基于G6实现的流成工具

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>插件:统一分层布局</title>
    <style>
        ::-webkit-scrollbar {
            display: none;
        }

        html,
        body {
            overflow: hidden;
        }
    </style>
</head>

<body>
    <div id="toolBar" style="position: absolute;z-index: 10">
        <button id="addCircle">新增圆</button>
        <button id="addRect">新增矩形</button>
        <button id="delete">删除</button>
        <button id="addCustom1">自定义形1</button>
        <button id="addCustom2">自定义形2</button>
        <button id="addCustom3">自定义形3</button>
        <button id="addLine">添加直线</button>
        <button id="addArrowLine">添加箭头直线</button>
        <button id="addSmooth">添加曲线</button>
        <button id="drag">拖拽模式</button>
        <button id="edit">编辑模式</button>
        <button id="consoleJSON">输出json</button>
        <button id="downloadImage">保存图片</button>
        <button id="reLayout">自动布局</button>
    </div>
    <div id="mountNode"></div>

</body>
<script>/*Fixing iframe window.innerHeight 0 issue in Safari*/document.body.clientHeight;</script>
<script src="https://gw.alipayobjects.com/os/antv/assets/g6/1.2.5/g6.min.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
<script src="https://gw.alipayobjects.com/os/antv/assets/g6-plugins/1.0.1/g6-plugins.min.js"></script>
<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<script type="text/javascript">

    //保存为图片
    $("#downloadImage").on('click', (bool) => {
        const matrixStash = net.getMatrix(); // 缓存当前矩阵
        if (bool) {
            net.autoZoom(); // 图自动缩放以适应画布尺寸
        }
        html2canvas(net.get('graphContainer'), {
            onrendered(canvas) {
                const dataURL = canvas.toDataURL('image/png');
                const link = document.createElement('a');
                const saveName = '图片' + ('.png' || 'graph.png');//<====选中模块名称
                link.download = saveName;
                link.href = dataURL.replace('image/png', 'image/octet-stream');
                link.click();
                net.updateMatrix(matrixStash); // 还原矩阵
                net.refresh();
            }
        });
    });

    const plugin = new G6.Plugins['layout.dagre']();
    const data = {
        nodes: [
           
        ],
        edges: [
            
        ]
    };
  
    
    const net = new G6.Net({
        id: 'mountNode',               // dom id
        height: window.innerHeight,    // 画布高
        fitView: 'autoZoom',
        grid: {//背景网格
            forceAlign: true, // 是否支持网格对齐
            cell: 10,         // 网格大小 
        },
        plugins: [plugin],
    });

    var i = 1;
    $('#addCircle').on('click', () => {//添加圆形节点
        net.add('node', {
            shape: 'circle',
            id: 'id' + i++,
            x: 50 + i * 10,
            y: 50 + i * 10
        });
        net.refresh();
    });

    $('#addRect').on('click', () => {//添加矩形
        net.add('node', {
            shape: 'rect',
            id: 'id' + i++,
            x: 50 + i * 10,
            y: 50 + i * 10
        });
        net.refresh();
    });
    var Util = G6.Util;
    var input = Util.createDOM('<input class="g6-label-input" />', {
        position: 'absolute',
        zIndex: 10,
        display: 'none'
    });

    function hasClass(shape, className) {
        if (shape) {
            const clasees = shape.get('class');
            if (clasees && clasees.indexOf(className) !== -1) {
                return true;
            }
        }
        return false;
    }

    function showInputLabel(node) {
        if (!node) {
            return;
        }
        const group = node.get('group');
        const label = group.findBy(function (child) {
            if (hasClass(child, 'label')) {
                return true;
            }
            return false;
        });
        const rootGroup = net.get('rootGroup');
        const bbox = Util.getBBox(label, rootGroup);
        const borderWidth = 1;
        const text = label.attr('text');
        clearAllActived();

        input.value = text;
        input.show();
        input.css({
            top: bbox.minY - borderWidth + 'px',
            left: bbox.minX - borderWidth + 'px',
            width: bbox.width + 'px',
            height: bbox.height + 'px',
            padding: '0px',
            margin: '0px',
            border: borderWidth + 'px solid #999'
        });
        input.focus();
        input.node = node;
    }

    function updateLabel() {
        if (input.visibility) {
            const node = input.node;
            clearAllActived();
            if (input.value !== node.get('model').name) {
                if (input.value) {
                    net.update(node, {
                        label: input.value
                    });
                }
            }
            input.hide();
        }
    }

    function clearAllActived() {
        net.clearAllActived();
        net.refresh(false);
    }
    input.hide = function () {
        input.css({
            display: 'none'
        });
        input.visibility = false;
    };
    input.show = function () {
        input.css({
            display: 'block'
        });
        input.visibility = true;
    };

    input.on('keydown', ev => {
        if (ev.keyCode === 13) {
            updateLabel();
        }
    });

    input.on('blur', () => {
        updateLabel();
    });


    const graphContainer = net.get('graphContainer');//获取图表内部容器
    graphContainer.appendChild(input);//追加input输入框
    graphContainer.oncontextmenu = function (e) { return false; }//阻止默认右键菜单
    net.on('contextmenu', ev => {// 鼠标右键点击事件
        console.log("选中类型:", ev.itemType);
        console.log(ev);
    });

    net.on('itemmouseenter', ev => {//子项鼠标悬浮
        const item = ev.item;
        net.update(item, {
            color: 'red',
        });
        net.refresh();
    });
    net.on('itemmouseleave', ev => {//子项鼠标离开事件
        const item = ev.item;
        net.update(item, {
            color: null
        });
        net.refresh();
    });
    net.on('itemmousedown', ev => {//子项鼠标按下
        const item = ev.item;
        net.update(item, {
            color: '#9ef'
        });
    });
    net.on('itemmouseup', ev => {//子项鼠标弹起
        const item = ev.item;
        net.update(item, {
            color: 'null'
        });
    });

    net.on('dragmove', () => {//拖拽隐藏
        input.hide();
    });

    net.on('dblclick', ev => {//双击显示
        const item = ev.item;
        const shape = ev.shape;
        if (hasClass(shape, 'label') && item && item.get('type') === 'node') {//节点的情况下
            showInputLabel(item);
        }
    });

    $('#delete').on('click', () => {//根据添加顺序删除
        if (i > 1) {
            i = i - 1;
            const item = net.find('id' + i);
            net.remove(item);
            net.refresh();
        }
    });

    G6.registerNode('customNode1', {
        getAnchorPoints() {
            return [
                [0, 0.25],
                [0, 0.5],
                [0, 0.75],
                [1, 0.25],
                [1, 0.5],
                [1, 0.75],
                [0.25, 0],
                [0.5, 0],
                [0.75, 0],
                [0.25, 1],
                [0.5, 1],
                [0.75, 1]
            ];
        }
    }, 'rect');

    $('#addCustom1').on('click', () => {//添加自定义节点图形
        net.beginAdd('node', {
            label: '[未定义]',
            shape: 'circle'
        });
    });

    $('#addCustom2').on('click', () => {//添加自定义节点图形
        net.beginAdd('node', { label: '[未定义]' });
    });

    $('#addCustom3').on('click', () => {//添加自定义节点图形
        net.beginAdd('node', {
            label: '[未定义]',
            shape: 'customNode1'//<====
        });
    });

    $('#addLine').on('click', () => {//添加普通直线
        net.beginAdd('edge', {
            shape: 'line'//<====
        });
    });

    $('#addArrowLine').on('click', () => {//添加箭头直线
        net.beginAdd('edge', {
            shape: 'arrow'//<====
        });
    });

    $('#addSmooth').on('click', () => {//添加曲线
        net.beginAdd('edge', {
            shape: 'smooth'//<====
        });
    });

    $('#drag').on('click', () => {//拖拽模式
        net.changeMode('drag');
    });

    $('#edit').on('click', () => {//编辑模式
        net.changeMode('edit');
    });

    $('#consoleJSON').on('click', () => {//控制台输入json
        const saveData = net.save();
        const json = JSON.stringify(saveData, null, 2);
        console.log(saveData, json); // eslint-disable-line no-console
    });



    net.source(data.nodes, data.edges);

    net.tooltip({
        title: '节点信息', // @type {String} 标题
        split: ':',  // @type {String} 分割符号
        dx: 10,       // @type {Number} 水平偏移
        dy: 10        // @type {Number} 竖直偏移
    });
    net.node().tooltip(['id', 'label']);
    net.edge().tooltip(['id']);
    net.render();
    
$("#reLayout").on('click', () => {
            var a = net.save();
            net.changeData();
            a.source.edges.forEach((v, i, a) => {
                delete v.x;
                delete v.y;
            });
            a.source.nodes.forEach((v, i, a) => {
                delete v.x;
                delete v.y;
            });
            net.source(a.source.nodes, a.source.edges);
            net.render();
        });
</script>


</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351