123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- define('echarts/chart/tree', [
- 'require',
- './base',
- '../util/shape/Icon',
- 'zrender/shape/Image',
- 'zrender/shape/Line',
- 'zrender/shape/BezierCurve',
- '../layout/Tree',
- '../data/Tree',
- '../config',
- '../util/ecData',
- 'zrender/config',
- 'zrender/tool/event',
- 'zrender/tool/util',
- '../chart'
- ], function (require) {
- var ChartBase = require('./base');
- var GOLDEN_SECTION = 0.618;
- var IconShape = require('../util/shape/Icon');
- var ImageShape = require('zrender/shape/Image');
- var LineShape = require('zrender/shape/Line');
- var BezierCurveShape = require('zrender/shape/BezierCurve');
- var TreeLayout = require('../layout/Tree');
- var TreeData = require('../data/Tree');
- var ecConfig = require('../config');
- ecConfig.tree = {
- zlevel: 1,
- z: 2,
- calculable: false,
- clickable: true,
- rootLocation: {},
- orient: 'vertical',
- symbol: 'circle',
- symbolSize: 20,
- nodePadding: 30,
- layerPadding: 100,
- itemStyle: {
- normal: {
- label: { show: true },
- lineStyle: {
- width: 1,
- color: '#777',
- type: 'curve'
- }
- },
- emphasis: {}
- }
- };
- var ecData = require('../util/ecData');
- var zrConfig = require('zrender/config');
- var zrEvent = require('zrender/tool/event');
- var zrUtil = require('zrender/tool/util');
- function Tree(ecTheme, messageCenter, zr, option, myChart) {
- ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart);
- this.refresh(option);
- }
- Tree.prototype = {
- type: ecConfig.CHART_TYPE_TREE,
- _buildShape: function (series, seriesIndex) {
- var data = series.data[0];
- this.tree = TreeData.fromOptionData(data.name, data.children);
- this.tree.root.data = data;
- this._setTreeShape(series);
- this.tree.traverse(function (treeNode) {
- this._buildItem(treeNode, series, seriesIndex);
- if (treeNode.children.length > 0) {
- this._buildLink(treeNode, series);
- }
- }, this);
- var panable = series.roam === true || series.roam === 'move';
- var zoomable = series.roam === true || series.roam === 'scale';
- this.zr.modLayer(this.getZlevelBase(), {
- panable: panable,
- zoomable: zoomable
- });
- if (this.query('markPoint.effect.show') || this.query('markLine.effect.show')) {
- this.zr.modLayer(ecConfig.EFFECT_ZLEVEL, {
- panable: panable,
- zoomable: zoomable
- });
- }
- this.addShapeList();
- },
- _buildItem: function (treeNode, serie, seriesIndex) {
- var queryTarget = [
- treeNode.data,
- serie
- ];
- var symbol = this.deepQuery(queryTarget, 'symbol');
- var normal = this.deepMerge(queryTarget, 'itemStyle.normal') || {};
- var emphasis = this.deepMerge(queryTarget, 'itemStyle.emphasis') || {};
- var normalColor = normal.color || this.zr.getColor();
- var emphasisColor = emphasis.color || this.zr.getColor();
- var angle = -treeNode.layout.angle || 0;
- if (treeNode.id === this.tree.root.id) {
- angle = 0;
- }
- var textPosition = 'right';
- if (Math.abs(angle) >= Math.PI / 2 && Math.abs(angle) < Math.PI * 3 / 2) {
- angle += Math.PI;
- textPosition = 'left';
- }
- var rotation = [
- angle,
- treeNode.layout.position[0],
- treeNode.layout.position[1]
- ];
- var shape = new IconShape({
- zlevel: this.getZlevelBase(),
- z: this.getZBase() + 1,
- rotation: rotation,
- clickable: this.deepQuery(queryTarget, 'clickable'),
- style: {
- x: treeNode.layout.position[0] - treeNode.layout.width * 0.5,
- y: treeNode.layout.position[1] - treeNode.layout.height * 0.5,
- width: treeNode.layout.width,
- height: treeNode.layout.height,
- iconType: symbol,
- color: normalColor,
- brushType: 'both',
- lineWidth: normal.borderWidth,
- strokeColor: normal.borderColor
- },
- highlightStyle: {
- color: emphasisColor,
- lineWidth: emphasis.borderWidth,
- strokeColor: emphasis.borderColor
- }
- });
- if (shape.style.iconType.match('image')) {
- shape.style.image = shape.style.iconType.replace(new RegExp('^image:\\/\\/'), '');
- shape = new ImageShape({
- rotation: rotation,
- style: shape.style,
- highlightStyle: shape.highlightStyle,
- clickable: shape.clickable,
- zlevel: this.getZlevelBase(),
- z: this.getZBase()
- });
- }
- if (this.deepQuery(queryTarget, 'itemStyle.normal.label.show')) {
- shape.style.text = treeNode.data.label == null ? treeNode.id : treeNode.data.label;
- shape.style.textPosition = this.deepQuery(queryTarget, 'itemStyle.normal.label.position');
- if (serie.orient === 'radial' && shape.style.textPosition !== 'inside') {
- shape.style.textPosition = textPosition;
- }
- shape.style.textColor = this.deepQuery(queryTarget, 'itemStyle.normal.label.textStyle.color');
- shape.style.textFont = this.getFont(this.deepQuery(queryTarget, 'itemStyle.normal.label.textStyle') || {});
- }
- if (this.deepQuery(queryTarget, 'itemStyle.emphasis.label.show')) {
- shape.highlightStyle.textPosition = this.deepQuery(queryTarget, 'itemStyle.emphasis.label.position');
- shape.highlightStyle.textColor = this.deepQuery(queryTarget, 'itemStyle.emphasis.label.textStyle.color');
- shape.highlightStyle.textFont = this.getFont(this.deepQuery(queryTarget, 'itemStyle.emphasis.label.textStyle') || {});
- }
- ecData.pack(shape, serie, seriesIndex, treeNode.data, 0, treeNode.id);
- this.shapeList.push(shape);
- },
- _buildLink: function (parentNode, serie) {
- var lineStyle = serie.itemStyle.normal.lineStyle;
- if (lineStyle.type === 'broken') {
- this._buildBrokenLine(parentNode, lineStyle, serie);
- return;
- }
- for (var i = 0; i < parentNode.children.length; i++) {
- var xStart = parentNode.layout.position[0];
- var yStart = parentNode.layout.position[1];
- var xEnd = parentNode.children[i].layout.position[0];
- var yEnd = parentNode.children[i].layout.position[1];
- switch (lineStyle.type) {
- case 'curve':
- this._buildBezierCurve(parentNode, parentNode.children[i], lineStyle, serie);
- break;
- case 'broken':
- break;
- default:
- var shape = this._getLine(xStart, yStart, xEnd, yEnd, lineStyle);
- this.shapeList.push(shape);
- }
- }
- },
- _buildBrokenLine: function (parentNode, lineStyle, serie) {
- var solidLineStyle = zrUtil.clone(lineStyle);
- solidLineStyle.type = 'solid';
- var shapes = [];
- var xStart = parentNode.layout.position[0];
- var yStart = parentNode.layout.position[1];
- var orient = serie.orient;
- var yEnd = parentNode.children[0].layout.position[1];
- var xMiddle = xStart;
- var yMiddle = yStart + (yEnd - yStart) * (1 - GOLDEN_SECTION);
- var xMiddleStart = parentNode.children[0].layout.position[0];
- var yMiddleStart = yMiddle;
- var xMiddleEnd = parentNode.children[parentNode.children.length - 1].layout.position[0];
- var yMiddleEnd = yMiddle;
- if (orient === 'horizontal') {
- var xEnd = parentNode.children[0].layout.position[0];
- xMiddle = xStart + (xEnd - xStart) * (1 - GOLDEN_SECTION);
- yMiddle = yStart;
- xMiddleStart = xMiddle;
- yMiddleStart = parentNode.children[0].layout.position[1];
- xMiddleEnd = xMiddle;
- yMiddleEnd = parentNode.children[parentNode.children.length - 1].layout.position[1];
- }
- shapes.push(this._getLine(xStart, yStart, xMiddle, yMiddle, solidLineStyle));
- shapes.push(this._getLine(xMiddleStart, yMiddleStart, xMiddleEnd, yMiddleEnd, solidLineStyle));
- for (var i = 0; i < parentNode.children.length; i++) {
- xEnd = parentNode.children[i].layout.position[0];
- yEnd = parentNode.children[i].layout.position[1];
- if (orient === 'horizontal') {
- yMiddleStart = yEnd;
- } else {
- xMiddleStart = xEnd;
- }
- shapes.push(this._getLine(xMiddleStart, yMiddleStart, xEnd, yEnd, solidLineStyle));
- }
- this.shapeList = this.shapeList.concat(shapes);
- },
- _getLine: function (xStart, yStart, xEnd, yEnd, lineStyle) {
- if (xStart === xEnd) {
- xStart = xEnd = this.subPixelOptimize(xStart, lineStyle.width);
- }
- if (yStart === yEnd) {
- yStart = yEnd = this.subPixelOptimize(yStart, lineStyle.width);
- }
- return new LineShape({
- zlevel: this.getZlevelBase(),
- hoverable: false,
- style: zrUtil.merge({
- xStart: xStart,
- yStart: yStart,
- xEnd: xEnd,
- yEnd: yEnd,
- lineType: lineStyle.type,
- strokeColor: lineStyle.color,
- lineWidth: lineStyle.width
- }, lineStyle, true)
- });
- },
- _buildBezierCurve: function (parentNode, treeNode, lineStyle, serie) {
- var offsetRatio = GOLDEN_SECTION;
- var orient = serie.orient;
- var xStart = parentNode.layout.position[0];
- var yStart = parentNode.layout.position[1];
- var xEnd = treeNode.layout.position[0];
- var yEnd = treeNode.layout.position[1];
- var cpX1 = xStart;
- var cpY1 = (yEnd - yStart) * offsetRatio + yStart;
- var cpX2 = xEnd;
- var cpY2 = (yEnd - yStart) * (1 - offsetRatio) + yStart;
- if (orient === 'horizontal') {
- cpX1 = (xEnd - xStart) * offsetRatio + xStart;
- cpY1 = yStart;
- cpX2 = (xEnd - xStart) * (1 - offsetRatio) + xStart;
- cpY2 = yEnd;
- } else if (orient === 'radial') {
- if (parentNode.id === this.tree.root.id) {
- cpX1 = (xEnd - xStart) * offsetRatio + xStart;
- cpY1 = (yEnd - yStart) * offsetRatio + yStart;
- cpX2 = (xEnd - xStart) * (1 - offsetRatio) + xStart;
- cpY2 = (yEnd - yStart) * (1 - offsetRatio) + yStart;
- } else {
- var xStartOrigin = parentNode.layout.originPosition[0];
- var yStartOrigin = parentNode.layout.originPosition[1];
- var xEndOrigin = treeNode.layout.originPosition[0];
- var yEndOrigin = treeNode.layout.originPosition[1];
- var rootX = this.tree.root.layout.position[0];
- var rootY = this.tree.root.layout.position[1];
- cpX1 = xStartOrigin;
- cpY1 = (yEndOrigin - yStartOrigin) * offsetRatio + yStartOrigin;
- cpX2 = xEndOrigin;
- cpY2 = (yEndOrigin - yStartOrigin) * (1 - offsetRatio) + yStartOrigin;
- var rad = (cpX1 - this.minX) / this.width * Math.PI * 2;
- cpX1 = cpY1 * Math.cos(rad) + rootX;
- cpY1 = cpY1 * Math.sin(rad) + rootY;
- rad = (cpX2 - this.minX) / this.width * Math.PI * 2;
- cpX2 = cpY2 * Math.cos(rad) + rootX;
- cpY2 = cpY2 * Math.sin(rad) + rootY;
- }
- }
- var shape = new BezierCurveShape({
- zlevel: this.getZlevelBase(),
- hoverable: false,
- style: zrUtil.merge({
- xStart: xStart,
- yStart: yStart,
- cpX1: cpX1,
- cpY1: cpY1,
- cpX2: cpX2,
- cpY2: cpY2,
- xEnd: xEnd,
- yEnd: yEnd,
- strokeColor: lineStyle.color,
- lineWidth: lineStyle.width
- }, lineStyle, true)
- });
- this.shapeList.push(shape);
- },
- _setTreeShape: function (serie) {
- var treeLayout = new TreeLayout({
- nodePadding: serie.nodePadding,
- layerPadding: serie.layerPadding
- });
- this.tree.traverse(function (treeNode) {
- var queryTarget = [
- treeNode.data,
- serie
- ];
- var symbolSize = this.deepQuery(queryTarget, 'symbolSize');
- if (typeof symbolSize === 'number') {
- symbolSize = [
- symbolSize,
- symbolSize
- ];
- }
- treeNode.layout = {
- width: symbolSize[0],
- height: symbolSize[1]
- };
- }, this);
- treeLayout.run(this.tree);
- var orient = serie.orient;
- var rootX = serie.rootLocation.x;
- var rootY = serie.rootLocation.y;
- var zrWidth = this.zr.getWidth();
- var zrHeight = this.zr.getHeight();
- if (rootX === 'center') {
- rootX = zrWidth * 0.5;
- } else {
- rootX = this.parsePercent(rootX, zrWidth);
- }
- if (rootY === 'center') {
- rootY = zrHeight * 0.5;
- } else {
- rootY = this.parsePercent(rootY, zrHeight);
- }
- rootY = this.parsePercent(rootY, zrHeight);
- if (orient === 'horizontal') {
- rootX = isNaN(rootX) ? 10 : rootX;
- rootY = isNaN(rootY) ? zrHeight * 0.5 : rootY;
- }
- if (orient === 'radial') {
- rootX = isNaN(rootX) ? zrWidth * 0.5 : rootX;
- rootY = isNaN(rootY) ? zrHeight * 0.5 : rootY;
- } else {
- rootX = isNaN(rootX) ? zrWidth * 0.5 : rootX;
- rootY = isNaN(rootY) ? 10 : rootY;
- }
- var originRootX = this.tree.root.layout.position[0];
- if (orient === 'radial') {
- var minX = Infinity;
- var maxX = 0;
- var maxWidth = 0;
- this.tree.traverse(function (treeNode) {
- maxX = Math.max(maxX, treeNode.layout.position[0]);
- minX = Math.min(minX, treeNode.layout.position[0]);
- maxWidth = Math.max(maxWidth, treeNode.layout.width);
- });
- this.width = maxX - minX + 2 * maxWidth;
- this.minX = minX;
- }
- this.tree.traverse(function (treeNode) {
- var x;
- var y;
- if (orient === 'vertical' && serie.direction === 'inverse') {
- x = treeNode.layout.position[0] - originRootX + rootX;
- y = rootY - treeNode.layout.position[1];
- } else if (orient === 'vertical') {
- x = treeNode.layout.position[0] - originRootX + rootX;
- y = treeNode.layout.position[1] + rootY;
- } else if (orient === 'horizontal' && serie.direction === 'inverse') {
- y = treeNode.layout.position[0] - originRootX + rootY;
- x = rootX - treeNode.layout.position[1];
- } else if (orient === 'horizontal') {
- y = treeNode.layout.position[0] - originRootX + rootY;
- x = treeNode.layout.position[1] + rootX;
- } else {
- x = treeNode.layout.position[0];
- y = treeNode.layout.position[1];
- treeNode.layout.originPosition = [
- x,
- y
- ];
- var r = y;
- var angle = (x - minX) / this.width * Math.PI * 2;
- x = r * Math.cos(angle) + rootX;
- y = r * Math.sin(angle) + rootY;
- treeNode.layout.angle = angle;
- }
- treeNode.layout.position[0] = x;
- treeNode.layout.position[1] = y;
- }, this);
- },
- refresh: function (newOption) {
- this.clear();
- if (newOption) {
- this.option = newOption;
- this.series = this.option.series;
- }
- var series = this.series;
- var legend = this.component.legend;
- for (var i = 0; i < series.length; i++) {
- if (series[i].type === ecConfig.CHART_TYPE_TREE) {
- series[i] = this.reformOption(series[i]);
- var seriesName = series[i].name || '';
- this.selectedMap[seriesName] = legend ? legend.isSelected(seriesName) : true;
- if (!this.selectedMap[seriesName]) {
- continue;
- }
- this._buildSeries(series[i], i);
- }
- }
- },
- _buildSeries: function (series, seriesIndex) {
- this._buildShape(series, seriesIndex);
- }
- };
- zrUtil.inherits(Tree, ChartBase);
- require('../chart').define('tree', Tree);
- return Tree;
- });define('echarts/layout/Tree', [
- 'require',
- 'zrender/tool/vector'
- ], function (require) {
- var vec2 = require('zrender/tool/vector');
- function TreeLayout(opts) {
- opts = opts || {};
- this.nodePadding = opts.nodePadding || 30;
- this.layerPadding = opts.layerPadding || 100;
- this._layerOffsets = [];
- this._layers = [];
- }
- TreeLayout.prototype.run = function (tree) {
- this._layerOffsets.length = 0;
- for (var i = 0; i < tree.root.height + 1; i++) {
- this._layerOffsets[i] = 0;
- this._layers[i] = [];
- }
- this._updateNodeXPosition(tree.root);
- var root = tree.root;
- this._updateNodeYPosition(root, 0, root.layout.height);
- };
- TreeLayout.prototype._updateNodeXPosition = function (node) {
- var minX = Infinity;
- var maxX = -Infinity;
- node.layout.position = node.layout.position || vec2.create();
- for (var i = 0; i < node.children.length; i++) {
- var child = node.children[i];
- this._updateNodeXPosition(child);
- var x = child.layout.position[0];
- if (x < minX) {
- minX = x;
- }
- if (x > maxX) {
- maxX = x;
- }
- }
- if (node.children.length > 0) {
- node.layout.position[0] = (minX + maxX) / 2;
- } else {
- node.layout.position[0] = 0;
- }
- var off = this._layerOffsets[node.depth] || 0;
- if (off > node.layout.position[0]) {
- var shift = off - node.layout.position[0];
- this._shiftSubtree(node, shift);
- for (var i = node.depth + 1; i < node.height + node.depth; i++) {
- this._layerOffsets[i] += shift;
- }
- }
- this._layerOffsets[node.depth] = node.layout.position[0] + node.layout.width + this.nodePadding;
- this._layers[node.depth].push(node);
- };
- TreeLayout.prototype._shiftSubtree = function (root, offset) {
- root.layout.position[0] += offset;
- for (var i = 0; i < root.children.length; i++) {
- this._shiftSubtree(root.children[i], offset);
- }
- };
- TreeLayout.prototype._updateNodeYPosition = function (node, y, prevLayerHeight) {
- node.layout.position[1] = y;
- var layerHeight = 0;
- for (var i = 0; i < node.children.length; i++) {
- layerHeight = Math.max(node.children[i].layout.height, layerHeight);
- }
- var layerPadding = this.layerPadding;
- if (typeof layerPadding === 'function') {
- layerPadding = layerPadding(node.depth);
- }
- for (var i = 0; i < node.children.length; i++) {
- this._updateNodeYPosition(node.children[i], y + layerPadding + prevLayerHeight, layerHeight);
- }
- };
- return TreeLayout;
- });define('echarts/data/Tree', [
- 'require',
- 'zrender/tool/util'
- ], function (require) {
- var zrUtil = require('zrender/tool/util');
- function TreeNode(id, data) {
- this.id = id;
- this.depth = 0;
- this.height = 0;
- this.children = [];
- this.parent = null;
- this.data = data || null;
- }
- TreeNode.prototype.add = function (child) {
- var children = this.children;
- if (child.parent === this) {
- return;
- }
- children.push(child);
- child.parent = this;
- };
- TreeNode.prototype.remove = function (child) {
- var children = this.children;
- var idx = zrUtil.indexOf(children, child);
- if (idx >= 0) {
- children.splice(idx, 1);
- child.parent = null;
- }
- };
- TreeNode.prototype.traverse = function (cb, context) {
- cb.call(context, this);
- for (var i = 0; i < this.children.length; i++) {
- this.children[i].traverse(cb, context);
- }
- };
- TreeNode.prototype.updateDepthAndHeight = function (depth) {
- var height = 0;
- this.depth = depth;
- for (var i = 0; i < this.children.length; i++) {
- var child = this.children[i];
- child.updateDepthAndHeight(depth + 1);
- if (child.height > height) {
- height = child.height;
- }
- }
- this.height = height + 1;
- };
- TreeNode.prototype.getNodeById = function (id) {
- if (this.id === id) {
- return this;
- }
- for (var i = 0; i < this.children.length; i++) {
- var res = this.children[i].getNodeById(id);
- if (res) {
- return res;
- }
- }
- };
- function Tree(id) {
- this.root = new TreeNode(id);
- }
- Tree.prototype.traverse = function (cb, context) {
- this.root.traverse(cb, context);
- };
- Tree.prototype.getSubTree = function (id) {
- var root = this.getNodeById(id);
- if (root) {
- var tree = new Tree(root.id);
- tree.root = root;
- return tree;
- }
- };
- Tree.prototype.getNodeById = function (id) {
- return this.root.getNodeById(id);
- };
- Tree.fromOptionData = function (id, data) {
- var tree = new Tree(id);
- var rootNode = tree.root;
- rootNode.data = {
- name: id,
- children: data
- };
- function buildHierarchy(dataNode, parentNode) {
- var node = new TreeNode(dataNode.name, dataNode);
- parentNode.add(node);
- var children = dataNode.children;
- if (children) {
- for (var i = 0; i < children.length; i++) {
- buildHierarchy(children[i], node);
- }
- }
- }
- for (var i = 0; i < data.length; i++) {
- buildHierarchy(data[i], rootNode);
- }
- tree.root.updateDepthAndHeight(0);
- return tree;
- };
- Tree.fromGraph = function (graph) {
- function buildHierarchy(root) {
- var graphNode = graph.getNodeById(root.id);
- for (var i = 0; i < graphNode.outEdges.length; i++) {
- var edge = graphNode.outEdges[i];
- var childTreeNode = treeNodesMap[edge.node2.id];
- root.children.push(childTreeNode);
- buildHierarchy(childTreeNode);
- }
- }
- var treeMap = {};
- var treeNodesMap = {};
- for (var i = 0; i < graph.nodes.length; i++) {
- var node = graph.nodes[i];
- var treeNode;
- if (node.inDegree() === 0) {
- treeMap[node.id] = new Tree(node.id);
- treeNode = treeMap[node.id].root;
- } else {
- treeNode = new TreeNode(node.id);
- }
- treeNode.data = node.data;
- treeNodesMap[node.id] = treeNode;
- }
- var treeList = [];
- for (var id in treeMap) {
- buildHierarchy(treeMap[id].root);
- treeMap[id].root.updateDepthAndHeight(0);
- treeList.push(treeMap[id]);
- }
- return treeList;
- };
- return Tree;
- });
|