GraphView.js 10.9 KB
Newer Older
L
lang 已提交
1

L
lang 已提交
2 3
define(function (require) {

L
lang 已提交
4 5
    var SymbolDraw = require('../helper/SymbolDraw');
    var LineDraw = require('../helper/LineDraw');
L
lang 已提交
6
    var RoamController = require('../../component/helper/RoamController');
L
lang 已提交
7

L
lang 已提交
8
    var graphic = require('../../util/graphic');
L
lang 已提交
9
    var adjustEdge = require('./adjustEdge');
L
lang 已提交
10 11 12 13 14 15 16 17
    var zrUtil = require('zrender/core/util');

    var nodeOpacityPath = ['itemStyle', 'normal', 'opacity'];
    var lineOpacityPath = ['lineStyle', 'normal', 'opacity'];

    function getItemOpacity(item, opacityPath) {
        return item.getVisual('opacity') || item.getModel().get(opacityPath);
    }
L
lang 已提交
18

L
lang 已提交
19 20 21 22
    require('../../echarts').extendChartView({

        type: 'graph',

L
lang 已提交
23
        init: function (ecModel, api) {
L
lang 已提交
24
            var symbolDraw = new SymbolDraw();
L
lang 已提交
25
            var lineDraw = new LineDraw();
L
lang 已提交
26
            var group = this.group;
L
lang 已提交
27

L
lang 已提交
28 29
            var controller = new RoamController(api.getZr(), group);

L
lang 已提交
30 31
            group.add(symbolDraw.group);
            group.add(lineDraw.group);
L
lang 已提交
32

L
lang 已提交
33
            this._symbolDraw = symbolDraw;
L
lang 已提交
34
            this._lineDraw = lineDraw;
L
lang 已提交
35
            this._controller = controller;
L
lang 已提交
36 37

            this._firstRender = true;
L
lang 已提交
38 39 40
        },

        render: function (seriesModel, ecModel, api) {
L
lang 已提交
41 42 43
            var coordSys = seriesModel.coordinateSystem;

            this._model = seriesModel;
44
            this._nodeScaleRatio = seriesModel.get('nodeScaleRatio');
L
lang 已提交
45

L
lang 已提交
46 47 48
            var symbolDraw = this._symbolDraw;
            var lineDraw = this._lineDraw;

L
lang 已提交
49
            var group = this.group;
50 51 52 53 54 55 56 57 58 59 60 61

            if (coordSys.type === 'view') {
                var groupNewProp = {
                    position: coordSys.position,
                    scale: coordSys.scale
                };
                if (this._firstRender) {
                    group.attr(groupNewProp);
                }
                else {
                    graphic.updateProps(group, groupNewProp, seriesModel);
                }
L
lang 已提交
62
            }
63 64
            // Fix edge contact point with node
            adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
L
lang 已提交
65

66 67 68 69 70
            var data = seriesModel.getData();
            symbolDraw.updateData(data);

            var edgeData = seriesModel.getEdgeData();
            lineDraw.updateData(edgeData);
L
lang 已提交
71 72 73

            this._updateNodeAndLinkScale();

74
            this._updateController(seriesModel, api);
L
lang 已提交
75

L
lang 已提交
76
            clearTimeout(this._layoutTimeout);
L
lang 已提交
77
            var forceLayout = seriesModel.forceLayout;
L
lang 已提交
78
            var layoutAnimation = seriesModel.get('force.layoutAnimation');
L
lang 已提交
79
            if (forceLayout) {
L
lang 已提交
80
                this._startForceLayoutIteration(forceLayout, layoutAnimation);
L
lang 已提交
81
            }
L
lang 已提交
82
            data.eachItemGraphicEl(function (el, idx) {
L
lang 已提交
83 84 85
                var itemModel = data.getItemModel(idx);
                // Update draggable
                el.off('drag').off('dragend');
L
lang 已提交
86
                var draggable = data.getItemModel(idx).get('draggable');
87
                if (draggable) {
L
lang 已提交
88
                    el.on('drag', function () {
89 90 91 92 93 94 95 96
                        if (forceLayout) {
                            forceLayout.warmUp();
                            !this._layouting
                                && this._startForceLayoutIteration(forceLayout, layoutAnimation);
                            forceLayout.setFixed(idx);
                            // Write position back to layout
                            data.setItemLayout(idx, el.position);
                        }
L
lang 已提交
97
                    }, this).on('dragend', function () {
98 99 100
                        if (forceLayout) {
                            forceLayout.setUnfixed(idx);
                        }
L
lang 已提交
101
                    }, this);
L
lang 已提交
102
                }
103
                el.setDraggable(draggable && forceLayout);
L
lang 已提交
104 105

                el.off('mouseover', this._focusNodeAdjacency);
L
lang 已提交
106
                el.off('mouseout', this._unfocusAll);
L
lang 已提交
107 108
                if (itemModel.get('focusNodeAdjacency')) {
                    el.on('mouseover', this._focusNodeAdjacency, this);
L
lang 已提交
109
                    el.on('mouseout', this._unfocusAll, this);
L
lang 已提交
110
                }
L
lang 已提交
111
            }, this);
L
lang 已提交
112

113 114 115 116 117 118 119 120 121 122 123 124 125 126
            seriesModel.getGraph().eachEdge(function (edge, idx) {
                var itemModel = edge.getModel();
                var el = edge.getGraphicEl();
                switch (itemModel.get('lineStyle.normal.color')) {
                    case 'source':
                        el.setColor(edge.node1.getVisual('color'));
                        break;
                    case 'target':
                        el.setColor(edge.node2.getVisual('color'));
                        break;
                    default:
                }
            });

L
lang 已提交
127
            this._firstRender = false;
L
lang 已提交
128 129
        },

L
lang 已提交
130 131 132 133 134 135 136
        _focusNodeAdjacency: function (e) {
            var data = this._model.getData();
            var graph = data.graph;
            var el = e.target;
            var dataIndex = el.dataIndex;
            var dataType = el.dataType;

L
lang 已提交
137 138 139 140 141
            function fadeOutItem(item, opacityPath) {
                var opacity = getItemOpacity(item, opacityPath);
                var el = item.getGraphicEl();
                if (opacity == null) {
                    opacity = 1;
L
lang 已提交
142
                }
L
lang 已提交
143 144 145 146 147 148 149

                el.traverse(function (child) {
                    child.trigger('normal');
                    if (child.type !== 'group') {
                        child.setStyle('opacity', opacity * 0.1);
                    }
                });
L
lang 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
            }

            function fadeInItem(item, opacityPath) {
                var opacity = getItemOpacity(item, opacityPath);
                var el = item.getGraphicEl();

                el.traverse(function (child) {
                    child.trigger('emphasis');
                    if (child.type !== 'group') {
                        child.setStyle('opacity', opacity);
                    }
                });
            }
            if (dataIndex !== null && dataType !== 'edge') {
                graph.eachNode(function (node) {
L
lang 已提交
165
                    fadeOutItem(node, nodeOpacityPath);
L
lang 已提交
166 167
                });
                graph.eachEdge(function (edge) {
L
lang 已提交
168
                    fadeOutItem(edge, lineOpacityPath);
L
lang 已提交
169 170 171 172 173 174 175 176 177 178 179 180 181 182
                });

                var node = graph.getNodeByIndex(dataIndex);
                zrUtil.each(node.edges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem(edge, lineOpacityPath);
                    fadeInItem(edge.node1, nodeOpacityPath);
                    fadeInItem(edge.node2, nodeOpacityPath);
                });
            }
        },

L
lang 已提交
183
        _unfocusAll: function () {
L
lang 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
            var data = this._model.getData();
            var graph = data.graph;
            graph.eachNode(function (node) {
                var opacity = getItemOpacity(node, nodeOpacityPath);
                node.getGraphicEl().traverse(function (child) {
                    child.trigger('normal');
                    if (child.type !== 'group') {
                        child.setStyle('opacity', opacity);
                    }
                });
            });
            graph.eachEdge(function (edge) {
                var opacity = getItemOpacity(edge, lineOpacityPath);
                edge.getGraphicEl().traverse(function (child) {
                    child.trigger('normal');
                    if (child.type !== 'group') {
                        child.setStyle('opacity', opacity);
                    }
                });
            });
        },

L
lang 已提交
206
        _startForceLayoutIteration: function (forceLayout, layoutAnimation) {
L
lang 已提交
207 208 209
            var self = this;
            (function step() {
                forceLayout.step(function (stopped) {
210
                    self.updateLayout(self._model);
L
lang 已提交
211
                    (self._layouting = !stopped) && (
L
lang 已提交
212 213 214 215
                        layoutAnimation
                            ? (self._layoutTimeout = setTimeout(step, 16))
                            : step()
                    );
L
lang 已提交
216 217
                });
            })();
L
lang 已提交
218 219
        },

220
        _updateController: function (seriesModel, api) {
L
lang 已提交
221
            var controller = this._controller;
222 223 224 225 226 227
            var group = this.group;
            controller.rectProvider = function () {
                var rect = group.getBoundingRect();
                rect.applyTransform(group.transform);
                return rect;
            };
228 229 230 231
            if (seriesModel.coordinateSystem.type !== 'view') {
                controller.disable();
                return;
            }
L
lang 已提交
232
            controller.enable(seriesModel.get('roam'));
L
lang 已提交
233 234
            controller.zoomLimit = seriesModel.get('scaleLimit');
            // Update zoom from model
235
            controller.zoom = seriesModel.coordinateSystem.getZoom();
L
lang 已提交
236 237 238 239 240

            controller
                .off('pan')
                .off('zoom')
                .on('pan', function (dx, dy) {
L
lang 已提交
241
                    api.dispatchAction({
P
pah100 已提交
242
                        seriesId: seriesModel.id,
L
lang 已提交
243 244 245 246 247 248
                        type: 'graphRoam',
                        dx: dx,
                        dy: dy
                    });
                })
                .on('zoom', function (zoom, mouseX, mouseY) {
L
lang 已提交
249
                    api.dispatchAction({
P
pah100 已提交
250
                        seriesId: seriesModel.id,
L
lang 已提交
251 252 253 254 255
                        type: 'graphRoam',
                        zoom:  zoom,
                        originX: mouseX,
                        originY: mouseY
                    });
256 257 258 259
                    this._updateNodeAndLinkScale();
                    adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));
                    this._lineDraw.updateLayout();
                }, this);
L
lang 已提交
260 261 262 263 264
        },

        _updateNodeAndLinkScale: function () {
            var seriesModel = this._model;
            var data = seriesModel.getData();
265 266 267 268 269 270 271 272 273 274

            var nodeScale = this._getNodeGlobalScale(seriesModel);
            var invScale = [nodeScale, nodeScale];

            data.eachItemGraphicEl(function (el, idx) {
                el.attr('scale', invScale);
            });
        },

        _getNodeGlobalScale: function (seriesModel) {
275
            var coordSys = seriesModel.coordinateSystem;
276 277 278
            if (coordSys.type !== 'view') {
                return 1;
            }
L
lang 已提交
279 280 281

            var nodeScaleRatio = this._nodeScaleRatio;

L
lang 已提交
282
            var groupScale = coordSys.scale;
283 284 285 286
            var groupZoom = (groupScale && groupScale[0]) || 1;
            // Scale node when zoom changes
            var roamZoom = coordSys.getZoom();
            var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
L
lang 已提交
287

288
            return nodeScale / groupZoom;
L
lang 已提交
289 290
        },

291
        updateLayout: function (seriesModel) {
L
lang 已提交
292 293
            adjustEdge(seriesModel.getGraph(), this._getNodeGlobalScale(seriesModel));

L
lang 已提交
294 295 296
            this._symbolDraw.updateLayout();
            this._lineDraw.updateLayout();
        },
L
lang 已提交
297

L
lang 已提交
298
        remove: function (ecModel, api) {
L
lang 已提交
299 300
            this._symbolDraw && this._symbolDraw.remove();
            this._lineDraw && this._lineDraw.remove();
L
lang 已提交
301 302 303
        }
    });
});