define(function (require) { var graphic = require('../../util/graphic'); var modelUtil = require('../../util/model'); var zrUtil = require('zrender/core/util'); var SankeyShape = graphic.extendShape({ shape: { x1: 0, y1: 0, x2: 0, y2: 0, cpx1: 0, cpy1: 0, cpx2: 0, cpy2: 0, extent: 0 }, buildPath: function (ctx, shape) { var halfExtent = shape.extent / 2; ctx.moveTo(shape.x1, shape.y1 - halfExtent); ctx.bezierCurveTo( shape.cpx1, shape.cpy1 - halfExtent, shape.cpx2, shape.cpy2 - halfExtent, shape.x2, shape.y2 - halfExtent ); ctx.lineTo(shape.x2, shape.y2 + halfExtent); ctx.bezierCurveTo( shape.cpx2, shape.cpy2 + halfExtent, shape.cpx1, shape.cpy1 + halfExtent, shape.x1, shape.y1 + halfExtent ); ctx.closePath(); } }); return require('../../echarts').extendChartView({ type: 'sankey', /** * @private * @type {module:echarts/chart/sankey/SankeySeries} */ _model: null, render: function(seriesModel, ecModel, api) { var graph = seriesModel.getGraph(); var group = this.group; var layoutInfo = seriesModel.layoutInfo; this._model = seriesModel; group.removeAll(); group.position = [layoutInfo.x, layoutInfo.y]; var edgeData = graph.edgeData; var rawOption = seriesModel.option; var formatModel = modelUtil.createDataFormatModel(seriesModel, edgeData); formatModel.formatTooltip = function (dataIndex) { var params = this.getDataParams(dataIndex); var rawDataOpt = params.data; var html = rawDataOpt.source + ' -- ' + rawDataOpt.target; if (params.value) { html += ':' + params.value; } return html; }; // generate a rect for each node graph.eachNode(function (node) { var layout = node.getLayout(); var itemModel = node.getModel(); var labelModel = itemModel.getModel('label.normal'); var textStyleModel = labelModel.getModel('textStyle'); var labelHoverModel = itemModel.getModel('label.emphasis'); var textStyleHoverModel = labelHoverModel.getModel('textStyle'); var rect = new graphic.Rect({ shape: { x: layout.x, y: layout.y, width: node.getLayout().dx, height: node.getLayout().dy }, style: { // Get formatted label in label.normal option. Use node id if it is not specified text: labelModel.get('show') ? seriesModel.getFormattedLabel(node.dataIndex, 'normal') || node.id // Use empty string to hide the label : '', textFont: textStyleModel.getFont(), textFill: textStyleModel.getTextColor(), textPosition: labelModel.get('position') } }); rect.setStyle(zrUtil.defaults( { fill: node.getVisual('color') }, itemModel.getModel('itemStyle.normal').getItemStyle() )); graphic.setHoverStyle(rect, zrUtil.extend( node.getModel('itemStyle.emphasis'), { text: labelHoverModel.get('show') ? seriesModel.getFormattedLabel(node.dataIndex, 'emphasis') || node.id : '', textFont: textStyleHoverModel.getFont(), textFill: textStyleHoverModel.getTextColor(), textPosition: labelHoverModel.get('position') } )); group.add(rect); }); // generate a bezire Curve for each edge graph.eachEdge(function (edge) { var curve = new SankeyShape(); curve.dataIndex = edge.dataIndex; curve.dataModel = formatModel; var lineStyleModel = edge.getModel('lineStyle.normal'); var curvature = lineStyleModel.get('curveness'); var n1Layout = edge.node1.getLayout(); var n2Layout = edge.node2.getLayout(); var edgeLayout = edge.getLayout(); curve.shape.extent = Math.max(1, edgeLayout.dy); var x1 = n1Layout.x + n1Layout.dx; var y1 = n1Layout.y + edgeLayout.sy + edgeLayout.dy / 2; var x2 = n2Layout.x; var y2 = n2Layout.y + edgeLayout.ty + edgeLayout.dy /2; var cpx1 = x1 * (1 - curvature) + x2 * curvature; var cpy1 = y1; var cpx2 = x1 * curvature + x2 * (1 - curvature); var cpy2 = y2; curve.setShape({ x1: x1, y1: y1, x2: x2, y2: y2, cpx1: cpx1, cpy1: cpy1, cpx2: cpx2, cpy2: cpy2 }); curve.setStyle(lineStyleModel.getItemStyle()); graphic.setHoverStyle(curve, edge.getModel('lineStyle.emphasis').getItemStyle()); group.add(curve); }); if (!this._data) { group.setClipPath(createGridClipShape(group.getBoundingRect(), seriesModel, function () { group.removeClipPath(); })); } this._data = seriesModel.getData(); } }); //add animation to the view function createGridClipShape(rect, seriesModel, cb) { var rectEl = new graphic.Rect({ shape: { x: rect.x - 10, y: rect.y - 10, width: 0, height: rect.height + 20 } }); graphic.initProps(rectEl, { shape: { width: rect.width + 20, height: rect.height + 20 } }, seriesModel, cb); return rectEl; } });