637 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			637 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
 | |
| /*
 | |
| * Licensed to the Apache Software Foundation (ASF) under one
 | |
| * or more contributor license agreements.  See the NOTICE file
 | |
| * distributed with this work for additional information
 | |
| * regarding copyright ownership.  The ASF licenses this file
 | |
| * to you under the Apache License, Version 2.0 (the
 | |
| * "License"); you may not use this file except in compliance
 | |
| * with the License.  You may obtain a copy of the License at
 | |
| *
 | |
| *   http://www.apache.org/licenses/LICENSE-2.0
 | |
| *
 | |
| * Unless required by applicable law or agreed to in writing,
 | |
| * software distributed under the License is distributed on an
 | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 | |
| * KIND, either express or implied.  See the License for the
 | |
| * specific language governing permissions and limitations
 | |
| * under the License.
 | |
| */
 | |
| 
 | |
| var zrUtil = require("zrender/lib/core/util");
 | |
| 
 | |
| var graphic = require("../../util/graphic");
 | |
| 
 | |
| var SymbolClz = require("../helper/Symbol");
 | |
| 
 | |
| var _layoutHelper = require("./layoutHelper");
 | |
| 
 | |
| var radialCoordinate = _layoutHelper.radialCoordinate;
 | |
| 
 | |
| var echarts = require("../../echarts");
 | |
| 
 | |
| var bbox = require("zrender/lib/core/bbox");
 | |
| 
 | |
| var View = require("../../coord/View");
 | |
| 
 | |
| var roamHelper = require("../../component/helper/roamHelper");
 | |
| 
 | |
| var RoamController = require("../../component/helper/RoamController");
 | |
| 
 | |
| var _cursorHelper = require("../../component/helper/cursorHelper");
 | |
| 
 | |
| var onIrrelevantElement = _cursorHelper.onIrrelevantElement;
 | |
| 
 | |
| var _config = require("../../config");
 | |
| 
 | |
| var __DEV__ = _config.__DEV__;
 | |
| 
 | |
| var _number = require("../../util/number");
 | |
| 
 | |
| var parsePercent = _number.parsePercent;
 | |
| 
 | |
| /*
 | |
| * Licensed to the Apache Software Foundation (ASF) under one
 | |
| * or more contributor license agreements.  See the NOTICE file
 | |
| * distributed with this work for additional information
 | |
| * regarding copyright ownership.  The ASF licenses this file
 | |
| * to you under the Apache License, Version 2.0 (the
 | |
| * "License"); you may not use this file except in compliance
 | |
| * with the License.  You may obtain a copy of the License at
 | |
| *
 | |
| *   http://www.apache.org/licenses/LICENSE-2.0
 | |
| *
 | |
| * Unless required by applicable law or agreed to in writing,
 | |
| * software distributed under the License is distributed on an
 | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 | |
| * KIND, either express or implied.  See the License for the
 | |
| * specific language governing permissions and limitations
 | |
| * under the License.
 | |
| */
 | |
| var TreeShape = graphic.extendShape({
 | |
|   shape: {
 | |
|     parentPoint: [],
 | |
|     childPoints: [],
 | |
|     orient: '',
 | |
|     forkPosition: ''
 | |
|   },
 | |
|   style: {
 | |
|     stroke: '#000',
 | |
|     fill: null
 | |
|   },
 | |
|   buildPath: function (ctx, shape) {
 | |
|     var childPoints = shape.childPoints;
 | |
|     var childLen = childPoints.length;
 | |
|     var parentPoint = shape.parentPoint;
 | |
|     var firstChildPos = childPoints[0];
 | |
|     var lastChildPos = childPoints[childLen - 1];
 | |
| 
 | |
|     if (childLen === 1) {
 | |
|       ctx.moveTo(parentPoint[0], parentPoint[1]);
 | |
|       ctx.lineTo(firstChildPos[0], firstChildPos[1]);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     var orient = shape.orient;
 | |
|     var forkDim = orient === 'TB' || orient === 'BT' ? 0 : 1;
 | |
|     var otherDim = 1 - forkDim;
 | |
|     var forkPosition = parsePercent(shape.forkPosition, 1);
 | |
|     var tmpPoint = [];
 | |
|     tmpPoint[forkDim] = parentPoint[forkDim];
 | |
|     tmpPoint[otherDim] = parentPoint[otherDim] + (lastChildPos[otherDim] - parentPoint[otherDim]) * forkPosition;
 | |
|     ctx.moveTo(parentPoint[0], parentPoint[1]);
 | |
|     ctx.lineTo(tmpPoint[0], tmpPoint[1]);
 | |
|     ctx.moveTo(firstChildPos[0], firstChildPos[1]);
 | |
|     tmpPoint[forkDim] = firstChildPos[forkDim];
 | |
|     ctx.lineTo(tmpPoint[0], tmpPoint[1]);
 | |
|     tmpPoint[forkDim] = lastChildPos[forkDim];
 | |
|     ctx.lineTo(tmpPoint[0], tmpPoint[1]);
 | |
|     ctx.lineTo(lastChildPos[0], lastChildPos[1]);
 | |
| 
 | |
|     for (var i = 1; i < childLen - 1; i++) {
 | |
|       var point = childPoints[i];
 | |
|       ctx.moveTo(point[0], point[1]);
 | |
|       tmpPoint[forkDim] = point[forkDim];
 | |
|       ctx.lineTo(tmpPoint[0], tmpPoint[1]);
 | |
|     }
 | |
|   }
 | |
| });
 | |
| 
 | |
| var _default = echarts.extendChartView({
 | |
|   type: 'tree',
 | |
| 
 | |
|   /**
 | |
|    * Init the chart
 | |
|    * @override
 | |
|    * @param  {module:echarts/model/Global} ecModel
 | |
|    * @param  {module:echarts/ExtensionAPI} api
 | |
|    */
 | |
|   init: function (ecModel, api) {
 | |
|     /**
 | |
|      * @private
 | |
|      * @type {module:echarts/data/Tree}
 | |
|      */
 | |
|     this._oldTree;
 | |
|     /**
 | |
|      * @private
 | |
|      * @type {module:zrender/container/Group}
 | |
|      */
 | |
| 
 | |
|     this._mainGroup = new graphic.Group();
 | |
|     /**
 | |
|      * @private
 | |
|      * @type {module:echarts/componet/helper/RoamController}
 | |
|      */
 | |
| 
 | |
|     this._controller = new RoamController(api.getZr());
 | |
|     this._controllerHost = {
 | |
|       target: this.group
 | |
|     };
 | |
|     this.group.add(this._mainGroup);
 | |
|   },
 | |
|   render: function (seriesModel, ecModel, api, payload) {
 | |
|     var data = seriesModel.getData();
 | |
|     var layoutInfo = seriesModel.layoutInfo;
 | |
|     var group = this._mainGroup;
 | |
|     var layout = seriesModel.get('layout');
 | |
| 
 | |
|     if (layout === 'radial') {
 | |
|       group.attr('position', [layoutInfo.x + layoutInfo.width / 2, layoutInfo.y + layoutInfo.height / 2]);
 | |
|     } else {
 | |
|       group.attr('position', [layoutInfo.x, layoutInfo.y]);
 | |
|     }
 | |
| 
 | |
|     this._updateViewCoordSys(seriesModel, layoutInfo, layout);
 | |
| 
 | |
|     this._updateController(seriesModel, ecModel, api);
 | |
| 
 | |
|     var oldData = this._data;
 | |
|     var seriesScope = {
 | |
|       expandAndCollapse: seriesModel.get('expandAndCollapse'),
 | |
|       layout: layout,
 | |
|       edgeShape: seriesModel.get('edgeShape'),
 | |
|       edgeForkPosition: seriesModel.get('edgeForkPosition'),
 | |
|       orient: seriesModel.getOrient(),
 | |
|       curvature: seriesModel.get('lineStyle.curveness'),
 | |
|       symbolRotate: seriesModel.get('symbolRotate'),
 | |
|       symbolOffset: seriesModel.get('symbolOffset'),
 | |
|       hoverAnimation: seriesModel.get('hoverAnimation'),
 | |
|       useNameLabel: true,
 | |
|       fadeIn: true
 | |
|     };
 | |
|     data.diff(oldData).add(function (newIdx) {
 | |
|       if (symbolNeedsDraw(data, newIdx)) {
 | |
|         // Create node and edge
 | |
|         updateNode(data, newIdx, null, group, seriesModel, seriesScope);
 | |
|       }
 | |
|     }).update(function (newIdx, oldIdx) {
 | |
|       var symbolEl = oldData.getItemGraphicEl(oldIdx);
 | |
| 
 | |
|       if (!symbolNeedsDraw(data, newIdx)) {
 | |
|         symbolEl && removeNode(oldData, oldIdx, symbolEl, group, seriesModel, seriesScope);
 | |
|         return;
 | |
|       } // Update node and edge
 | |
| 
 | |
| 
 | |
|       updateNode(data, newIdx, symbolEl, group, seriesModel, seriesScope);
 | |
|     }).remove(function (oldIdx) {
 | |
|       var symbolEl = oldData.getItemGraphicEl(oldIdx); // When remove a collapsed node of subtree, since the collapsed
 | |
|       // node haven't been initialized with a symbol element,
 | |
|       // you can't found it's symbol element through index.
 | |
|       // so if we want to remove the symbol element we should insure
 | |
|       // that the symbol element is not null.
 | |
| 
 | |
|       if (symbolEl) {
 | |
|         removeNode(oldData, oldIdx, symbolEl, group, seriesModel, seriesScope);
 | |
|       }
 | |
|     }).execute();
 | |
|     this._nodeScaleRatio = seriesModel.get('nodeScaleRatio');
 | |
| 
 | |
|     this._updateNodeAndLinkScale(seriesModel);
 | |
| 
 | |
|     if (seriesScope.expandAndCollapse === true) {
 | |
|       data.eachItemGraphicEl(function (el, dataIndex) {
 | |
|         el.off('click').on('click', function () {
 | |
|           api.dispatchAction({
 | |
|             type: 'treeExpandAndCollapse',
 | |
|             seriesId: seriesModel.id,
 | |
|             dataIndex: dataIndex
 | |
|           });
 | |
|         });
 | |
|       });
 | |
|     }
 | |
| 
 | |
|     this._data = data;
 | |
|   },
 | |
|   _updateViewCoordSys: function (seriesModel) {
 | |
|     var data = seriesModel.getData();
 | |
|     var points = [];
 | |
|     data.each(function (idx) {
 | |
|       var layout = data.getItemLayout(idx);
 | |
| 
 | |
|       if (layout && !isNaN(layout.x) && !isNaN(layout.y)) {
 | |
|         points.push([+layout.x, +layout.y]);
 | |
|       }
 | |
|     });
 | |
|     var min = [];
 | |
|     var max = [];
 | |
|     bbox.fromPoints(points, min, max); // If don't Store min max when collapse the root node after roam,
 | |
|     // the root node will disappear.
 | |
| 
 | |
|     var oldMin = this._min;
 | |
|     var oldMax = this._max; // If width or height is 0
 | |
| 
 | |
|     if (max[0] - min[0] === 0) {
 | |
|       min[0] = oldMin ? oldMin[0] : min[0] - 1;
 | |
|       max[0] = oldMax ? oldMax[0] : max[0] + 1;
 | |
|     }
 | |
| 
 | |
|     if (max[1] - min[1] === 0) {
 | |
|       min[1] = oldMin ? oldMin[1] : min[1] - 1;
 | |
|       max[1] = oldMax ? oldMax[1] : max[1] + 1;
 | |
|     }
 | |
| 
 | |
|     var viewCoordSys = seriesModel.coordinateSystem = new View();
 | |
|     viewCoordSys.zoomLimit = seriesModel.get('scaleLimit');
 | |
|     viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]);
 | |
|     viewCoordSys.setCenter(seriesModel.get('center'));
 | |
|     viewCoordSys.setZoom(seriesModel.get('zoom')); // Here we use viewCoordSys just for computing the 'position' and 'scale' of the group
 | |
| 
 | |
|     this.group.attr({
 | |
|       position: viewCoordSys.position,
 | |
|       scale: viewCoordSys.scale
 | |
|     });
 | |
|     this._viewCoordSys = viewCoordSys;
 | |
|     this._min = min;
 | |
|     this._max = max;
 | |
|   },
 | |
|   _updateController: function (seriesModel, ecModel, api) {
 | |
|     var controller = this._controller;
 | |
|     var controllerHost = this._controllerHost;
 | |
|     var group = this.group;
 | |
|     controller.setPointerChecker(function (e, x, y) {
 | |
|       var rect = group.getBoundingRect();
 | |
|       rect.applyTransform(group.transform);
 | |
|       return rect.contain(x, y) && !onIrrelevantElement(e, api, seriesModel);
 | |
|     });
 | |
|     controller.enable(seriesModel.get('roam'));
 | |
|     controllerHost.zoomLimit = seriesModel.get('scaleLimit');
 | |
|     controllerHost.zoom = seriesModel.coordinateSystem.getZoom();
 | |
|     controller.off('pan').off('zoom').on('pan', function (e) {
 | |
|       roamHelper.updateViewOnPan(controllerHost, e.dx, e.dy);
 | |
|       api.dispatchAction({
 | |
|         seriesId: seriesModel.id,
 | |
|         type: 'treeRoam',
 | |
|         dx: e.dx,
 | |
|         dy: e.dy
 | |
|       });
 | |
|     }, this).on('zoom', function (e) {
 | |
|       roamHelper.updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
 | |
|       api.dispatchAction({
 | |
|         seriesId: seriesModel.id,
 | |
|         type: 'treeRoam',
 | |
|         zoom: e.scale,
 | |
|         originX: e.originX,
 | |
|         originY: e.originY
 | |
|       });
 | |
| 
 | |
|       this._updateNodeAndLinkScale(seriesModel);
 | |
|     }, this);
 | |
|   },
 | |
|   _updateNodeAndLinkScale: function (seriesModel) {
 | |
|     var data = seriesModel.getData();
 | |
| 
 | |
|     var nodeScale = this._getNodeGlobalScale(seriesModel);
 | |
| 
 | |
|     var invScale = [nodeScale, nodeScale];
 | |
|     data.eachItemGraphicEl(function (el, idx) {
 | |
|       el.attr('scale', invScale);
 | |
|     });
 | |
|   },
 | |
|   _getNodeGlobalScale: function (seriesModel) {
 | |
|     var coordSys = seriesModel.coordinateSystem;
 | |
| 
 | |
|     if (coordSys.type !== 'view') {
 | |
|       return 1;
 | |
|     }
 | |
| 
 | |
|     var nodeScaleRatio = this._nodeScaleRatio;
 | |
|     var groupScale = coordSys.scale;
 | |
|     var groupZoom = groupScale && groupScale[0] || 1; // Scale node when zoom changes
 | |
| 
 | |
|     var roamZoom = coordSys.getZoom();
 | |
|     var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
 | |
|     return nodeScale / groupZoom;
 | |
|   },
 | |
|   dispose: function () {
 | |
|     this._controller && this._controller.dispose();
 | |
|     this._controllerHost = {};
 | |
|   },
 | |
|   remove: function () {
 | |
|     this._mainGroup.removeAll();
 | |
| 
 | |
|     this._data = null;
 | |
|   }
 | |
| });
 | |
| 
 | |
| function symbolNeedsDraw(data, dataIndex) {
 | |
|   var layout = data.getItemLayout(dataIndex);
 | |
|   return layout && !isNaN(layout.x) && !isNaN(layout.y) && data.getItemVisual(dataIndex, 'symbol') !== 'none';
 | |
| }
 | |
| 
 | |
| function getTreeNodeStyle(node, itemModel, seriesScope) {
 | |
|   seriesScope.itemModel = itemModel;
 | |
|   seriesScope.itemStyle = itemModel.getModel('itemStyle').getItemStyle();
 | |
|   seriesScope.hoverItemStyle = itemModel.getModel('emphasis.itemStyle').getItemStyle();
 | |
|   seriesScope.lineStyle = itemModel.getModel('lineStyle').getLineStyle();
 | |
|   seriesScope.labelModel = itemModel.getModel('label');
 | |
|   seriesScope.hoverLabelModel = itemModel.getModel('emphasis.label');
 | |
| 
 | |
|   if (node.isExpand === false && node.children.length !== 0) {
 | |
|     seriesScope.symbolInnerColor = seriesScope.itemStyle.fill;
 | |
|   } else {
 | |
|     seriesScope.symbolInnerColor = '#fff';
 | |
|   }
 | |
| 
 | |
|   return seriesScope;
 | |
| }
 | |
| 
 | |
| function updateNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) {
 | |
|   var isInit = !symbolEl;
 | |
|   var node = data.tree.getNodeByDataIndex(dataIndex);
 | |
|   var itemModel = node.getModel();
 | |
|   var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope);
 | |
|   var virtualRoot = data.tree.root;
 | |
|   var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
 | |
|   var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
 | |
|   var sourceLayout = source.getLayout();
 | |
|   var sourceOldLayout = sourceSymbolEl ? {
 | |
|     x: sourceSymbolEl.position[0],
 | |
|     y: sourceSymbolEl.position[1],
 | |
|     rawX: sourceSymbolEl.__radialOldRawX,
 | |
|     rawY: sourceSymbolEl.__radialOldRawY
 | |
|   } : sourceLayout;
 | |
|   var targetLayout = node.getLayout();
 | |
| 
 | |
|   if (isInit) {
 | |
|     symbolEl = new SymbolClz(data, dataIndex, seriesScope);
 | |
|     symbolEl.attr('position', [sourceOldLayout.x, sourceOldLayout.y]);
 | |
|   } else {
 | |
|     symbolEl.updateData(data, dataIndex, seriesScope);
 | |
|   }
 | |
| 
 | |
|   symbolEl.__radialOldRawX = symbolEl.__radialRawX;
 | |
|   symbolEl.__radialOldRawY = symbolEl.__radialRawY;
 | |
|   symbolEl.__radialRawX = targetLayout.rawX;
 | |
|   symbolEl.__radialRawY = targetLayout.rawY;
 | |
|   group.add(symbolEl);
 | |
|   data.setItemGraphicEl(dataIndex, symbolEl);
 | |
|   graphic.updateProps(symbolEl, {
 | |
|     position: [targetLayout.x, targetLayout.y]
 | |
|   }, seriesModel);
 | |
|   var symbolPath = symbolEl.getSymbolPath();
 | |
| 
 | |
|   if (seriesScope.layout === 'radial') {
 | |
|     var realRoot = virtualRoot.children[0];
 | |
|     var rootLayout = realRoot.getLayout();
 | |
|     var length = realRoot.children.length;
 | |
|     var rad;
 | |
|     var isLeft;
 | |
| 
 | |
|     if (targetLayout.x === rootLayout.x && node.isExpand === true) {
 | |
|       var center = {};
 | |
|       center.x = (realRoot.children[0].getLayout().x + realRoot.children[length - 1].getLayout().x) / 2;
 | |
|       center.y = (realRoot.children[0].getLayout().y + realRoot.children[length - 1].getLayout().y) / 2;
 | |
|       rad = Math.atan2(center.y - rootLayout.y, center.x - rootLayout.x);
 | |
| 
 | |
|       if (rad < 0) {
 | |
|         rad = Math.PI * 2 + rad;
 | |
|       }
 | |
| 
 | |
|       isLeft = center.x < rootLayout.x;
 | |
| 
 | |
|       if (isLeft) {
 | |
|         rad = rad - Math.PI;
 | |
|       }
 | |
|     } else {
 | |
|       rad = Math.atan2(targetLayout.y - rootLayout.y, targetLayout.x - rootLayout.x);
 | |
| 
 | |
|       if (rad < 0) {
 | |
|         rad = Math.PI * 2 + rad;
 | |
|       }
 | |
| 
 | |
|       if (node.children.length === 0 || node.children.length !== 0 && node.isExpand === false) {
 | |
|         isLeft = targetLayout.x < rootLayout.x;
 | |
| 
 | |
|         if (isLeft) {
 | |
|           rad = rad - Math.PI;
 | |
|         }
 | |
|       } else {
 | |
|         isLeft = targetLayout.x > rootLayout.x;
 | |
| 
 | |
|         if (!isLeft) {
 | |
|           rad = rad - Math.PI;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     var textPosition = isLeft ? 'left' : 'right';
 | |
|     var rotate = seriesScope.labelModel.get('rotate');
 | |
|     var labelRotateRadian = rotate * (Math.PI / 180);
 | |
|     symbolPath.setStyle({
 | |
|       textPosition: seriesScope.labelModel.get('position') || textPosition,
 | |
|       textRotation: rotate == null ? -rad : labelRotateRadian,
 | |
|       textOrigin: 'center',
 | |
|       verticalAlign: 'middle'
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group, seriesScope);
 | |
| }
 | |
| 
 | |
| function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group, seriesScope) {
 | |
|   var edgeShape = seriesScope.edgeShape;
 | |
|   var edge = symbolEl.__edge;
 | |
| 
 | |
|   if (edgeShape === 'curve') {
 | |
|     if (node.parentNode && node.parentNode !== virtualRoot) {
 | |
|       if (!edge) {
 | |
|         edge = symbolEl.__edge = new graphic.BezierCurve({
 | |
|           shape: getEdgeShape(seriesScope, sourceOldLayout, sourceOldLayout),
 | |
|           style: zrUtil.defaults({
 | |
|             opacity: 0,
 | |
|             strokeNoScale: true
 | |
|           }, seriesScope.lineStyle)
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       graphic.updateProps(edge, {
 | |
|         shape: getEdgeShape(seriesScope, sourceLayout, targetLayout),
 | |
|         style: zrUtil.defaults({
 | |
|           opacity: 1
 | |
|         }, seriesScope.lineStyle)
 | |
|       }, seriesModel);
 | |
|     }
 | |
|   } else if (edgeShape === 'polyline') {
 | |
|     if (seriesScope.layout === 'orthogonal') {
 | |
|       if (node !== virtualRoot && node.children && node.children.length !== 0 && node.isExpand === true) {
 | |
|         var children = node.children;
 | |
|         var childPoints = [];
 | |
| 
 | |
|         for (var i = 0; i < children.length; i++) {
 | |
|           var childLayout = children[i].getLayout();
 | |
|           childPoints.push([childLayout.x, childLayout.y]);
 | |
|         }
 | |
| 
 | |
|         if (!edge) {
 | |
|           edge = symbolEl.__edge = new TreeShape({
 | |
|             shape: {
 | |
|               parentPoint: [targetLayout.x, targetLayout.y],
 | |
|               childPoints: [[targetLayout.x, targetLayout.y]],
 | |
|               orient: seriesScope.orient,
 | |
|               forkPosition: seriesScope.edgeForkPosition
 | |
|             },
 | |
|             style: zrUtil.defaults({
 | |
|               opacity: 0,
 | |
|               strokeNoScale: true
 | |
|             }, seriesScope.lineStyle)
 | |
|           });
 | |
|         }
 | |
| 
 | |
|         graphic.updateProps(edge, {
 | |
|           shape: {
 | |
|             parentPoint: [targetLayout.x, targetLayout.y],
 | |
|             childPoints: childPoints
 | |
|           },
 | |
|           style: zrUtil.defaults({
 | |
|             opacity: 1
 | |
|           }, seriesScope.lineStyle)
 | |
|         }, seriesModel);
 | |
|       }
 | |
|     } else {}
 | |
|   }
 | |
| 
 | |
|   group.add(edge);
 | |
| }
 | |
| 
 | |
| function removeNode(data, dataIndex, symbolEl, group, seriesModel, seriesScope) {
 | |
|   var node = data.tree.getNodeByDataIndex(dataIndex);
 | |
|   var virtualRoot = data.tree.root;
 | |
|   var itemModel = node.getModel();
 | |
|   var seriesScope = getTreeNodeStyle(node, itemModel, seriesScope);
 | |
|   var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
 | |
|   var edgeShape = seriesScope.edgeShape;
 | |
|   var sourceLayout;
 | |
| 
 | |
|   while (sourceLayout = source.getLayout(), sourceLayout == null) {
 | |
|     source = source.parentNode === virtualRoot ? source : source.parentNode || source;
 | |
|   }
 | |
| 
 | |
|   graphic.updateProps(symbolEl, {
 | |
|     position: [sourceLayout.x + 1, sourceLayout.y + 1]
 | |
|   }, seriesModel, function () {
 | |
|     group.remove(symbolEl);
 | |
|     data.setItemGraphicEl(dataIndex, null);
 | |
|   });
 | |
|   symbolEl.fadeOut(null, {
 | |
|     keepLabel: true
 | |
|   });
 | |
|   var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
 | |
|   var sourceEdge = sourceSymbolEl.__edge; // 1. when expand the sub tree, delete the children node should delete the edge of
 | |
|   // the source at the same time. because the polyline edge shape is only owned by the source.
 | |
|   // 2.when the node is the only children of the source, delete the node should delete the edge of
 | |
|   // the source at the same time. the same reason as above.
 | |
| 
 | |
|   var edge = symbolEl.__edge || (source.isExpand === false || source.children.length === 1 ? sourceEdge : undefined);
 | |
|   var edgeShape = seriesScope.edgeShape;
 | |
| 
 | |
|   if (edge) {
 | |
|     if (edgeShape === 'curve') {
 | |
|       graphic.updateProps(edge, {
 | |
|         shape: getEdgeShape(seriesScope, sourceLayout, sourceLayout),
 | |
|         style: {
 | |
|           opacity: 0
 | |
|         }
 | |
|       }, seriesModel, function () {
 | |
|         group.remove(edge);
 | |
|       });
 | |
|     } else if (edgeShape === 'polyline' && seriesScope.layout === 'orthogonal') {
 | |
|       graphic.updateProps(edge, {
 | |
|         shape: {
 | |
|           parentPoint: [sourceLayout.x, sourceLayout.y],
 | |
|           childPoints: [[sourceLayout.x, sourceLayout.y]]
 | |
|         },
 | |
|         style: {
 | |
|           opacity: 0
 | |
|         }
 | |
|       }, seriesModel, function () {
 | |
|         group.remove(edge);
 | |
|       });
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function getEdgeShape(seriesScope, sourceLayout, targetLayout) {
 | |
|   var cpx1;
 | |
|   var cpy1;
 | |
|   var cpx2;
 | |
|   var cpy2;
 | |
|   var orient = seriesScope.orient;
 | |
|   var x1;
 | |
|   var x2;
 | |
|   var y1;
 | |
|   var y2;
 | |
| 
 | |
|   if (seriesScope.layout === 'radial') {
 | |
|     x1 = sourceLayout.rawX;
 | |
|     y1 = sourceLayout.rawY;
 | |
|     x2 = targetLayout.rawX;
 | |
|     y2 = targetLayout.rawY;
 | |
|     var radialCoor1 = radialCoordinate(x1, y1);
 | |
|     var radialCoor2 = radialCoordinate(x1, y1 + (y2 - y1) * seriesScope.curvature);
 | |
|     var radialCoor3 = radialCoordinate(x2, y2 + (y1 - y2) * seriesScope.curvature);
 | |
|     var radialCoor4 = radialCoordinate(x2, y2);
 | |
|     return {
 | |
|       x1: radialCoor1.x,
 | |
|       y1: radialCoor1.y,
 | |
|       x2: radialCoor4.x,
 | |
|       y2: radialCoor4.y,
 | |
|       cpx1: radialCoor2.x,
 | |
|       cpy1: radialCoor2.y,
 | |
|       cpx2: radialCoor3.x,
 | |
|       cpy2: radialCoor3.y
 | |
|     };
 | |
|   } else {
 | |
|     x1 = sourceLayout.x;
 | |
|     y1 = sourceLayout.y;
 | |
|     x2 = targetLayout.x;
 | |
|     y2 = targetLayout.y;
 | |
| 
 | |
|     if (orient === 'LR' || orient === 'RL') {
 | |
|       cpx1 = x1 + (x2 - x1) * seriesScope.curvature;
 | |
|       cpy1 = y1;
 | |
|       cpx2 = x2 + (x1 - x2) * seriesScope.curvature;
 | |
|       cpy2 = y2;
 | |
|     }
 | |
| 
 | |
|     if (orient === 'TB' || orient === 'BT') {
 | |
|       cpx1 = x1;
 | |
|       cpy1 = y1 + (y2 - y1) * seriesScope.curvature;
 | |
|       cpx2 = x2;
 | |
|       cpy2 = y2 + (y1 - y2) * seriesScope.curvature;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     x1: x1,
 | |
|     y1: y1,
 | |
|     x2: x2,
 | |
|     y2: y2,
 | |
|     cpx1: cpx1,
 | |
|     cpy1: cpy1,
 | |
|     cpx2: cpx2,
 | |
|     cpy2: cpy2
 | |
|   };
 | |
| }
 | |
| 
 | |
| module.exports = _default; | 
