原生js绘制流程图

<!DOCTYPE html>
<html lang="en" onselectstart='return false'>

    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <style type="text/css">
            #d1 {
                width: 800px;
                height: 800px;
                border: 1px solid #ccc;
                background: #fafafa;
                position: relative;
            }
            #d1 .drawContent{
                position: absolute;
                width: 100%;
                height: 100%;
            }
            #d1 .drawContent div {
                width: 130px;
                height: 30px;
                border: 1px solid #ccc;
                background: #fff;
                border-radius: 8px;
                position: absolute;
                text-align: center;
                line-height: 30px;
                z-index: 2;
                cursor: move;
            }
            
            #d1 .drawContent div span {
                display: inline-block;
                width: 130px;
                height: 20px;
                line-height: 20px;
                cursor: move;
            }
            
            #d1 .drawContent div i {
                display: inline-block;
                width: 10px;
                height: 10px;
                background: #fff;
                border-radius: 50%;
                position: absolute;
                top: -7px;
                left: 46%;
                border: 1px solid #ccc;
                cursor: default;
            }
            
            #d1 .drawContent div s {
                display: inline-block;
                width: 10px;
                height: 10px;
                background: #fff;
                border-radius: 50%;
                position: absolute;
                bottom: -7px;
                left: 46%;
                border: 1px solid #ccc;
                cursor: crosshair;
            }
            
            #d1 .drawContent div u {
                position: absolute;
                display: inline-block;
                border: 6px solid transparent;
                border-top: 6px solid #ccc;
                top: 0px;
                left: 58px;
            }
            
            #d1 .drawContent div s:hover {
                background: #F8BC06;
            }
            
            #d1 svg {
                width: 100%;
                height: 100%;
                position: absolute;
                z-index: 1;
            }
            
            #d2 {
                width: 300px;
                height: 2000px;
            }
            
            ul li {
                cursor: default;
            }
        </style>
    </head>

    <body>
        <ul id="Dragblock">
            <li data-name='xiangjiao'>
                <span>香蕉</span>
            </li>
            <li data-name='pingguo'>
                <span>苹果</span>
            </li>
            <li data-name='liulian'>
                <span>榴莲</span>
            </li>
            <li data-name='xigua'>
                <span>西瓜</span>
            </li>
            <li data-name='xihongshi'>
                <span>西红柿</span>
            </li>
        </ul>
        <div id='d1'>
            <div class="drawContent">

            </div>
            <svg></svg>
        </div>
        <div id='d2'></div>
        <script type="text/x-handlebars-template" id="content">
            {{#each this}}
            <div class="{{name}}" data-drag="1" data-id='{{id}}' data-inx='{{inx}}' data-iny='{{iny}}' style="top:{{y}}px;left:{{x}}px">
                <u style="display:{{arrow}}"></u>
                <span class="label">{{label}}</span>
                <s title="输出"></s>
            </div>
            {{/each}}
        </script>
        <script type="text/x-handlebars-template" id="line">
            {{#each this}} {{#each link}}
            <g class="{{name}}">
                <path d="M{{../outx}} {{../outy}} Q{{mx1}} {{my1}} {{mx2}} {{my2}} T{{dx}} {{dy}}" stroke="#CCCCCC" fill="none" style="stroke-width: 1px;" />
            </g>
            {{/each}} {{/each}}
        </script>
        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
        <script src="https://cdn.bootcss.com/handlebars.js/4.0.10/handlebars.min.js"></script>
        <script type="text/javascript">
            var element;
            // 获得容器的宽度
            var dWidth = Number($('#d1').css('width').slice(0, -2));
            // 获得容器的高度
            var dHeight = Number($('#d1').css('height').slice(0, -2));
            var dragData = []

            function reload() {
                var myTemplate = Handlebars.compile($("#content").html());
                $('#d1 .drawContent').html(myTemplate(dragData));
                var myLine = Handlebars.compile($("#line").html());
                $('#d1 svg').html(myLine(dragData));
            }
//            reload();
            //按下列表创建虚像
            $('#Dragblock li').mousedown(function(e) {
                var span = document.createElement('span');
                span.innerHTML = $(this).text();
                span.setAttribute('data-name', $(this).data('name'));
                span.style.opacity = 0.6;
                span.style.position = 'absolute';
                span.style.top = (e.pageY - 8) + 'px';
                span.style.left = (e.pageX - 8) + 'px';
                span.style.zIndex = 5;
                $(this).append(span);
                element = $(this).children('span:last-child');
                console.log('element', element);
            })
            // 文档鼠标抬起时判断在不在容器内,创建元素
            $(document).mouseup(function(e) {
                console.log('e.target', e.target);
                $('#d1').unbind('mousemove');
                if(element) {
                    if(e.pageY > $('#d1').offset().top && e.pageX > $('#d1').offset().left) {
                        console.log('e.offsetY', e.offsetY, 'e.offsetX', e.offsetX);
                        console.log(element);
                        var x = e.pageX - $('#d1').offset().left - e.offsetX;
                        var y = e.pageY - $('#d1').offset().top - e.offsetY;
                        //判断x
                        if((x >= 0 && x <= dWidth - 132)) {
                            x = x;
                        } else if(x < 0) {
                            x = 1;
                        } else if(x > dWidth - 132) {
                            x = dWidth - 132
                        }
                        //判断y
                        if((y >= 0 && y <= dHeight - 32)) {
                            y = y;
                        } else if(y < 0) {
                            y = 1;
                        } else if(y > dHeight - 32) {
                            y = dHeight - 32
                        }
                        dragData.push({
                            id: dragData.length,
                            name: element.data('name'),
                            draw: false,
                            label: element.text(),
                            x: x,
                            y: y,
                            outx: x + 68,
                            outy: y + 30,
                            inx: x + 65,
                            iny: y - 1,
                            link: [],
                            linked: [],
                            dx: 0,
                            dy: 0,
                            arrow: "none"
                        })
                        reload();
                        element.remove();
                        element = undefined;
                    } else {
                        element.remove();
                        element = undefined;
                    }
                }

            })
            //拖动虚像在文档中进行移动
            $(document).mousemove(function(e) {
                //console.log('x',e.pageX,'y',e.pageY);
                if(element) {
                    element.css({
                        'top': (e.pageY - 8) + 'px',
                        'left': (e.pageX - 8)
                    });
                }
            })
            //给创建的新的组件加上mousedown事件
            var waitElement;
            $('#d1 > .drawContent').on('mousedown', 'div', function(e) {
                waitElement = $(this);
                console.log(waitElement);
                var dx = e.offsetX
                var dy = e.offsetY
                console.log('e.offsetX', e.offsetX)
                console.log('e.offsetY', e.offsetY)
                //容器的mousemove事件
                $('#d1').on("mousemove",function(e) {
                    if(waitElement) {
                        waitElement.css({
                            top: (e.pageY - $('#d1').offset().top - dy) + 'px',
                            left: (e.pageX - $('#d1').offset().left - dx) + 'px'
                        });
                        console.log(waitElement.data('id'));
                        var id = waitElement.data('id')
                        var x = e.pageX - $('#d1').offset().left - dx;
                        var y = e.pageY - $('#d1').offset().top - dy;
                        //判断x
                        if((x >= 0 && x <= dWidth - 132)) {
                            x = x;
                        } else if(x < 0) {
                            x = 1;
                        } else if(x > dWidth - 132) {
                            x = dWidth - 132
                        }
                        //判断y
                        if((y >= 0 && y <= dHeight - 32)) {
                            y = y;
                        } else if(y < 0) {
                            y = 1;
                        } else if(y > dHeight - 32) {
                            y = dHeight - 32
                        }
                        for(var i = 0; i < dragData.length; i++) {
                            if(id == dragData[i].id) {
                                console.log(dragData[i]);
                                dragData[i].x = x;
                                dragData[i].outx = dragData[i].x + 68;
                                dragData[i].inx = dragData[i].x + 65;
                                dragData[i].y = y;
                                dragData[i].outy = dragData[i].y + 30;
                                dragData[i].iny = dragData[i].y - 1;
                                console.log('要开始了')
                                for(let j = 0; j < dragData[i].link.length; j++) {
                                    dragData[i].link[j].linkId = parseFloat(dragData[i].link[j].name.split("|")[1]);
                                }
                                for(var k = 0; k < dragData[i].linked.length; k++) {
                                    console.log('dragData[i].linked[k]', dragData[i].linked[k]);
                                    for(let j = 0; j < dragData.length; j++) {
                                        if(dragData[i].linked[k].linkedNum == dragData[j].id) {
                                            console.log('ID一样了啊');
                                            for(let m = 0; m < dragData[j].link.length; m++) {
                                                if(dragData[i].linked[k].name == dragData[j].link[m].name) {
                                                    console.log("名字一样了啊");
                                                    dragData[j].link[m].dx = dragData[i].inx;
                                                    dragData[j].link[m].dy = dragData[i].iny;
                                                    dragData[j].link[m].mx1 = dragData[j].outx;
                                                    dragData[j].link[m].my1 = dragData[j].link[m].dy > dragData[j].outy ? dragData[j].outy + (dragData[j].link[m].dy - dragData[j].outy) / 4 : dragData[j].outy - (dragData[j].link[m].dy - dragData[j].outy) / 4;
                                                    dragData[j].link[m].mx2 = dragData[j].outx + (dragData[j].link[m].dx - dragData[j].outx) / 2,
                                                    dragData[j].link[m].my2 = dragData[j].outy + (dragData[j].link[m].dy - dragData[j].outy) / 2
                                                }
                                            }
                                        }
                                    }
                                }
                                reload();
                                if(dragData[i].link.length > 0) {
                                    for(var j = 0; j < dragData[i].link.length; j++) {
                                        dragData[i].link[j].mx1 = dragData[i].outx;
                                        dragData[i].link[j].my1 = dragData[i].link[j].dy > dragData[i].outy ? dragData[i].outy + (dragData[i].link[j].dy - dragData[i].outy) / 4 : dragData[i].outy - (dragData[i].link[j].dy - dragData[i].outy) / 4;
                                        dragData[i].link[j].mx2 = dragData[i].outx + (dragData[i].link[j].dx - dragData[i].outx) / 2,
                                            dragData[i].link[j].my2 = dragData[i].outy + (dragData[i].link[j].dy - dragData[i].outy) / 2
                                    }
                                }
                                reload();
                            }
                        }
                        console.log(dragData);
                        reload();
                    }
                })
            })
            //给创建的新的组件加上mouseup事件
            $('#d1 > .drawContent > div').mouseup(function() {
                waitElement = undefined;
                console.log(waitElement);
            })
            //容器的mouseup事件
            $('#d1').mouseup(function(e) {
                console.log('我抬起了');
                waitElement = undefined;
                if(waitElement) {
                    waitElement.css({
                        top: e.pageY - $('#d1').offset().top,
                        left: e.pageX - $('#d1').offset().left
                    })
                }
            })
            //给组件的输出圆圈加入mouseenter事件使组件不能拖拽
            $('#d1 > .drawContent').on('mouseenter', 'div>s', function() {
                console.log('进入了输出');
                waitElement = undefined;
                $('svg').unbind('mousemove');
            })
            //先给组件的输出源加入mousedown事件,先创建连线
            $('#d1 > .drawContent').on('mousedown', 'div>s', function(event) {
                event.preventDefault();
                event.stopPropagation();
                //先创建连线的数据
                console.log($(this).parent());
                var parent = $(this).parent();
                var id = parent.data('id');
                console.log('idididid', id);
                for(var i = 0; i < dragData.length; i++) {
                    if(dragData[i].id == id) {
                        dragData[i].draw = true;
                        dragData[i].link.push({
                            name: id + parent.attr('class'),
                            dx: 0,
                            dy: 0,
                            mx1: 0,
                            my1: 0,
                            mx2: 0,
                            my2: 0
                        });
                        console.log('dragData哈哈哈哈', dragData);
                        $('body').on('mouseup', function(e) {
                            for(var j = 0; j < dragData.length; j++) {
                                if(id == dragData[j].id) {
                                    console.log('页面抬起了');
                                    dragData[j].draw = false;
                                    var $dom=$(e.target).data("drag")?$(e.target):$(e.target).closest("div[data-drag]");
                                    if($dom.length){
                                        if($dom.data("drag") && $dom[0].dataset.id!=dragData[j].id){//判断是否关联另外模块,非自己
                                            $('svg').unbind('mousemove');
                                            var name=dragData[j].link[dragData[j].link.length - 1].name + "|" + $dom[0].dataset.id + $dom[0].className;
                                            var isontbe=0;//判断是否存在关联
                                            for(let i = 0; i < dragData.length; i++){
                                                if($dom[0].dataset.id == dragData[i].id){
                                                    for(let c = 0; c < dragData[i].linked.length; c++){
                                                        if(name==dragData[i].linked[c].name){
                                                            isontbe=1
                                                        }
                                                    }
                                                    if(!isontbe){//不存在时候存入linked
                                                        dragData[i].linked.push({
                                                            name: name,
                                                            linkedNum:parseFloat(name)
                                                       })
                                                        dragData[i].arrow = "inline-block";
                                                    }
                                                }
                                            }
                                            if(!isontbe){//不存在时候生成link数据
                                                dragData[j].link[dragData[j].link.length - 1].name = name;
                                                dragData[j].link[dragData[j].link.length - 1].dx = Number($dom[0].dataset.inx);
                                                dragData[j].link[dragData[j].link.length - 1].dy = Number($dom[0].dataset.iny);
                                               }else{
                                                   dragData[j].link.splice(dragData[j].link.length-1,1);
                                               }
                                        } else {
                                            dragData[j].link.splice(dragData[j].link.length - 1, 1);
                                        }
                                    } else {
                                        dragData[j].link.splice(dragData[j].link.length - 1, 1);
                                    }
                                    $('svg').unbind('mousemove');
                                    reload();
                                }
                            }
                            $('body').unbind('mouseup');
                        })
                    }
                }
            })
            //给输出圆圈添加mouseup事件
            $('#d1 > .drawContent').on('mouseup', 'div>s', function() {
                var parent = $(this).parent();
                for(var i = 0; i < dragData.length; i++) {
                    if(parent.data('id') == dragData[i].id) {
                        dragData[i].draw = false;
                        console.log(dragData[i]);
                    }
                }
            })
            //给组件的输出源加入mouseleave事件使组件继续能够拖拽
            $('#d1 > .drawContent').on('mouseleave', 'div>s', function(event) {
                event.preventDefault();
                event.stopPropagation();
                console.log('离开了了输出');
                console.log($(this).parent());
                waitElement = $(this).parent();
                var id = waitElement.data('id')
                //给svg加mousemove事件
                for(var i = 0; i < dragData.length; i++) {
                    if(id == dragData[i].id) {
                        if(dragData[i].draw == true) {
                            $('svg').mousemove(function(e) {
                                for(var i = 0; i < dragData.length; i++) {
                                    if(id == dragData[i].id) {
                                        console.log(dragData[i]);
                                        if(dragData[i].link[dragData[i].link.length - 1]) {
                                            dragData[i].link[dragData[i].link.length - 1].dx = e.offsetX;
                                            dragData[i].link[dragData[i].link.length - 1].dy = e.offsetY;
                                            dragData[i].link[dragData[i].link.length - 1].mx1 = dragData[i].outx;
                                            dragData[i].link[dragData[i].link.length - 1].my1 = dragData[i].dy > dragData[i].outy ? dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 4 : dragData[i].outy - (dragData[i].dy - dragData[i].outy) / 4;
                                            dragData[i].link[dragData[i].link.length - 1].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2,
                                                dragData[i].link[dragData[i].link.length - 1].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2
                                        }
                                        //
                                        dragData[i].dx = e.offsetX;
                                        dragData[i].dy = e.offsetY;
                                        dragData[i].mx1 = dragData[i].outx;
                                        if(dragData[i].dy > dragData[i].outy) {
                                            dragData[i].my1 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 4;
                                        } else {
                                            dragData[i].my1 = dragData[i].outy - (dragData[i].dy - dragData[i].outy) / 4;
                                        }
                                        dragData[i].mx2 = dragData[i].outx + (dragData[i].dx - dragData[i].outx) / 2
                                        dragData[i].my2 = dragData[i].outy + (dragData[i].dy - dragData[i].outy) / 2
                                    }
                                }
                                reload();
                                console.log(2333);
                            })
                        } else {
                            $('svg').unbind('mousemove');
                        }

                    }
                }
            })
            //给svg添加mouseup事件
            $('svg').mouseup(function(e) {
                console.log(e.target);
                $('svg').unbind('mousemove');
                for(var i = 0; i < dragData.length; i++) {
                    dragData[i].draw = false;
                }
                console.log('起来了');
            })
        </script>
    </body>

</html>
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
 跨浏览器,可兼容IE7--IE10, FireFox, Chrome, Opera等几大内核的浏览器,且不需要浏览器再加装任何控件。  多系统兼容性、可移植性:由于只包括前台UI,因此二次开发者可很方便将本插件用在任何一种需要流程图的B/S系统应用上,流程图的详细实现逻辑完全交于后台程序开发者自己实现;对于后台,只要能返回/接收能被本插件解析的JSON格式数据即可.所以本插件可用于不同的服务器语言建立的后台上.  跨领域:流程图设计器不止用在电信领域,在其它需要IT进行技术支持的领域中都有重大作用.  以下从纯技术实现层面具体描述:  页面顶部栏、左边侧边栏均可自定义;  当左边的侧边栏设为不显示时,为只读状态,此时的视图区可当作是一个查看器而非编辑器。  侧边工具栏除了基本和一些流程节点按钮外,还自定义新的节点按钮,自定义节点都可以有自有的图标、类型名称,定义后在使用可可在工作区内增加这些自定义节点。  顶部栏可显示流程图数据组的标题,也可提供一些常用操作按钮。  顶部栏的按钮,除了撤销、重做按钮外,其余按钮均可自定义点击事件。  可画直线、折线;折线还可以左右/上下移动其中段。  具有区域划分功能,能让用户更直观地了解哪些节点及其相互间的转换,是属于何种自定义区域内的。  具有标注功能,用橙红色标注某个结点或者转换线,一般用在展示流程进度时。  能直接双击结点、连线、分组区域中的文字进行编辑  在对结点、连线、分组区域的各种编辑操作,如新增/删除/修改名称/重设样式或大小/移动/标注时,均可捕捉到事件,并触发自定义事件,如果自定义事件执行的方法返回FALSE,则会阻止操作。  具有操作事务序列控制功能,在工作区内的各种有效操作都能记录到一个栈中,然后可以进行撤销(undo())或重做(redo()),像典型的C/S软件一样。  0.4版中,加入了只导出在初始载入后被编辑的流程图中,只作了增删改等变更的元素,这样可用于用户快速存储,只保存本次变更过的内容,不用重新保存整个流程。  0.5版中,结点的样式不再受到原有程序的限制,所有样式均默认为淡蓝色长方形;如果要指定为圆形,可在初始化时定义结点类型为”原有类型”+” round”;如果要指定为复合结点,则可在初始化时定义结点类型为”原有类型”+” mix”。”原有类型”+” myType”:myType可为自己写的一种特殊样式类.  0.6版中,修正了一些BUG,改善了用户操作体验,并增加在可编辑状态下时,能用键盘上DELETE按键对元素进行删除功能。  0.7版中,修正了一些BUG,增加了连线变更要连的起始结点或结束结点的功能。  0.8版,取消原来的拟物化页面,变成如今的扁平化页面,并且支持主要位置的颜色自定义功能(如果想沿用原来老版本中的拟物化页面,只需保留原来的GooFlow.css文件即可);修正0.7版中的画线BUG。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值