0

我正在创建一个模块来使用 raphael 以图形方式可视化工作流程,该模块从数据库中获取数据。为此,我创建了一个名为“FlowEdit”的类,并根据 raphael 创建了移动、向上和拖动功能。

但是在移动功能中,当我尝试使用对象引用访问连接列表时,我无法引用它,它给出了未定义的错误。

该课程的代码是这样的:-

        //class definition
        function FlowView(list) {
        this.list = list;
        this.connections = [];
        this.r = Raphael("holder", 1400, 500);
        this.shapes = [];
        this.texts = [];
        this.y_center = 500 / 2;
        //box size
        this.r_width = 60;
        this.r_height = 40;
        // To define virtual regions
        this.x_offset = 50;
        this.y_offset = 40;
        this.x_start = 40;
        //this.color, this.tempS, this.tempT;
        //Define position in y direction
        this.top_count = [0];
        this.bottom_count = [0];
        //Initialize Top_count & Bottom_Count Arrays
        for (var i = 0; i < this.list.length; i++) {
            this.top_count.push(0);
            this.bottom_count.push(0);
        }
    }
    ;

    // Give starting points from list
    FlowView.prototype.start_point = function () {
        var start_list = [];
        for (var i in this.list) {
            if (this.list[i][1] == this.list[i][2][0]) {
                start_list.push(this.list[i][1]);
            }
        }
        return start_list;
    };

    //For Finding index of an element in list
    FlowView.prototype.index_of = function (curr_point) {
        for (var i in this.list) {
            if (this.list[i][1] == curr_point) {
                return i;
            }
        }
    };

    //add next function
    FlowView.prototype.add_next = function () {
        for (var i in this.list) {
            if (this.list[i][3][0] == "NULL") {
                //For all last nodes add same to their next
                this.list[i][3][0] = this.list[i][1];
            }
            if (this.list[i][3].length == 0) {
                //For all last nodes add same to their next
                this.list[i][3].push(this.list[i][1]);
            }
        }
    };

    //For given next of all nodes add previous to those nodes
    FlowView.prototype.add_previous = function () {
        for (var i in this.list) {
            for (var j in this.list[i][3]) {
                //For all next add current node to their previous list
                var curr_index = this.index_of(this.list[i][3][j]);
                if (this.list[curr_index][2].indexOf(this.list[i][1]) == -1 && (curr_index != i)) {
                    this.list[curr_index][2].push(this.list[i][1]);
                }
            }
        }
        //Add previous of all start node
        for (var i in this.list) {
            if (this.list[i][2].length == 0) {
                this.list[i][2].push(this.list[i][1]);
            }
        }
    };


    //Region update recursively
    FlowView.prototype.region_update = function (curr_index) {
        if (this.list[curr_index][1] != this.list[curr_index][3][0]) {
            for (var i in this.list[curr_index][3]) {
                var next_index = this.index_of(this.list[curr_index][3][i]);
                if (this.list[next_index][0] < this.list[curr_index][0] + 1) {
                    this.list[next_index][0] = this.list[curr_index][0] + 1;
                    this.region_update(next_index);
                }
            }
        }
    };

    //Draw the workflow for given data structure
    FlowView.prototype.construct = function () {
        var open = this.start_point();
        var close = [];

        while (open.length != 0) {
            var curr_point = open.shift();
            var curr_index = this.index_of(curr_point);
            //document.write(curr_index);
            //draw box
            var curr_region = this.list[curr_index][0];
            //document.write(curr_region);
            var x_cord = parseInt(curr_region) * (this.x_offset + this.r_width) + this.x_start;
            //document.write(x_start);
            var y_cord = 0;

            if (this.top_count[curr_region] == 0 && this.bottom_count[curr_region] == 0) {
                y_cord = this.y_center - this.r_height / 2;
                this.top_count[curr_region] = 1;
                this.bottom_count[curr_region] = 1;
            }
            else if (this.top_count[curr_region] <= this.bottom_count[curr_region]) {
                y_cord = this.y_center - this.r_height / 2 - this.top_count[curr_region] * (this.y_offset + this.r_height);
                this.top_count[curr_region] = this.top_count[curr_region] + 1;
            }
            else {
                y_cord = this.y_center + this.r_height / 2 + this.bottom_count[curr_region] * (this.y_offset + this.r_height) - this.r_height;
                this.bottom_count[curr_region] = this.bottom_count[curr_region] + 1;
            }

            //drawing the box
            this.shapes[this.list[curr_index][1]] = this.r.rect(x_cord, y_cord, this.r_width, this.r_height, 10);
            this.texts[this.list[curr_index][1]] = this.r.text(x_cord + this.r_width / 2, y_cord + this.r_height / 2, this.list[curr_index][1]);
            // Adding next nodes to open list
            for (var i in this.list[curr_index][3]) {
                //If not in open than add to open
                if (this.list[curr_index][3][0] != this.list[curr_index][1]) {
                    if (open.indexOf(this.list[curr_index][3][i]) == -1 && close.indexOf(this.list[curr_index][3][i]) == -1) {
                        open.push(this.list[curr_index][3][i]);
                    }
                }
            }
            //Increasing region index for each next node
            this.region_update(curr_index);
            close.push(curr_point);
            //document.write(open.toString()+"</br>");
            //document.write(close.toString()+"</br>");
        }
        for (var j in this.list) {
            if (this.list[j][1] != this.list[j][3][0]) {
                for (var i in this.list[j][3]) {
                    //make link for each previous
                    if (close.indexOf(this.list[j][3][i]) != -1) {
                                 this.connections.push(this.r.connection(this.shapes[this.list[j][1]], this.shapes[this.list[j][3][i]], "bcd"));
                    }
                }
            }
        }
    };

    FlowView.prototype.dragger = function () {
        // Original cords for main element
        this.ox = this.type == "ellipse" ? this.attr("cx") : this.attr("x");
        this.oy = this.type == "ellipse" ? this.attr("cy") : this.attr("y");
        if (this.type != "text") this.animate({"fill-opacity":.2}, 500);

        // Original co-ords for pair element
        this.pair.ox = this.pair.type == "ellipse" ? this.pair.attr("cx") : this.pair.attr("x");
        this.pair.oy = this.pair.type == "ellipse" ? this.pair.attr("cy") : this.pair.attr("y");
        if (this.pair.type != "text") this.pair.animate({"fill-opacity":.2}, 500);
    };

    FlowView.prototype.move = function (dx, dy) {
        // Move main element
        var att = this.type == "ellipse" ? {cx:this.ox + dx, cy:this.oy + dy} :
        {x:this.ox + dx, y:this.oy + dy};
        this.attr(att);
        // Move paired element
        att = this.pair.type == "ellipse" ? {cx:this.pair.ox + dx, cy:this.pair.oy + dy} :
        {x:this.pair.ox + dx, y:this.pair.oy + dy};
        this.pair.attr(att);
        //document.write("adass");
        //document.write(x_offset);
        // Move connections
        for (var i = this.connections.length; i--;) {
             this.r.connection(this.connections[i]);
        }
        this.r.safari();
    };


    FlowView.prototype.up = function () {
        // Fade original element on mouse up
        if (this.type != "text") this.animate({"fill-opacity":0}, 500);

        // Fade paired element on mouse up
        if (this.pair.type != "text") this.pair.animate({"fill-opacity":0}, 500);
        // Move connections
    };


    FlowView.prototype.drag_initialize = function () {

        for (var i in this.shapes) {
            var color = Raphael.getColor();
            var tempS = this.shapes[i].attr({fill:color, stroke:color, "fill-opacity":0, "stroke-width":2, cursor:"move"});
            var tempT = this.texts[i].attr({fill:color, stroke:"none", "font-size":15, cursor:"move"});
            this.shapes[i].drag(this.move, this.dragger, this.up);
            this.texts[i].drag(this.move, this.dragger, this.up);

            // Associate the elements
            tempS.pair = tempT;
            tempT.pair = tempS;
        }
    };

使用上面的代码,我可以绘制图形并拖动项目,但是当我拖动项目时,连接的路径不会沿着它拖动。所以我做错了。为了建立连接,我使用了 raphael 演示中给出的相同代码..

4

2 回答 2

0

这是一个常见的烦恼,幸运的是,有一个非常简单的解决方案!

问题:Raphael 正在使用您指定的函数(this.move、this.dragger 和 this.up),但它没有在对象的上下文中调用它们。因此,this 变量实际上不是指您的对象,而是指窗口。绝对没有帮助。

解决方案:使用函数闭包来绑定对对象实例的引用。用这个更新你的 drag_initialize 函数:

var self = this;
this.shapes[i].drag(function(){ self.move(); }, function() { self.dragger(); }, function() { self.up(); } );
this.texts[i].drag(function() { self.move(); }, function() { self.dragger(); }, function() { self.up(); } );
于 2012-06-20T16:41:10.740 回答
0

嗨,我找到了问题的答案。在移动函数中,我返回另一个函数,在调用拖动时,我在移动函数中给出对象参数,因此传递了当前对象的上下文。现在更改的移动功能是:-

    FlowView.prototype.move = function (obj) {

        // Move main element
        return function(dx, dy){
            var att = this.type == "ellipse" ? {cx:this.ox + dx, cy:this.oy + dy} :
            {x:this.ox + dx, y:this.oy + dy};
            this.attr(att);
            // Move paired element
            att = this.pair.type == "ellipse" ? {cx:this.pair.ox + dx, cy:this.pair.oy + dy} :
            {x:this.pair.ox + dx, y:this.pair.oy + dy};
            this.pair.attr(att);
            // Move connections
            for (var i = obj.connections.length; i--;) {
                obj.r.connection(obj.connections[i]);
            }
            obj.r.safari();
        }
    };

并用

    this.shapes[i].drag(this.move(this), this.dragger, this.up);
    this.texts[i].drag(this.move(this), this.dragger, this.up);
于 2012-06-21T11:37:47.050 回答