Skip to content
jtopo-0.4.8-dev.js 158 KiB
Newer Older
wangqinghua's avatar
wangqinghua committed
/**
 * 修改:
 * 1. 扩展对图片base64的支持
 */
!
    function (window) {
        function Element() {
            this.initialize = function () {
                this.elementType = "element", this.serializedProperties = ["elementType", "id"], this.propertiesStack = [], this.id = ""
            }, this.distroy = function () {
            }, this.removeHandler = function () {
            }, this.attr = function (a, b) {
                if (null != a && null != b) this[a] = b;
                else if (null != a) return this[a];
                return this
            }, this.save = function () {
                var a = this,
                    b = {};
                this.serializedProperties.forEach(function (c) {
                    b[c] = a[c]
                }), this.propertiesStack.push(b)
            }, this.restore = function () {
                if (null != this.propertiesStack && 0 != this.propertiesStack.length) {
                    var a = this,
                        b = this.propertiesStack.pop();
                    this.save();
                    this.serializedProperties.forEach(function (c) {
                        a[c] = b[c]
                    })
                }
            }, this.toJson = function () {
                var a = this,
                    b = "{",
                    c = this.serializedProperties.length;
                return this.serializedProperties.forEach(function (d, e) {
                    var f = a[d];
                    // xwenyuan修改,在源码层做反序列化保护,防undefined
                    // todo...这里如果是未定义,统一置为'',需要验证有没有必要置为对应变量类型的默认值
                    if (typeof f == "undefined") {
                        f = ""
                    }
                    // xwenyuan修改,element的参数支持json对象
                    // todo...typeof有六种可能:"number"、"string"、"boolean"、"object"、"function"、"undefined".逐一验证
                    if (typeof f == "number") {
                        if (d == "width" || d == "height") {
                            f = Math.round(f);
                        } else {
                            f = Math.round(f * 100) / 100;
                        }
                        b += '"' + d + '":' + f
                    } else if (typeof f == "string") {
                        b += '"' + d + '":' + '"' + f + '"'
                    } else if (typeof f == "object") {
                        b = b + '"' + d + '":' + JSON.stringify(f)
                    } else {
                        b += '"' + d + '":' + f
                    }
                    if (c > e + 1) {
                        b += ","
                    }
                }), b += "}"
            }
        }

        CanvasRenderingContext2D.prototype.JTopoRoundRect = function (a, b, c, d, e) {
            "undefined" == typeof e && (e = 5), this.beginPath(), this.moveTo(a + e, b), this.lineTo(a + c - e, b), this.quadraticCurveTo(a + c, b, a + c, b + e), this.lineTo(a + c, b + d - e), this.quadraticCurveTo(a + c, b + d, a + c - e, b + d), this.lineTo(a + e, b + d), this.quadraticCurveTo(a, b + d, a, b + d - e), this.lineTo(a, b + e), this.quadraticCurveTo(a, b, a + e, b), this.closePath()
        }, CanvasRenderingContext2D.prototype.JTopoDashedLineTo = function (a, b, c, d, e) {
            "undefined" == typeof e && (e = 5);
            var f = c - a,
                g = d - b,
                h = Math.floor(Math.sqrt(f * f + g * g)),
                i = 0 >= e ? h : h / e,
                j = g / h * e,
                k = f / h * e;
            this.beginPath();
            for (var l = 0; i > l; l++) l % 2 ? this.lineTo(a + l * k, b + l * j) : this.moveTo(a + l * k, b + l * j);
            this.stroke()
        }, JTopo = {
            version: "0.4.8",
            zIndex_Container: 1,
            zIndex_Link: 2,
            zIndex_Node: 3,
            SceneMode: {
                normal: "normal",
                drag: "drag",
                edit: "edit",
                select: "select"
            },
            MouseCursor: {
                normal: "default",
                pointer: "pointer",
                top_left: "nw-resize",
                top_center: "n-resize",
                top_right: "ne-resize",
                middle_left: "e-resize",
                middle_right: "e-resize",
                bottom_left: "ne-resize",
                bottom_center: "n-resize",
                bottom_right: "nw-resize",
                move: "move",
                open_hand: " 8 8, default",
                closed_hand: " 8 8, default"
            },
            replaceStageWithJson: function (jsonObj) {
                var stage = editor.stage;
                for (var k in jsonObj) {
                    if ("childs" != k) {
                        stage[k] = jsonObj[k];
                        if (k == "deviceNum" || k == "wheelZoom" || k == "frames" || k == "height" || k == "width") {
                            stage[k] = parseFloat(stage[k]);
                        }
                    }
                }
                var scenes = jsonObj.childs;
                stage.childs.forEach(function (s) {
                    s.clear();
                });
                return scenes.forEach(function (a) {
                    var b = editor.scene;
                    b.paintAll = false;
                    b.areaSelect = true;
                    b.translate = true;
                    b.lastTranslatedX = undefined;
                    b.lastTranslatedY = undefined;
                    b.visible = true
                    for (var c in a) {
                        if ("childs" != c) {
                            if (a[c] == "undefined") {
                                b[c] = undefined
                            } else if (c == "translateX" || c == "translateY" || c == "scaleX" || c == "scaleY") {
                                b[c] = parseFloat(a[c]);
                            } else {
                                b[c] = a[c];
                            }

                        }
                    }
                    var d = a.childs;
                    d.forEach(function (a) {
                        var c = null, d = a.elementType;
                        if ("node" == d) {
                            c = new JTopo.Node;
                            c.alpha = editor.config.nodeAlpha;
wangqinghua's avatar
wangqinghua committed
                            c.hostId = editor.config.hostId;
wangqinghua's avatar
wangqinghua committed
                            c.itemId = editor.config.itemId;
wangqinghua's avatar
wangqinghua committed
                            c.strokeColor = editor.config.nodeStrokeColor;
                            c.fillColor = editor.config.nodeFillColor;
                            c.shadow = editor.config.nodeShadow;
                            c.shadowColor = editor.config.nodeShadowColor;
                            c.font = editor.config.nodeFont;
                            c.fontColor = editor.config.nodeFontColor;
                            c.borderRadius = null;
                            c.shadowOffsetX = editor.config.shadowOffsetX;
                            c.shadowOffsetY = editor.config.shadowOffsetY;
                            c.transformAble = true;
                            c.visible = true;
                            c.dragable = true;
                            c.selected = false;
                            c.showSelected = true;
                            c.isMouseOver = false
                        } else if ("CircleNode" == d) {
                            c = new JTopo.CircleNode;
                        } else if ("link" == d) {
                            return false;
                        } else if ("container" == d) {
                            return false;
                        }
                        for (var e in a) {
                            // 加载节点的图片
                            if (e == "nodeImage") {
wangqinghua's avatar
wangqinghua committed
                                c.setImage( a[e]);
wangqinghua's avatar
wangqinghua committed
                            }
                            if (c) {
                                if (a[e] == "undefined") {
                                    c[e] = undefined;
                                    continue;
                                } else if (e == "rotate" || e == "scaleX" || e == "scaleY" || e == "zIndex" || e == "x" || e == "y"
                                    || e == "width" || e == "height") {
                                    c[e] = parseFloat(a[e]);
                                } else {
                                    c[e] = a[e];
                                }
                            }
                        }
                        if (c)
                            b.add(c);
                    });

                    // 遍历连线上的起始节点
                    var nodes = b.getAllNodes();
                    d.forEach(function (a) {
                        var c = null, d = a.elementType;
                        if ("link" != d && "container" != d) {
                            return false;
                        }
                        if ("link" == d) {
                            var nodeA, nodeZ;
                            // 找出连接点
                            if (a["nodeSrc"] && a["nodeDst"]) {
                                nodes.forEach(function (nodeEle) {
                                    if (nodeEle.elementType == "node") {
                                        if (nodeEle.nodeId == a["nodeSrc"])
                                            nodeA = nodeEle;
                                        if (nodeEle.nodeId == a["nodeDst"])
                                            nodeZ = nodeEle;
                                    }
                                });
                            }

                            if (nodeA && nodeZ) {    // 折线和直线绘制
                                if (a["lineType"] == "line") {
                                    c = new JTopo.Link(nodeA, nodeZ);
                                }
                                if (a["lineType"] == "foldLine") {
                                    c = new JTopo.FoldLink(nodeA, nodeZ);
                                    c.bundleOffset = editor.config.linkOffsetGap;
                                }
                                if (a["lineType"] == "flexLine") {
                                    c = new JTopo.FlexionalLink(nodeA, nodeZ);
                                    c.offsetGap = editor.config.linkOffsetGap;
                                }
                                if (a["lineType"] == "curveLine") {
                                    c = new JTopo.CurveLink(nodeA, nodeZ);
                                }
                                c.alpha = editor.config.linkAlpha;
wangqinghua's avatar
wangqinghua committed
                                c.itemId = editor.config.itemId;
wangqinghua's avatar
wangqinghua committed
                                c.strokeColor = editor.config.linkStrokeColor;
                                c.fillColor = editor.config.linkFillColor;
                                c.shadow = editor.config.linkShadow;
                                c.shadowColor = editor.config.linkShadowColor;
                                c.font = editor.config.linkFont;
                                c.fontColor = editor.config.linkFontColor;
                                c.arrowsRadius = editor.config.linkArrowsRadius;
                                c.lineWidth = editor.config.linkDefaultWidth;
                                c.shadowOffsetX = editor.config.shadowOffsetX;
                                c.shadowOffsetY = editor.config.shadowOffsetY;
                            }
                        } else if ("container" == d) {
                            if (a["childNodes"]) {
                                var temp = a["childNodes"].split(",");
                                if (temp && temp.length > 0) {
                                    c = new JTopo.Container();
                                    c.alpha = editor.config.containerAlpha;
wangqinghua's avatar
wangqinghua committed
                                    c.itemId = editor.config.itemId;
wangqinghua's avatar
wangqinghua committed
                                    c.strokeColor = editor.config.containerStrokeColor;
                                    c.fillColor = editor.config.containerFillColor;
                                    c.shadow = editor.config.containerShadow;
                                    c.shadowColor = editor.config.containerShadowColor;
                                    c.font = editor.config.containerFont;
                                    c.fontColor = editor.config.containerFontColor;
                                    c.borderColor = editor.config.containerBorderColor;
                                    c.borderRadius = editor.config.containerBorderRadius;
                                    c.shadowOffsetX = editor.config.shadowOffsetX;
                                    c.shadowOffsetY = editor.config.shadowOffsetY;
                                    for (var ni = 0; ni < temp.length; ni++) {
                                        b.childs.forEach(function (n) {
                                            if (n instanceof JTopo.Node && n.nodeId == temp[ni]) {
                                                c.add(n);
                                            }
                                        });
                                    }
                                }
                            }
                        }

                        for (var e in a) {
                            if (c) {
                                if (a[e] == "undefined") {
                                    c[e] = undefined;
                                } else if (e == "rotate" || e == "scaleX" || e == "scaleY" || e == "zIndex" || e == "x" || e == "y"
                                    || e == "width" || e == "height") {
                                    c[e] = parseFloat(a[e]);
                                } else {
                                    c[e] = a[e];
                                }
                            }
                        }
                        if (c)
                            b.add(c);
                    })
                })
            },
            createStageFromJson: function (jsonObj, canvas) {
                // eval("var jsonObj = " + jsonStr);
                // editor.modeIdIndex = jsonObj.deviceNum;
                var stage = new JTopo.Stage(canvas);
                for (var k in jsonObj) {
                    if ("childs" != k) {
                        stage[k] = jsonObj[k];
                        // if (k == "deviceNum" || k == "wheelZoom" || k == "frames" || k == "height" || k == "width") {
                        //     stage[k] = parseFloat(stage[k]);
                        // }
                    }
                }
                var scenes = jsonObj.childs;
                return scenes.forEach(function (a) {
                    var b = new JTopo.Scene(stage);
                    b.paintAll = false;
                    b.areaSelect = true;
                    b.translate = true;
                    b.lastTranslatedX = undefined;
                    b.lastTranslatedY = undefined;
                    b.visible = true;
                    for (var c in a) {
                        if ("childs" != c) {
                            if (a[c] == "undefined") {
                                b[c] = undefined
                            } else if (c == "translateX" || c == "translateY" || c == "scaleX" || c == "scaleY") {
                                b[c] = parseFloat(a[c]);
                            } else {
                                b[c] = a[c];
                            }

                        }
                    }
                    var d = a.childs;
                    d.forEach(function (a) {
                        var c = null, d = a.elementType;
                        if ("node" == d) {
                            c = new JTopo.Node;
                            c.alpha = editor.config.nodeAlpha;
wangqinghua's avatar
wangqinghua committed
                            c.hostId = editor.config.hostId;
wangqinghua's avatar
wangqinghua committed
                            c.itemId = editor.config.itemId;
wangqinghua's avatar
wangqinghua committed
                            c.strokeColor = editor.config.nodeStrokeColor;
                            c.fillColor = editor.config.nodeFillColor;
                            c.shadow = editor.config.nodeShadow;
                            c.shadowColor = editor.config.nodeShadowColor;
                            c.font = editor.config.nodeFont;
                            c.fontColor = editor.config.nodeFontColor;
                            c.borderRadius = null;
                            c.shadowOffsetX = editor.config.shadowOffsetX;
                            c.shadowOffsetY = editor.config.shadowOffsetY;
                            c.transformAble = true;
                            c.visible = true;
                            c.dragable = true;
                            c.selected = false;
                            c.showSelected = true;
                            c.isMouseOver = false
                        } else if ("CircleNode" == d) {
                            c = new JTopo.CircleNode;
                        } else if ("link" == d) {
                            return false;
                        } else if ("container" == d) {
                            return false;
                        }
                        for (var e in a) {
                            // 加载节点的图片
                            if (e == "nodeImage") {
wangqinghua's avatar
wangqinghua committed
                                c.setImage(a[e]);
wangqinghua's avatar
wangqinghua committed
                            }
                            if (c) {
                                if (a[e] == "undefined") {
                                    c[e] = undefined;
                                    continue;
                                } else if (e == "rotate" || e == "scaleX" || e == "scaleY" || e == "zIndex" || e == "x" || e == "y"
                                    || e == "width" || e == "height") {
                                    c[e] = parseFloat(a[e]);
                                } else {
                                    c[e] = a[e];
                                }
                            }
                        }
                        if (c)
                            b.add(c);
                    });

                    // 遍历连线上的起始节点
                    var nodes = b.getAllNodes();
                    d.forEach(function (a) {
                        var c = null, d = a.elementType;
                        if ("link" != d && "container" != d) {
                            return false;
                        }
                        if ("link" == d) {
                            var nodeA, nodeZ;
                            // 找出连接点
                            if (a["nodeSrc"] && a["nodeDst"]) {
                                nodes.forEach(function (nodeEle) {
                                    if (nodeEle.elementType == "node") {
                                        if (nodeEle.nodeId == a["nodeSrc"])
                                            nodeA = nodeEle;
                                        if (nodeEle.nodeId == a["nodeDst"])
                                            nodeZ = nodeEle;
                                    }
                                });
                            }

                            if (nodeA && nodeZ) {    // 折线和直线绘制
                                if (a["lineType"] == "line")
                                    c = new JTopo.Link(nodeA, nodeZ);
                                if (a["lineType"] == "foldLine") {
                                    c = new JTopo.FoldLink(nodeA, nodeZ);
                                    c.bundleOffset = editor.config.linkOffsetGap;
                                }
                                if (a["lineType"] == "flexLine") {
                                    c = new JTopo.FlexionalLink(nodeA, nodeZ);
                                    c.offsetGap = editor.config.linkOffsetGap;
                                }
                                if (a["lineType"] == "curveLine") {
                                    c = new JTopo.CurveLink(nodeA, nodeZ);
                                }
                                c.alpha = editor.config.linkAlpha;
wangqinghua's avatar
wangqinghua committed
                                c.itemId = editor.config.itemId;
wangqinghua's avatar
wangqinghua committed
                                c.strokeColor = editor.config.linkStrokeColor;
                                c.fillColor = editor.config.linkFillColor;
                                c.shadow = editor.config.linkShadow;
                                c.shadowColor = editor.config.linkShadowColor;
                                c.font = editor.config.linkFont;
                                c.fontColor = editor.config.linkFontColor;
                                c.arrowsRadius = editor.config.linkArrowsRadius;
                                c.lineWidth = editor.config.linkDefaultWidth;
                                c.shadowOffsetX = editor.config.shadowOffsetX;
                                c.shadowOffsetY = editor.config.shadowOffsetY;
                            }
                        } else if ("container" == d) {
                            if (a["childNodes"]) {
                                var temp = a["childNodes"].split(",");
                                if (temp && temp.length > 0) {
                                    c = new JTopo.Container();
                                    c.alpha = editor.config.containerAlpha;
wangqinghua's avatar
wangqinghua committed
                                    c.itemId = editor.config.itemId;
wangqinghua's avatar
wangqinghua committed
                                    c.strokeColor = editor.config.containerStrokeColor;
                                    c.fillColor = editor.config.containerFillColor;
                                    c.shadow = editor.config.containerShadow;
                                    c.shadowColor = editor.config.containerShadowColor;
                                    c.font = editor.config.containerFont;
                                    c.fontColor = editor.config.containerFontColor;
                                    c.borderColor = editor.config.containerBorderColor;
                                    c.borderRadius = editor.config.containerBorderRadius;
                                    c.shadowOffsetX = editor.config.shadowOffsetX;
                                    c.shadowOffsetY = editor.config.shadowOffsetY;
                                    for (var ni = 0; ni < temp.length; ni++) {
                                        b.childs.forEach(function (n) {
                                            if (n instanceof JTopo.Node && n.nodeId == temp[ni]) {
                                                c.add(n);
                                            }
                                        });
                                    }
                                }
                            }
                        }

                        for (var e in a) {
                            if (c) {
                                if (a[e] == "undefined") {
                                    c[e] = undefined;
                                } else if (e == "rotate" || e == "scaleX" || e == "scaleY" || e == "zIndex" || e == "x" || e == "y"
                                    || e == "width" || e == "height") {
                                    c[e] = parseFloat(a[e]);
                                } else {
                                    c[e] = a[e];
                                }
                            }
                        }
                        if (c)
                            b.add(c);
                    })
                }), stage;
            }
        }, JTopo.Element = Element, window.JTopo = JTopo
    }(window),

    function (JTopo) {
        function MessageBus(messageName) {
            var b = this;
            this.name = messageName, this.messageMap = {}, this.messageCount = 0, this.subscribe = function (eventType, eventHandel) {
                var d = b.messageMap[eventType];
                null == d && (b.messageMap[eventType] = []), b.messageMap[eventType].push(eventHandel), b.messageCount++
            }, this.unsubscribe = function (eventType) {
                var c = b.messageMap[eventType];
                null != c && (b.messageMap[eventType] = null, delete b.messageMap[eventType], b.messageCount--)
            }, this.publish = function (eventType, event, delay) {
                var e = b.messageMap[eventType];
                if (null != e) for (var f = 0; f < e.length; f++) delay ? !
                    function (a, b) {
                        setTimeout(function () {
                            a(b)
                        }, 10)
                    }(e[f], event) : e[f](event)
            }
        }

        function getDistance(a, b, c, d) {
            var e, f;
            return null == c && null == d ? (e = b.x - a.x, f = b.y - a.y) : (e = c - a, f = d - b), Math.sqrt(e * e + f * f)
        }

        function getElementsBound(a) {
            for (var b = {
                left: Number.MAX_VALUE,
                right: Number.MIN_VALUE,
                top: Number.MAX_VALUE,
                bottom: Number.MIN_VALUE
            }, c = 0; c < a.length; c++) {
                var d = a[c];
                d instanceof JTopo.Link || (b.left > d.x && (b.left = d.x, b.leftNode = d), b.right < d.x + d.width && (b.right = d.x + d.width, b.rightNode = d), b.top > d.y && (b.top = d.y, b.topNode = d), b.bottom < d.y + d.height && (b.bottom = d.y + d.height, b.bottomNode = d))
            }
            return b.width = b.right - b.left, b.height = b.bottom - b.top, b
        }

        function mouseCoords(a) {
            return a = cloneEvent(a), a.pageX || (a.pageX = a.clientX + document.body.scrollLeft - document.body.clientLeft, a.pageY = a.clientY + document.body.scrollTop - document.body.clientTop), a
        }

        function getEventPosition(a) {
            return a = mouseCoords(a)
        }

        function rotatePoint(a, b, c, d, e) {
            var f = c - a,
                g = d - b,
                h = Math.sqrt(f * f + g * g),
                i = Math.atan2(g, f) + e;
            return {
                x: a + Math.cos(i) * h,
                y: b + Math.sin(i) * h
            }
        }

        function rotatePoints(a, b, c) {
            for (var d = [], e = 0; e < b.length; e++) {
                var f = rotatePoint(a.x, a.y, b[e].x, b[e].y, c);
                d.push(f)
            }
            return d
        }

        function $foreach(a, b, c) {
            function d(e) {
                e != a.length && (b(a[e]), setTimeout(function () {
                    d(++e)
                }, c))
            }

            if (0 != a.length) {
                var e = 0;
                d(e)
            }
        }

        function $for(a, b, c, d) {
            function e(a) {
                a != b && (c(b), setTimeout(function () {
                    e(++a)
                }, d))
            }

            if (!(a > b)) {
                var f = 0;
                e(f)
            }
        }

        function cloneEvent(a) {
            var b = {};
            for (var c in a) "returnValue" != c && "keyLocation" != c && (b[c] = a[c]);
            return b
        }

        function clone(a) {
            var b = {};
            for (var c in a) b[c] = a[c];
            return b
        }

        function isPointInRect(a, b) {
            var c = b.x,
                d = b.y,
                e = b.width,
                f = b.height;
            return a.x > c && a.x < c + e && a.y > d && a.y < d + f
        }

        function isPointInLine(a, b, c) {
            var d = JTopo.util.getDistance(b, c),
                e = JTopo.util.getDistance(b, a),
                f = JTopo.util.getDistance(c, a),
                g = Math.abs(e + f - d) <= .5;
            return g
        }

        function removeFromArray(a, b) {
            for (var c = 0; c < a.length; c++) {
                var d = a[c];
                if (d === b) {
                    a = a.del(c);
                    break
                }
            }
            return a
        }

        function randomColor() {
            return Math.floor(255 * Math.random()) + "," + Math.floor(255 * Math.random()) + "," + Math.floor(255 * Math.random())
        }

        function isIntsect() {
        }

        function getProperties(a, b) {
            for (var c = "", d = 0; d < b.length; d++) {
                d > 0 && (c += ",");
                var e = a[b[d]];
                "string" == typeof e ? e = '"' + e + '"' : void 0 == e && (e = null), c += b[d] + ":" + e
            }
            return c
        }

        function loadStageFromJson(json, canvas) {
            var obj = eval(json),
                stage = new JTopo.Stage(canvas);
            for (var k in stageObj) if ("scenes" != k) stage[k] = obj[k];
            else for (var scenes = obj.scenes, i = 0; i < scenes.length; i++) {
                    var sceneObj = scenes[i],
                        scene = new JTopo.Scene(stage);
                    for (var p in sceneObj) if ("elements" != p) scene[p] = sceneObj[p];
                    else for (var nodeMap = {}, elements = sceneObj.elements, m = 0; m < elements.length; m++) {
                            var elementObj = elements[m],
                                type = elementObj.elementType,
                                element;
                            "Node" == type && (element = new JTopo.Node);
                            for (var mk in elementObj) element[mk] = elementObj[mk];
                            nodeMap[element.text] = element, scene.add(element)
                        }
                }
            return console.log(stage), stage
        }

        function toJson(a) {
            var b = "backgroundColor,visible,mode,rotate,alpha,scaleX,scaleY,shadow,translateX,translateY,areaSelect,paintAll".split(","),
wangqinghua's avatar
wangqinghua committed
                c = "text,hostId,elementType,x,y,width,height,visible,alpha,rotate,scaleX,scaleY,fillColor,shadow,transformAble,zIndex,dragable,selected,showSelected,font,fontColor,textPosition,textOffsetX,textOffsetY".split(","),
wangqinghua's avatar
wangqinghua committed
                d = "{";
            d += "frames:" + a.frames, d += ", scenes:[";
            for (var e = 0; e < a.childs.length; e++) {
                var f = a.childs[e];
                d += "{", d += getProperties(f, b), d += ", elements:[";
                for (var g = 0; g < f.childs.length; g++) {
                    var h = f.childs[g];
                    g > 0 && (d += ","), d += "{", d += getProperties(h, c), d += "}"
                }
                d += "]}"
            }
            return d += "]", d += "}"
        }

        function changeColor(a, b, c, d, e) {
            var f = canvas.width = b.width,
                g = canvas.height = b.height;
            a.clearRect(0, 0, canvas.width, canvas.height), a.drawImage(b, 0, 0);
            for (var h = a.getImageData(0, 0, b.width, b.height), i = h.data, j = 0; f > j; j++) for (var k = 0; g > k; k++) {
                var l = 4 * (j + k * f);
                0 != i[l + 3] && (null != c && (i[l + 0] += c), null != d && (i[l + 1] += d), null != e && (i[l + 2] += e))
            }
            a.putImageData(h, 0, 0, 0, 0, b.width, b.height);
            var m = canvas.toDataURL();
            return alarmImageCache[b.src] = m, m
        }

        function genImageAlarm(a, b) {
            null == b && (b = 255);
            try {
                if (alarmImageCache[a.src]) return alarmImageCache[a.src];
                var c = new Image;
                return c.src = changeColor(graphics, a, b), alarmImageCache[a.src] = c, c
wangqinghua's avatar
wangqinghua committed
            } catch (d) {
            }
wangqinghua's avatar
wangqinghua committed
            return null
        }

        function getOffsetPosition(a) {
            if (!a) return {
                left: 0,
                top: 0
            };
            var b = 0,
                c = 0;
            if ("getBoundingClientRect" in document.documentElement) var d = a.getBoundingClientRect(),
                e = a.ownerDocument,
                f = e.body,
                g = e.documentElement,
                h = g.clientTop || f.clientTop || 0,
                i = g.clientLeft || f.clientLeft || 0,
                b = d.top + (self.pageYOffset || g && g.scrollTop || f.scrollTop) - h,
                c = d.left + (self.pageXOffset || g && g.scrollLeft || f.scrollLeft) - i;
            else do b += a.offsetTop || 0, c += a.offsetLeft || 0, a = a.offsetParent;
            while (a);
            return {
                left: c,
                top: b
            }
        }

        function lineF(a, b, c, d) {
            function e(a) {
                return a * f + g
            }

            var f = (d - b) / (c - a),
                g = b - a * f;
            return e.k = f, e.b = g, e.x1 = a, e.x2 = c, e.y1 = b, e.y2 = d, e
        }

        function inRange(a, b, c) {
            var d = Math.abs(b - c),
                e = Math.abs(b - a),
                f = Math.abs(c - a),
                g = Math.abs(d - (e + f));
            return 1e-6 > g ? !0 : !1
        }

        function isPointInLineSeg(a, b, c) {
            return inRange(a, c.x1, c.x2) && inRange(b, c.y1, c.y2)
        }

        function intersection(a, b) {
            var c, d;
            return a.k == b.k ? null : (1 / 0 == a.k || a.k == -1 / 0 ? (c = a.x1, d = b(a.x1)) : 1 / 0 == b.k || b.k == -1 / 0 ? (c = b.x1, d = a(b.x1)) : (c = (b.b - a.b) / (a.k - b.k), d = a(c)), 0 == isPointInLineSeg(c, d, a) ? null : 0 == isPointInLineSeg(c, d, b) ? null : {
                x: c,
                y: d
            })
        }

        function intersectionLineBound(a, b) {
            var c = JTopo.util.lineF(b.left, b.top, b.left, b.bottom),
                d = JTopo.util.intersection(a, c);
            return null == d && (c = JTopo.util.lineF(b.left, b.top, b.right, b.top), d = JTopo.util.intersection(a, c), null == d && (c = JTopo.util.lineF(b.right, b.top, b.right, b.bottom), d = JTopo.util.intersection(a, c), null == d && (c = JTopo.util.lineF(b.left, b.bottom, b.right, b.bottom), d = JTopo.util.intersection(a, c)))), d
        }

        requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame ||
            function (a) {
                setTimeout(a, 1e3 / 24)
            }, Array.prototype.del = function (a) {
            if ("number" != typeof a) {
                for (var b = 0; b < this.length; b++) if (this[b] === a) return this.slice(0, b).concat(this.slice(b + 1, this.length));
                return this
            }
            return 0 > a ? this : this.slice(0, a).concat(this.slice(a + 1, this.length))
        }, [].indexOf || (Array.prototype.indexOf = function (a) {
            for (var b = 0; b < this.length; b++) if (this[b] === a) return b;
            return -1
        }), window.console || (window.console = {
            log: function () {
            },
            info: function () {
            },
            debug: function () {
            },
            warn: function () {
            },
            error: function () {
            }
        });
        var canvas = document.createElement("canvas"),
            graphics = canvas.getContext("2d"),
            alarmImageCache = {};
        JTopo.util = {
            rotatePoint: rotatePoint,
            rotatePoints: rotatePoints,
            getDistance: getDistance,
            getEventPosition: getEventPosition,
            mouseCoords: mouseCoords,
            MessageBus: MessageBus,
            isFirefox: navigator.userAgent.indexOf("Firefox") > 0,
            isIE: !(!window.attachEvent || -1 !== navigator.userAgent.indexOf("Opera")),
            isChrome: null != navigator.userAgent.toLowerCase().match(/chrome/),
            clone: clone,
            isPointInRect: isPointInRect,
            isPointInLine: isPointInLine,
            removeFromArray: removeFromArray,
            cloneEvent: cloneEvent,
            randomColor: randomColor,
            isIntsect: isIntsect,
            toJson: toJson,
            loadStageFromJson: loadStageFromJson,
            getElementsBound: getElementsBound,
            genImageAlarm: genImageAlarm,
            getOffsetPosition: getOffsetPosition,
            lineF: lineF,
            intersection: intersection,
            intersectionLineBound: intersectionLineBound
        }, window.$for = $for, window.$foreach = $foreach
    }(JTopo),

    function (JTopo) {
        function eagleEye(a) {
            return {
                hgap: 16,
                visible: !1,
                exportCanvas: document.createElement("canvas"),
                getImage: function (b, c) {
                    var d = a.getBound(),
                        e = 1,
                        f = 1;
                    this.exportCanvas.width = a.canvas.width, this.exportCanvas.height = a.canvas.height, null != b && null != c ? (this.exportCanvas.width = b, this.exportCanvas.height = c, e = b / d.width, f = c / d.height) : (d.width > a.canvas.width && (this.exportCanvas.width = d.width), d.height > a.canvas.height && (this.exportCanvas.height = d.height));
                    var g = this.exportCanvas.getContext("2d");
                    return a.childs.length > 0 && (g.save(), g.clearRect(0, 0, this.exportCanvas.width, this.exportCanvas.height), a.childs.forEach(function (a) {
                        1 == a.visible && (a.save(), a.translateX = 0, a.translateY = 0, a.scaleX = 1, a.scaleY = 1, g.scale(e, f), d.left < 0 && (a.translateX = Math.abs(d.left)), d.top < 0 && (a.translateY = Math.abs(d.top)), a.paintAll = !0, a.repaint(g), a.paintAll = !1, a.restore())
                    }), g.restore()), this.exportCanvas.toDataURL("image/png")
                },
                canvas: document.createElement("canvas"),
                update: function () {
                    this.eagleImageDatas = this.getData(a)
                },
                setSize: function (a, b) {
                    this.width = this.canvas.width = a, this.height = this.canvas.height = b
                },
                getData: function (b, c) {
                    function d(a) {
                        var b = a.stage.canvas.width,
                            c = a.stage.canvas.height,
                            d = b / a.scaleX / 2,
                            e = c / a.scaleY / 2;
                        return {
                            translateX: a.translateX + d - d * a.scaleX,
                            translateY: a.translateY + e - e * a.scaleY
                        }
                    }

                    null != j && null != k ? this.setSize(b, c) : this.setSize(200, 160);
                    var e = this.canvas.getContext("2d");
                    if (a.childs.length > 0) {
                        e.save(), e.clearRect(0, 0, this.canvas.width, this.canvas.height), a.childs.forEach(function (a) {
                            1 == a.visible && (a.save(), a.centerAndZoom(null, null, e), a.repaint(e), a.restore())
                        });
                        var f = d(a.childs[0]),
                            g = f.translateX * (this.canvas.width / a.canvas.width) * a.childs[0].scaleX,
                            h = f.translateY * (this.canvas.height / a.canvas.height) * a.childs[0].scaleY,
                            i = a.getBound(),
                            j = a.canvas.width / a.childs[0].scaleX / i.width,
                            k = a.canvas.height / a.childs[0].scaleY / i.height;
                        j > 1 && (j = 1), k > 1 && (j = 1), g *= j, h *= k, i.left < 0 && (g -= Math.abs(i.left) * (this.width / i.width)), i.top < 0 && (h -= Math.abs(i.top) * (this.height / i.height)), e.save(), e.lineWidth = 1, e.strokeStyle = "rgba(0,255,0,1)";
                        // 画鹰眼区拖放的长方形小块
                        e.strokeRect(-g, -h, e.canvas.width * j, e.canvas.height * k), e.restore();
                        var l = null;
                        try {
                            l = e.getImageData(0, 0, e.canvas.width, e.canvas.height)
                        } catch (m) {
                        }
                        return l
                    }
                    return null
                },
                paint: function () {
                    if (null != this.eagleImageDatas) {
                        var b = a.graphics;
                        b.save(), b.fillStyle = "rgba(211,211,211,0.3)", b.fillRect(a.canvas.width - this.canvas.width - 2 * this.hgap, a.canvas.height - this.canvas.height - 1, a.canvas.width - this.canvas.width, this.canvas.height + 1), b.fill(), b.save(), b.lineWidth = 1, b.strokeStyle = "rgba(0,0,0,1)", b.rect(a.canvas.width - this.canvas.width - 2 * this.hgap, a.canvas.height - this.canvas.height - 1, a.canvas.width - this.canvas.width, this.canvas.height + 1), b.stroke(), b.restore(), b.putImageData(this.eagleImageDatas, a.canvas.width - this.canvas.width - this.hgap, a.canvas.height - this.canvas.height), b.restore()
                    } else this.eagleImageDatas = this.getData(a)
                },
                /**
                 * 鼠标在鹰眼区域拖拽时的动作
                 * @param a mouse系列事件名
                 * @param b event事件信息
                 * @param c stage对象
                 */
                eventHandler: function (a, b, c) {
                    var d = b.x,
                        e = b.y;
                    // 操作点位于鹰眼区域
                    if (d > c.canvas.width - this.canvas.width && e > c.canvas.height - this.canvas.height) {
                        if (d = b.x - this.canvas.width, e = b.y - this.canvas.height, "mousedown" == a && (this.lastTranslateX = c.childs[0].translateX, this.lastTranslateY = c.childs[0].translateY), "mousedrag" == a && c.childs.length > 0) {
                            var f = b.dx,
                                g = b.dy,
                                h = c.getBound(),
                                i = this.canvas.width / c.childs[0].scaleX / h.width,
                                j = this.canvas.height / c.childs[0].scaleY / h.height;
                            // 比例位移
                            c.childs[0].translateX = this.lastTranslateX - f / i, c.childs[0].translateY = this.lastTranslateY - g / j
                        }
                    } else {
                        return;
                    }
                    ;
                }
            }
        }

        /**
         *
         * @param 事件传递顺序:stage->scene->node,事件处理相反
         * @constructor
         */
        function Stage(c) {
            /**
             * 转换原生的event对象
             * @param b event对象
             */
            function d(b) {
                var c = JTopo.util.getEventPosition(b),
                    d = JTopo.util.getOffsetPosition(stage.canvas);
                return c.offsetLeft = c.pageX - d.left, c.offsetTop = c.pageY - d.top, c.x = c.offsetLeft, c.y = c.offsetTop, c.target = null, c
            }

            function e(a) {
                document.onselectstart = function () {
                    return !1
                }, this.mouseOver = !0;
                var b = d(a);
                stage.dispatchEventToScenes("mouseover", b), stage.dispatchEvent("mouseover", b)
            }

            function f(a) {
                p = setTimeout(function () {
                    o = !0
                }, 500), document.onselectstart = function () {
                    return !0
                };
                var b = d(a);
                stage.dispatchEventToScenes("mouseout", b), stage.dispatchEvent("mouseout", b), stage.needRepaint = 0 == stage.animate ? !1 : !0
            }

            function g(a) {
                var b = d(a);
                stage.mouseDown = !0, stage.mouseDownX = b.x, stage.mouseDownY = b.y, stage.dispatchEventToScenes("mousedown", b), stage.dispatchEvent("mousedown", b)
            }

            function h(a) {
                var b = d(a);
                stage.dispatchEventToScenes("mouseup", b), stage.dispatchEvent("mouseup", b), stage.mouseDown = !1, stage.needRepaint = 0 == stage.animate ? !1 : !0
            }

            function i(a) {
                p && (window.clearTimeout(p), p = null), o = !1;
                var b = d(a);
                stage.mouseDown ? 0 == a.button && (b.dx = b.x - stage.mouseDownX, b.dy = b.y - stage.mouseDownY, stage.dispatchEventToScenes("mousedrag", b), stage.dispatchEvent("mousedrag", b), 1 == stage.eagleEye.visible && stage.eagleEye.update()) : (stage.dispatchEventToScenes("mousemove", b), stage.dispatchEvent("mousemove", b))
            }

            function j(a) {
                var b = d(a);
                stage.dispatchEventToScenes("click", b), stage.dispatchEvent("click", b)
            }

            function k(a) {
                var b = d(a);
                stage.dispatchEventToScenes("dbclick", b), stage.dispatchEvent("dbclick", b)
            }

            function l(a) {
                var b = d(a);
                stage.dispatchEventToScenes("mousewheel", b), stage.dispatchEvent("mousewheel", b), null != stage.wheelZoom && (a.preventDefault ? a.preventDefault() : (a = a || window.event, a.returnValue = !1), 1 == stage.eagleEye.visible && stage.eagleEye.update())
            }

            /**
             * 实现事件处理:canvas无法监听具体里面是哪个元素的事件
             * 把事件绑定到canvas对应的DOM对象,然后再用事件分发机制处理(消息总线)
             * @param b 创建Stage对象时传入的Canvas对象
             */
            function initJtopoEvent(b) {
                // 事件绑定浏览器兼容性处理:非IE,用addEventlistener(type,fn,false)只监听冒泡事件,为true会监听捕获事件
                JTopo.util.isIE || !window.addEventListener ? (b.onmouseout = f, b.onmouseover = e, b.onmousedown = g, b.onmouseup = h, b.onmousemove = i, b.onclick = j, b.ondblclick = k, b.onmousewheel = l, b.touchstart = g, b.touchmove = i, b.touchend = h) : (b.addEventListener("mouseout", f), b.addEventListener("mouseover", e), b.addEventListener("mousedown", g), b.addEventListener("mouseup", h), b.addEventListener("mousemove", i), b.addEventListener("click", j), b.addEventListener("dblclick", k), JTopo.util.isFirefox ? b.addEventListener("DOMMouseScroll", l) : b.addEventListener("mousewheel", l)),
                window.addEventListener && (window.addEventListener("keydown", function (b) {
                    stage.dispatchEventToScenes("keydown", JTopo.util.cloneEvent(b));
                    var c = b.keyCode;
                    (37 == c || 38 == c || 39 == c || 40 == c) && (b.preventDefault ? b.preventDefault() : (b = b || window.event, b.returnValue = !1))
                }, !0), window.addEventListener("keyup", function (b) {
                    stage.dispatchEventToScenes("keyup", JTopo.util.cloneEvent(b));
                    var c = b.keyCode;
                    (37 == c || 38 == c || 39 == c || 40 == c) && (b.preventDefault ? b.preventDefault() : (b = b || window.event, b.returnValue = !1))
                }, !0))
            }

            JTopo.stage = this;
            var stage = this;

            // Stage对象初始化方法,初始化画布,画图对象和初始状态
            this.initialize = function (c) {
wangqinghua's avatar
wangqinghua committed
                initJtopoEvent(c), this.canvas = c, this.id = "", this.graphics = c.getContext("2d"), this.childs = [], this.frames = 24, this.messageBus = new JTopo.util.MessageBus, this.eagleEye = eagleEye(this), this.wheelZoom = null, this.mouseDownX = 0, this.mouseDownY = 0, this.mouseDown = !1, this.mouseOver = !1, this.needRepaint = !0, this.serializedProperties = ["wheelZoom", "width","height", "id"]
wangqinghua's avatar
wangqinghua committed
            }, null != c && this.initialize(c);

            var o = !0,
                p = null;
            // 禁用右键菜单
            document.oncontextmenu = function () {
                return o
            }, this.dispatchEventToScenes = function (eventType, event) {
                // 鼠标移动到鹰眼区域,触发联动位移操作
                if (0 != this.frames && (this.needRepaint = !0), 1 == this.eagleEye.visible && -1 != eventType.indexOf("mouse")) {
                    var c = event.x,
                        d = event.y;
                    if (c > this.width - this.eagleEye.width && d > this.height - this.eagleEye.height)
                        return void this.eagleEye.eventHandler(eventType, event, this);
                }
                // 对每个scene对象调用事件处理函数
                this.childs.forEach(function (c) {
                    if (1 == c.visible) {
                        var d = c[eventType + "Handler"];
                        if (null == d) throw new Error("Function not found:" + eventType + "Handler");
                        d.call(c, event)
                    }
                })
            }, this.add = function (a) {
                for (var b = 0; b < this.childs.length; b++) if (this.childs[b] === a) return;
                a.addTo(this), this.childs.push(a)
            }, this.remove = function (a) {
                if (null == a) throw new Error("Stage.remove出错: 参数为null!");
                for (var b = 0; b < this.childs.length; b++) if (this.childs[b] === a) return a.stage = null, this.childs = this.childs.del(b), this;
                return this
            }, this.clear = function () {
                this.childs = []
            }, this.addEventListener = function (a, b) {
                var c = this,