import * as echarts from 'echarts/lib/echarts'; import createGraphFromNodeEdge from './createGraphFromNodeEdge'; import formatUtil from '../../util/format'; var GraphSeries = echarts.SeriesModel.extend({ type: 'series.graphGL', visualStyleAccessPath: 'itemStyle', hasSymbolVisual: true, init: function (option) { GraphSeries.superApply(this, 'init', arguments); // Provide data for legend select this.legendDataProvider = function () { return this._categoriesData; }; this._updateCategoriesData(); }, mergeOption: function (option) { GraphSeries.superApply(this, 'mergeOption', arguments); this._updateCategoriesData(); }, getFormattedLabel: function (dataIndex, status, dataType, dimIndex) { var text = formatUtil.getFormattedLabel(this, dataIndex, status, dataType, dimIndex); if (text == null) { var data = this.getData(); var lastDim = data.dimensions[data.dimensions.length - 1]; text = data.get(lastDim, dataIndex); } return text; }, getInitialData: function (option, ecModel) { var edges = option.edges || option.links || []; var nodes = option.data || option.nodes || []; var self = this; if (nodes && edges) { return createGraphFromNodeEdge(nodes, edges, this, true, beforeLink).data; } function beforeLink(nodeData, edgeData) { // Overwrite nodeData.getItemModel to nodeData.wrapMethod('getItemModel', function (model) { const categoriesModels = self._categoriesModels; const categoryIdx = model.getShallow('category'); const categoryModel = categoriesModels[categoryIdx]; if (categoryModel) { categoryModel.parentModel = model.parentModel; model.parentModel = categoryModel; } return model; }); // TODO Inherit resolveParentPath by default in Model#getModel? const oldGetModel = ecModel.getModel([]).getModel; function newGetModel(path, parentModel) { const model = oldGetModel.call(this, path, parentModel); model.resolveParentPath = resolveParentPath; return model; } edgeData.wrapMethod('getItemModel', function (model) { model.resolveParentPath = resolveParentPath; model.getModel = newGetModel; return model; }); function resolveParentPath(pathArr) { if (pathArr && (pathArr[0] === 'label' || pathArr[1] === 'label')) { const newPathArr = pathArr.slice(); if (pathArr[0] === 'label') { newPathArr[0] = 'edgeLabel'; } else if (pathArr[1] === 'label') { newPathArr[1] = 'edgeLabel'; } return newPathArr; } return pathArr; } } }, /** * @return {module:echarts/data/Graph} */ getGraph: function () { return this.getData().graph; }, /** * @return {module:echarts/data/List} */ getEdgeData: function () { return this.getGraph().edgeData; }, /** * @return {module:echarts/data/List} */ getCategoriesData: function () { return this._categoriesData; }, /** * @override */ formatTooltip: function (dataIndex, multipleSeries, dataType) { if (dataType === 'edge') { var nodeData = this.getData(); var params = this.getDataParams(dataIndex, dataType); var edge = nodeData.graph.getEdgeByIndex(dataIndex); var sourceName = nodeData.getName(edge.node1.dataIndex); var targetName = nodeData.getName(edge.node2.dataIndex); var html = []; sourceName != null && html.push(sourceName); targetName != null && html.push(targetName); html = echarts.format.encodeHTML(html.join(' > ')); if (params.value) { html += ' : ' + echarts.format.encodeHTML(params.value); } return html; } else { // dataType === 'node' or empty return GraphSeries.superApply(this, 'formatTooltip', arguments); } }, _updateCategoriesData: function () { var categories = (this.option.categories || []).map(function (category) { // Data must has value return category.value != null ? category : Object.assign({ value: 0 }, category); }); var categoriesData = new echarts.List(['value'], this); categoriesData.initData(categories); this._categoriesData = categoriesData; this._categoriesModels = categoriesData.mapArray(function (idx) { return categoriesData.getItemModel(idx, true); }); }, setView: function (payload) { if (payload.zoom != null) { this.option.zoom = payload.zoom; } if (payload.offset != null) { this.option.offset = payload.offset; } }, setNodePosition: function (points) { for (var i = 0; i < points.length / 2; i++) { var x = points[i * 2]; var y = points[i * 2 + 1]; var opt = this.getData().getRawDataItem(i); opt.x = x; opt.y = y; } }, isAnimationEnabled: function () { return GraphSeries.superCall(this, 'isAnimationEnabled') // Not enable animation when do force layout && !(this.get('layout') === 'force' && this.get('force.layoutAnimation')); }, defaultOption: { zlevel: 10, z: 2, legendHoverLink: true, // Only support forceAtlas2 layout: 'forceAtlas2', // Configuration of force directed layout forceAtlas2: { initLayout: null, GPU: true, steps: 1, // barnesHutOptimize // Maxp layout steps. maxSteps: 1000, repulsionByDegree: true, linLogMode: false, strongGravityMode: false, gravity: 1.0, // scaling: 1.0, edgeWeightInfluence: 1.0, // Edge weight range. edgeWeight: [1, 4], // Node weight range. nodeWeight: [1, 4], // jitterTolerence: 0.1, preventOverlap: false, gravityCenter: null }, focusNodeAdjacency: true, focusNodeAdjacencyOn: 'mouseover', left: 'center', top: 'center', // right: null, // bottom: null, // width: '80%', // height: '80%', symbol: 'circle', symbolSize: 5, roam: false, // Default on center of graph center: null, zoom: 1, // categories: [], // data: [] // Or // nodes: [] // // links: [] // Or // edges: [] label: { show: false, formatter: '{b}', position: 'right', distance: 5, textStyle: { fontSize: 14 } }, itemStyle: {}, lineStyle: { color: '#aaa', width: 1, opacity: 0.5 }, emphasis: { label: { show: true } }, animation: false } }); export default GraphSeries;