上一篇文章中,我们添加了元素(矩形框),接下来给矩形框加上带箭头的直线,代码如下:

var wf_r = null; //画板对象
var wf_steps = []; //步骤数组
var wf_width = 108; //步骤宽度
var wf_height = 50; //步骤高度
var wf_rect = 8;
var wf_stepDefaultName = "新步骤";//默认步骤名称
var addToJSON = false;
var wf_nodeBorderColor = "#587aa9"; //节点边框颜色
var wf_noteColor = "#efeff0"; //节点填充颜色

var wf_focusObj=null;

var mouseX=0;

var mouseY=0;

var wf_option="";

var wf_conns = [];    //连线数组

//添加连线
function addConn() {
    if (!wf_focusObj || !isStepObj(wf_focusObj)) {
        alert("请选择要连接的步骤!"); return false;
    }
   
    wf_option = "line";
    document.body.onmousemove = mouseMove;
    document.body.onmousedown = function () {
        for (var i = 0; i < tempArrPath.length; i++) {
            tempArrPath[i].arrPath.remove();
        }
        tempArrPath = [];
        document.body.onmousemove = null;
    };
}

//判断一个对象是否是步骤对象
function isStepObj(obj) {
    return obj && obj.type1 && (obj.type1.toString() == "normal");
}

function mouseMove(ev) {
    ev = ev || window.event;
    var mousePos = mouseCoords(ev);
    mouseX = mousePos.x;
    mouseY = mousePos.y;
    var obj = { obj1: wf_focusObj, obj2: null };
    wf_r.drawArr(obj);
}

//判断一个节点与另一个节点之间是否可以连线
function isLine(obj) {
    if (!obj || !obj.obj1 || !obj.obj2) {
        return false;
    }
    if (obj.obj1 === obj.obj2) {
        return false;
    }
    if (!isStepObj(obj.obj1) || !isStepObj(obj.obj2)) {
        return false;
    }
    for (var i = 0; i < wf_conns.length; i++) {
        if (obj.obj1 === obj.obj2 || (wf_conns[i].obj1 === obj.obj1 && wf_conns[i].obj2 === obj.obj2)) {
            return false;
        }
    }
    return true;
}

function mouseCoords(ev) {
    if (ev.pageX || ev.pageY) {
        return { x: ev.pageX, y: ev.pageY };
    }
    return {
        x: ev.clientX + document.body.scrollLeft - document.body.clientLeft,
        y: ev.clientY + document.body.scrollTop - document.body.clientTop
    };
}

//随着节点位置的改变动态改变箭头
Raphael.fn.drawArr = function (obj) {
    if (!obj || !obj.obj1) {
        return;
    }
  
    if (!obj.obj2) {
        var point1 = getStartEnd(obj.obj1, obj.obj2);
        var path2 = getArr(point1.start.x, point1.start.y, mouseX, mouseY, 7);
        for (var i = 0; i < tempArrPath.length; i++) {
            tempArrPath[i].arrPath.remove();
        }
        tempArrPath = [];
        obj.arrPath = this.path(path2);
        obj.arrPath.attr({ "stroke-width": 1.7, "stroke": wf_connColor, "fill": wf_connColor });
        tempArrPath.push(obj);
        return;
    }
    
    var point = getStartEnd(obj.obj1, obj.obj2);
    var path1 = getArr(point.start.x, point.start.y, point.end.x, point.end.y, 7);
    try {
        if (obj.arrPath) {
            obj.arrPath.attr({ path: path1 });
        }
        else {
            obj.arrPath = this.path(path1);
            obj.arrPath.attr({ "stroke-width": 1.7, "stroke": wf_connColor, "fill": wf_connColor, "x": point.start.x, "y": point.start.y, "x1": point.end.x, "y1": point.end.y });
            if (wf_designer) {
                obj.arrPath.click(connClick);
                obj.arrPath.dblclick(connSetting);
                obj.arrPath.id = obj.id;
                obj.arrPath.fromid = obj.obj1.id;
                obj.arrPath.toid = obj.obj2.id;
            }
        }
    } catch (e) { }
    return obj;
};

//得到直线的在矩形上的起点和终点坐标
function getStartEnd(obj1, obj2) {
    var bb1 = obj1 ? obj1.getBBox() : null;
    var bb2 = obj2 ? obj2.getBBox() : null;
    var p = [
        { x: bb1.x + bb1.width / 2, y: bb1.y - 1 },
        { x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + 1 },
        { x: bb1.x - 1, y: bb1.y + bb1.height / 2 },
        { x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height / 2 },
        bb2 ? { x: bb2.x + bb2.width / 2, y: bb2.y - 1 } : {},
        bb2 ? { x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + 1 } : {},
        bb2 ? { x: bb2.x - 1, y: bb2.y + bb2.height / 2 } : {},
        bb2 ? { x: bb2.x + bb2.width + 1, y: bb2.y + bb2.height / 2 } : {}
    ];
    var d = {}, dis = [];
    for (var i = 0; i < 4; i++) {
        for (var j = 4; j < 8; j++) {
            var dx = Math.abs(p[i].x - p[j].x),
                dy = Math.abs(p[i].y - p[j].y);
            if (
                (i == j - 4) ||
                (((i != 3 && j != 6) || p[i].x < p[j].x) &&
                    ((i != 2 && j != 7) || p[i].x > p[j].x) &&
                    ((i != 0 && j != 5) || p[i].y > p[j].y) &&
                    ((i != 1 && j != 4) || p[i].y < p[j].y))
            ) {
                dis.push(dx + dy);
                d[dis[dis.length - 1]] = [i, j];
            }
        }
    }
    if (dis.length == 0) {
        var res = [0, 4];
    } else {
       // alert(Math.min.apply(Math, dis))
        res = d[Math.min.apply(Math, dis)];
    }
    var result = {};
    result.start = {};
    result.end = {};
    result.start.x = p[res[0]].x;
    result.start.y = p[res[0]].y;
    result.end.x = p[res[1]].x;
    result.end.y = p[res[1]].y;
    return result;
}

function getArr(x1, y1, x2, y2, size) {
    var angle = Raphael.angle(x1, y1, x2, y2);
    var a45 = Raphael.rad(angle - 28);
    var a45m = Raphael.rad(angle + 28);
    var x2a = x2 + Math.cos(a45) * size;
    var y2a = y2 + Math.sin(a45) * size;
    var x2b = x2 + Math.cos(a45m) * size;
    var y2b = y2 + Math.sin(a45m) * size;
    return ["M", x1, y1, "L", x2, y2, "M", x2, y2, "L", x2b, y2b, "L", x2a, y2a, "z"].join(",");
}

//得到带箭头的起点和终点坐标
function getArr(x1, y1, x2, y2, size) {
    var angle = Raphael.angle(x1, y1, x2, y2);
    var a45 = Raphael.rad(angle - 28);
    var a45m = Raphael.rad(angle + 28);
    var x2a = x2 + Math.cos(a45) * size;
    var y2a = y2 + Math.sin(a45) * size;
    var x2b = x2 + Math.cos(a45m) * size;
    var y2b = y2 + Math.sin(a45m) * size;
    return ["M", x1, y1, "L", x2, y2, "M", x2, y2, "L", x2b, y2b, "L", x2a, y2a, "z"].join(",");
}

//单击事件执行相关操作
function click()
{
    var o = this;
    switch (wf_option)
    {
        case "line":
            var obj = { id: getGuid(), obj1: wf_focusObj, obj2: o };
            connObj(obj);
            break;
        default:
            changeStyle(o);
            break;
    }
    wf_option = "";
    wf_focusObj = this;
}

//连接对象
function connObj(obj, addToJSON, title) {
    if (addToJSON == undefined || addToJSON == null) addToJSON = true;
    if (isLine(obj))
    {
        var newline = wf_r.drawArr(obj);
        wf_conns.push(newline);
    }
}

//添加步骤
function addStep(x, y, text, id, addToJSON, type1, bordercolor, bgcolor) {
    var guid = getGuid();
    var xy = getNewXY();
    x = x || xy.x;
    y = y || xy.y;
    
    text = text || wf_stepDefaultName;
   
    id = id || guid;
    var rect = wf_r.rect(x, y, wf_width, wf_height, wf_rect);
    rect.attr({ "fill": bgcolor || wf_noteColor, "stroke": bordercolor || wf_nodeBorderColor, "stroke-width": 1.4, "cursor": "default" });
    rect.id = id;
    rect.type1 = type1 ? type1 : "normal";
    rect.drag(move, dragger, up);

rect.click(click);

wf_steps.push(rect);

var text2 = text.length > 8 ? text.substr(0, 7) + "..." : text;
    var text1 = wf_r.text(x + 52, y + 25, text2);
    text1.attr({ "font-size": "12px" });
    if (text.length > 8) text1.attr({ "title": text });
    text1.id = "text_" + id;
    text1.type1 = "text";
}

//拖动节点开始时的事件
function dragger() {
    this.ox = this.attr("x");
    this.oy = this.attr("y");
    //changeStyle(this);
}

//拖动事件
function move(dx, dy) {
    var x = this.ox + dx;
    var y = this.oy + dy;

if (x < 0) {
        x = 0;
    }
    else if (x > wf_r.width - wf_width) {
        x = wf_r.width - wf_width;
    }

if (y < 0) {
        y = 0;
    }
    else if (y > wf_r.height - wf_height) {
        y = wf_r.height - wf_height;
    }
    var att = { x: x, y: y };
    this.attr(att);
    if (this.id) {
        var text = wf_r.getById('text_' + this.id);
        if (text) {
            text.attr("x", x + 52);
            text.attr("y", y + 25);
        }
    }
};

//拖动后的事件
function up()
{
}

//得到新步骤的XY
function getNewXY() {
    var x = 10, y = 50;
    if (wf_steps.length > 0) {
        var step = wf_steps[wf_steps.length - 1];
        x = parseInt(step.attr("x")) + 170;
        y = parseInt(step.attr("y"));
        if (x > wf_r.width - wf_width) {
            x = 10;
            y = y + 100;
        }

if (y > wf_r.height - wf_height) {
            y = wf_r.height - wf_height;
        }
    }
    return { x: x, y: y };
}

//得到GUID
function getGuid() {
    return Raphael.createUUID().toLowerCase();
}

Raphael绘制流程图(二),添加带箭头的直线相关推荐

  1. Raphael绘制流程图箭头的方法

    原项目使用的Raphael绘制流程图,要求能自定义箭头的样式和颜色,结合从网上找到的一些资料进行修改. 1.使用Raphael自带的箭头样式,代码与箭头的样式对应如下: var c = r.path( ...

  2. Raphael绘制流程图(一),添加可拖动的图形

    原项目使用的Raphael绘制流程图,要求能自定义箭头的样式和颜色,结合从网上找到的一些资料进行修改. 1.jquery或javascript代码 var wf_r = null; //画板对象 va ...

  3. Android Canvas绘制带箭头的直线

    先看下效果图: 下面我们直接看代码 我自定义了一个View,代码如下: package com.davis.drawtrangle;import android.content.Context; im ...

  4. Matlab任意两点之间绘制带箭头的直线

    Matlab任意两点之间绘制带箭头的直线 简单绘制任意两点之间.本来不想自己写的,可是网上的代码用起来不舒服,所以简单看看原理,原来就是个坐标变换而已.索性自己写了一份,分享如下: function ...

  5. CAD里面怎么画带箭头的直线

    转自:http://jingyan.baidu.com/article/9113f81b0192e72b3214c709.html?st=2&os=0&bd_page_type=1&a ...

  6. 【MFC】如何画带箭头的直线

    [MFC]如何画带箭头的直线 前言 代码 获得箭头坐标 前言 如何绘制带箭头的直线,说来也简单,只需要算出箭头左右两边的坐标,再使用LineTo()函数即可.话不多说上代码. 代码 获得箭头坐标 已知 ...

  7. MFC画带箭头的直线

    构造一个函数,是在startPoint,endPoint间画一条带箭头的线段: void CTry1View::DrawLine(POINT startPoint, POINT endPoint) { ...

  8. 关于google地图api3的离线和在线开发(画带箭头的直线,指定范围,搜索,计算距离)

    最近因为开发的需要,要做一个离线的google地图.并且能够加载google地图的一些特效.例如:地图的标记,计算距离,获取标记的经纬度,画带有箭头的直线,获取指定范围的数据等等.在这里我总结了很多开 ...

  9. 关于利用canvas画带箭头的直线旋转

    利用canvas在Vue项目中使用: <imgid="range_right"src=""style="position: absolute;l ...

最新文章

  1. 文件系统写入100G文件需要多久
  2. JDBC(二)——使用IDEA连接数据库、数据库连接池
  3. 史上最全PHP正则表达式实例汇总
  4. monogdb操作system.*权限
  5. python pdf转txt保留全部信息_Python 将pdf转换成txt(不处理图片)
  6. 软考网络工程师笔记-综合知识2
  7. instagram架构_通过创建Instagram副本学习Laravel
  8. word中添加mathtype
  9. 怎么做数据可视化大屏?从设计到上线,一般用这3类工具
  10. 如何操作反射中构造方法、属性和普通方法?
  11. circNet:人类环状RNA数据库
  12. 网管员常用工具(二)
  13. Alphapose_pytorch版本环境配置Win10
  14. 激光传感器构建栅格地图
  15. 爬虫之-bilibili视频下载-下载链接获取
  16. 美国人日常生活中常用的五星级句子
  17. 生病还要被压榨,外包太惨了!
  18. 网易企业邮箱技术剖析
  19. 使用阿里云消息服务mns发送短信
  20. 国富论(英语:The Wealth of Nations)

热门文章

  1. 多部电梯具有联动性的测试用例
  2. Windows磁盘管理工具Diskpart之一 管理基本磁盘
  3. 翻译——奇偶校验矩阵和低密度奇偶校验码的构造方法
  4. Layui前端判断,Date()函数时间戳转换
  5. linux搭建交换机日志,搭建属于自己的syslog日志服务器
  6. 俄罗斯盗版软件将被合法化:最大破解资源网站宣布解封,数十万盗版资源解禁...
  7. WordCount操作步骤
  8. IDC运维如何转linux运维,智简魔方DCIM系统助力IDC运维人员解决难题
  9. [IT 男人帮 -10/31] 雨林木风CEO赖霖枫: 互联网冬天前的思考
  10. 道路车辆 盲区监测(bsd)系统性能要求及试验方法_让你的爱车“多一双眼睛”——BSD盲点监测系统...