define('echarts/chart/venn', [ 'require', './base', 'zrender/shape/Text', 'zrender/shape/Circle', 'zrender/shape/Path', '../config', '../util/ecData', 'zrender/tool/util', '../chart' ], function (require) { var ChartBase = require('./base'); var TextShape = require('zrender/shape/Text'); var CircleShape = require('zrender/shape/Circle'); var PathShape = require('zrender/shape/Path'); var ecConfig = require('../config'); ecConfig.venn = { zlevel: 0, z: 1, calculable: false }; var ecData = require('../util/ecData'); var zrUtil = require('zrender/tool/util'); function Venn(ecTheme, messageCenter, zr, option, myChart) { ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart); this.refresh(option); } Venn.prototype = { type: ecConfig.CHART_TYPE_VENN, _buildShape: function () { this.selectedMap = {}; this._symbol = this.option.symbolList; this._queryTarget; this._dropBoxList = []; this._vennDataCounter = 0; var series = this.series; var legend = this.component.legend; for (var i = 0; i < series.length; i++) { if (series[i].type === ecConfig.CHART_TYPE_VENN) { series[i] = this.reformOption(series[i]); var serieName = series[i].name || ''; this.selectedMap[serieName] = legend ? legend.isSelected(serieName) : true; if (!this.selectedMap[serieName]) { continue; } this._buildVenn(i); } } this.addShapeList(); }, _buildVenn: function (seriesIndex) { var r0; var r1; var serie = this.series[seriesIndex]; var data = serie.data; if (data[0].value > data[1].value) { r0 = this.zr.getHeight() / 3; r1 = r0 * Math.sqrt(data[1].value) / Math.sqrt(data[0].value); } else { r1 = this.zr.getHeight() / 3; r0 = r1 * Math.sqrt(data[0].value) / Math.sqrt(data[1].value); } var x0 = this.zr.getWidth() / 2 - r0; var coincideLengthAnchor = (r0 + r1) / 2 * Math.sqrt(data[2].value) / Math.sqrt((data[0].value + data[1].value) / 2); var coincideLength = r0 + r1; if (data[2].value !== 0) { coincideLength = this._getCoincideLength(data[0].value, data[1].value, data[2].value, r0, r1, coincideLengthAnchor, Math.abs(r0 - r1), r0 + r1); } var x1 = x0 + coincideLength; var y = this.zr.getHeight() / 2; this._buildItem(seriesIndex, 0, data[0], x0, y, r0); this._buildItem(seriesIndex, 1, data[1], x1, y, r1); if (data[2].value !== 0 && data[2].value !== data[0].value && data[2].value !== data[1].value) { var xLeft = (r0 * r0 - r1 * r1) / (2 * coincideLength) + coincideLength / 2; var xRight = coincideLength / 2 - (r0 * r0 - r1 * r1) / (2 * coincideLength); var h = Math.sqrt(r0 * r0 - xLeft * xLeft); var rightLargeArcFlag = 0; var leftLargeArcFlag = 0; if (data[0].value > data[1].value && x1 < x0 + xLeft) { leftLargeArcFlag = 1; } if (data[0].value < data[1].value && x1 < x0 + xRight) { rightLargeArcFlag = 1; } this._buildCoincideItem(seriesIndex, 2, data[2], x0 + xLeft, y - h, y + h, r0, r1, rightLargeArcFlag, leftLargeArcFlag); } }, _getCoincideLength: function (value0, value1, value2, r0, r1, coincideLengthAnchor, coincideLengthAnchorMin, coincideLengthAnchorMax) { var x = (r0 * r0 - r1 * r1) / (2 * coincideLengthAnchor) + coincideLengthAnchor / 2; var y = coincideLengthAnchor / 2 - (r0 * r0 - r1 * r1) / (2 * coincideLengthAnchor); var alfa = Math.acos(x / r0); var beta = Math.acos(y / r1); var area0 = r0 * r0 * Math.PI; var area2 = alfa * r0 * r0 - x * r0 * Math.sin(alfa) + beta * r1 * r1 - y * r1 * Math.sin(beta); var scaleAnchor = area2 / area0; var scale = value2 / value0; var approximateValue = Math.abs(scaleAnchor / scale); if (approximateValue > 0.999 && approximateValue < 1.001) { return coincideLengthAnchor; } else if (approximateValue <= 0.999) { coincideLengthAnchorMax = coincideLengthAnchor; coincideLengthAnchor = (coincideLengthAnchor + coincideLengthAnchorMin) / 2; return this._getCoincideLength(value0, value1, value2, r0, r1, coincideLengthAnchor, coincideLengthAnchorMin, coincideLengthAnchorMax); } else { coincideLengthAnchorMin = coincideLengthAnchor; coincideLengthAnchor = (coincideLengthAnchor + coincideLengthAnchorMax) / 2; return this._getCoincideLength(value0, value1, value2, r0, r1, coincideLengthAnchor, coincideLengthAnchorMin, coincideLengthAnchorMax); } }, _buildItem: function (seriesIndex, dataIndex, dataItem, x, y, r) { var series = this.series; var serie = series[seriesIndex]; var circle = this.getCircle(seriesIndex, dataIndex, dataItem, x, y, r); ecData.pack(circle, serie, seriesIndex, dataItem, dataIndex, dataItem.name); this.shapeList.push(circle); if (serie.itemStyle.normal.label.show) { var label = this.getLabel(seriesIndex, dataIndex, dataItem, x, y, r); ecData.pack(label, serie, seriesIndex, serie.data[dataIndex], dataIndex, serie.data[dataIndex].name); this.shapeList.push(label); } }, _buildCoincideItem: function (seriesIndex, dataIndex, dataItem, x, y0, y1, r0, r1, rightLargeArcFlag, leftLargeArcFlag) { var series = this.series; var serie = series[seriesIndex]; var queryTarget = [ dataItem, serie ]; var normal = this.deepMerge(queryTarget, 'itemStyle.normal') || {}; var emphasis = this.deepMerge(queryTarget, 'itemStyle.emphasis') || {}; var normalColor = normal.color || this.zr.getColor(dataIndex); var emphasisColor = emphasis.color || this.zr.getColor(dataIndex); var path = 'M' + x + ',' + y0 + 'A' + r0 + ',' + r0 + ',0,' + rightLargeArcFlag + ',1,' + x + ',' + y1 + 'A' + r1 + ',' + r1 + ',0,' + leftLargeArcFlag + ',1,' + x + ',' + y0; var style = { color: normalColor, path: path }; var shape = { zlevel: serie.zlevel, z: serie.z, style: style, highlightStyle: { color: emphasisColor, lineWidth: emphasis.borderWidth, strokeColor: emphasis.borderColor } }; shape = new PathShape(shape); if (shape.buildPathArray) { shape.style.pathArray = shape.buildPathArray(style.path); } ecData.pack(shape, series[seriesIndex], 0, dataItem, dataIndex, dataItem.name); this.shapeList.push(shape); }, getCircle: function (seriesIndex, dataIndex, dataItem, x, y, r) { var serie = this.series[seriesIndex]; var queryTarget = [ dataItem, serie ]; var normal = this.deepMerge(queryTarget, 'itemStyle.normal') || {}; var emphasis = this.deepMerge(queryTarget, 'itemStyle.emphasis') || {}; var normalColor = normal.color || this.zr.getColor(dataIndex); var emphasisColor = emphasis.color || this.zr.getColor(dataIndex); var circle = { zlevel: serie.zlevel, z: serie.z, clickable: true, style: { x: x, y: y, r: r, brushType: 'fill', opacity: 1, color: normalColor }, highlightStyle: { color: emphasisColor, lineWidth: emphasis.borderWidth, strokeColor: emphasis.borderColor } }; if (this.deepQuery([ dataItem, serie, this.option ], 'calculable')) { this.setCalculable(circle); circle.draggable = true; } return new CircleShape(circle); }, getLabel: function (seriesIndex, dataIndex, dataItem, x, y, r) { var serie = this.series[seriesIndex]; var itemStyle = serie.itemStyle; var queryTarget = [ dataItem, serie ]; var normal = this.deepMerge(queryTarget, 'itemStyle.normal') || {}; var status = 'normal'; var labelControl = itemStyle[status].label; var textStyle = labelControl.textStyle || {}; var text = this.getLabelText(dataIndex, dataItem, status); var textFont = this.getFont(textStyle); var textColor = normal.color || this.zr.getColor(dataIndex); var textSize = textStyle.fontSize || 12; var textShape = { zlevel: serie.zlevel, z: serie.z, style: { x: x, y: y - r - textSize, color: textStyle.color || textColor, text: text, textFont: textFont, textAlign: 'center' } }; return new TextShape(textShape); }, getLabelText: function (dataIndex, dataItem, status) { var series = this.series; var serie = series[0]; var formatter = this.deepQuery([ dataItem, serie ], 'itemStyle.' + status + '.label.formatter'); if (formatter) { if (typeof formatter == 'function') { return formatter(serie.name, dataItem.name, dataItem.value); } else if (typeof formatter == 'string') { formatter = formatter.replace('{a}', '{a0}').replace('{b}', '{b0}').replace('{c}', '{c0}'); formatter = formatter.replace('{a0}', serie.name).replace('{b0}', dataItem.name).replace('{c0}', dataItem.value); return formatter; } } else { return dataItem.name; } }, refresh: function (newOption) { if (newOption) { this.option = newOption; this.series = newOption.series; } this._buildShape(); } }; zrUtil.inherits(Venn, ChartBase); require('../chart').define('venn', Venn); return Venn; });define('zrender/shape/Path', [ 'require', './Base', './util/PathProxy', '../tool/util' ], function (require) { var Base = require('./Base'); var PathProxy = require('./util/PathProxy'); var PathSegment = PathProxy.PathSegment; var vMag = function (v) { return Math.sqrt(v[0] * v[0] + v[1] * v[1]); }; var vRatio = function (u, v) { return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); }; var vAngle = function (u, v) { return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v)); }; var Path = function (options) { Base.call(this, options); }; Path.prototype = { type: 'path', buildPathArray: function (data, x, y) { if (!data) { return []; } x = x || 0; y = y || 0; var cs = data; var cc = [ 'm', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z', 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S', 'a', 'A' ]; cs = cs.replace(/-/g, ' -'); cs = cs.replace(/ /g, ' '); cs = cs.replace(/ /g, ','); cs = cs.replace(/,,/g, ','); var n; for (n = 0; n < cc.length; n++) { cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]); } var arr = cs.split('|'); var ca = []; var cpx = 0; var cpy = 0; for (n = 1; n < arr.length; n++) { var str = arr[n]; var c = str.charAt(0); str = str.slice(1); str = str.replace(new RegExp('e,-', 'g'), 'e-'); var p = str.split(','); if (p.length > 0 && p[0] === '') { p.shift(); } for (var i = 0; i < p.length; i++) { p[i] = parseFloat(p[i]); } while (p.length > 0) { if (isNaN(p[0])) { break; } var cmd = null; var points = []; var ctlPtx; var ctlPty; var prevCmd; var rx; var ry; var psi; var fa; var fs; var x1 = cpx; var y1 = cpy; switch (c) { case 'l': cpx += p.shift(); cpy += p.shift(); cmd = 'L'; points.push(cpx, cpy); break; case 'L': cpx = p.shift(); cpy = p.shift(); points.push(cpx, cpy); break; case 'm': cpx += p.shift(); cpy += p.shift(); cmd = 'M'; points.push(cpx, cpy); c = 'l'; break; case 'M': cpx = p.shift(); cpy = p.shift(); cmd = 'M'; points.push(cpx, cpy); c = 'L'; break; case 'h': cpx += p.shift(); cmd = 'L'; points.push(cpx, cpy); break; case 'H': cpx = p.shift(); cmd = 'L'; points.push(cpx, cpy); break; case 'v': cpy += p.shift(); cmd = 'L'; points.push(cpx, cpy); break; case 'V': cpy = p.shift(); cmd = 'L'; points.push(cpx, cpy); break; case 'C': points.push(p.shift(), p.shift(), p.shift(), p.shift()); cpx = p.shift(); cpy = p.shift(); points.push(cpx, cpy); break; case 'c': points.push(cpx + p.shift(), cpy + p.shift(), cpx + p.shift(), cpy + p.shift()); cpx += p.shift(); cpy += p.shift(); cmd = 'C'; points.push(cpx, cpy); break; case 'S': ctlPtx = cpx; ctlPty = cpy; prevCmd = ca[ca.length - 1]; if (prevCmd.command === 'C') { ctlPtx = cpx + (cpx - prevCmd.points[2]); ctlPty = cpy + (cpy - prevCmd.points[3]); } points.push(ctlPtx, ctlPty, p.shift(), p.shift()); cpx = p.shift(); cpy = p.shift(); cmd = 'C'; points.push(cpx, cpy); break; case 's': ctlPtx = cpx, ctlPty = cpy; prevCmd = ca[ca.length - 1]; if (prevCmd.command === 'C') { ctlPtx = cpx + (cpx - prevCmd.points[2]); ctlPty = cpy + (cpy - prevCmd.points[3]); } points.push(ctlPtx, ctlPty, cpx + p.shift(), cpy + p.shift()); cpx += p.shift(); cpy += p.shift(); cmd = 'C'; points.push(cpx, cpy); break; case 'Q': points.push(p.shift(), p.shift()); cpx = p.shift(); cpy = p.shift(); points.push(cpx, cpy); break; case 'q': points.push(cpx + p.shift(), cpy + p.shift()); cpx += p.shift(); cpy += p.shift(); cmd = 'Q'; points.push(cpx, cpy); break; case 'T': ctlPtx = cpx, ctlPty = cpy; prevCmd = ca[ca.length - 1]; if (prevCmd.command === 'Q') { ctlPtx = cpx + (cpx - prevCmd.points[0]); ctlPty = cpy + (cpy - prevCmd.points[1]); } cpx = p.shift(); cpy = p.shift(); cmd = 'Q'; points.push(ctlPtx, ctlPty, cpx, cpy); break; case 't': ctlPtx = cpx, ctlPty = cpy; prevCmd = ca[ca.length - 1]; if (prevCmd.command === 'Q') { ctlPtx = cpx + (cpx - prevCmd.points[0]); ctlPty = cpy + (cpy - prevCmd.points[1]); } cpx += p.shift(); cpy += p.shift(); cmd = 'Q'; points.push(ctlPtx, ctlPty, cpx, cpy); break; case 'A': rx = p.shift(); ry = p.shift(); psi = p.shift(); fa = p.shift(); fs = p.shift(); x1 = cpx, y1 = cpy; cpx = p.shift(), cpy = p.shift(); cmd = 'A'; points = this._convertPoint(x1, y1, cpx, cpy, fa, fs, rx, ry, psi); break; case 'a': rx = p.shift(); ry = p.shift(); psi = p.shift(); fa = p.shift(); fs = p.shift(); x1 = cpx, y1 = cpy; cpx += p.shift(); cpy += p.shift(); cmd = 'A'; points = this._convertPoint(x1, y1, cpx, cpy, fa, fs, rx, ry, psi); break; } for (var j = 0, l = points.length; j < l; j += 2) { points[j] += x; points[j + 1] += y; } ca.push(new PathSegment(cmd || c, points)); } if (c === 'z' || c === 'Z') { ca.push(new PathSegment('z', [])); } } return ca; }, _convertPoint: function (x1, y1, x2, y2, fa, fs, rx, ry, psiDeg) { var psi = psiDeg * (Math.PI / 180); var xp = Math.cos(psi) * (x1 - x2) / 2 + Math.sin(psi) * (y1 - y2) / 2; var yp = -1 * Math.sin(psi) * (x1 - x2) / 2 + Math.cos(psi) * (y1 - y2) / 2; var lambda = xp * xp / (rx * rx) + yp * yp / (ry * ry); if (lambda > 1) { rx *= Math.sqrt(lambda); ry *= Math.sqrt(lambda); } var f = Math.sqrt((rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) / (rx * rx * (yp * yp) + ry * ry * (xp * xp))); if (fa === fs) { f *= -1; } if (isNaN(f)) { f = 0; } var cxp = f * rx * yp / ry; var cyp = f * -ry * xp / rx; var cx = (x1 + x2) / 2 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; var cy = (y1 + y2) / 2 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; var theta = vAngle([ 1, 0 ], [ (xp - cxp) / rx, (yp - cyp) / ry ]); var u = [ (xp - cxp) / rx, (yp - cyp) / ry ]; var v = [ (-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry ]; var dTheta = vAngle(u, v); if (vRatio(u, v) <= -1) { dTheta = Math.PI; } if (vRatio(u, v) >= 1) { dTheta = 0; } if (fs === 0 && dTheta > 0) { dTheta = dTheta - 2 * Math.PI; } if (fs === 1 && dTheta < 0) { dTheta = dTheta + 2 * Math.PI; } return [ cx, cy, rx, ry, theta, dTheta, psi, fs ]; }, buildPath: function (ctx, style) { var path = style.path; var x = style.x || 0; var y = style.y || 0; style.pathArray = style.pathArray || this.buildPathArray(path, x, y); var pathArray = style.pathArray; var pointList = style.pointList = []; var singlePointList = []; for (var i = 0, l = pathArray.length; i < l; i++) { if (pathArray[i].command.toUpperCase() == 'M') { singlePointList.length > 0 && pointList.push(singlePointList); singlePointList = []; } var p = pathArray[i].points; for (var j = 0, k = p.length; j < k; j += 2) { singlePointList.push([ p[j], p[j + 1] ]); } } singlePointList.length > 0 && pointList.push(singlePointList); for (var i = 0, l = pathArray.length; i < l; i++) { var c = pathArray[i].command; var p = pathArray[i].points; switch (c) { case 'L': ctx.lineTo(p[0], p[1]); break; case 'M': ctx.moveTo(p[0], p[1]); break; case 'C': ctx.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]); break; case 'Q': ctx.quadraticCurveTo(p[0], p[1], p[2], p[3]); break; case 'A': var cx = p[0]; var cy = p[1]; var rx = p[2]; var ry = p[3]; var theta = p[4]; var dTheta = p[5]; var psi = p[6]; var fs = p[7]; var r = rx > ry ? rx : ry; var scaleX = rx > ry ? 1 : rx / ry; var scaleY = rx > ry ? ry / rx : 1; ctx.translate(cx, cy); ctx.rotate(psi); ctx.scale(scaleX, scaleY); ctx.arc(0, 0, r, theta, theta + dTheta, 1 - fs); ctx.scale(1 / scaleX, 1 / scaleY); ctx.rotate(-psi); ctx.translate(-cx, -cy); break; case 'z': ctx.closePath(); break; } } return; }, getRect: function (style) { if (style.__rect) { return style.__rect; } var lineWidth; if (style.brushType == 'stroke' || style.brushType == 'fill') { lineWidth = style.lineWidth || 1; } else { lineWidth = 0; } var minX = Number.MAX_VALUE; var maxX = Number.MIN_VALUE; var minY = Number.MAX_VALUE; var maxY = Number.MIN_VALUE; var x = style.x || 0; var y = style.y || 0; var pathArray = style.pathArray || this.buildPathArray(style.path); for (var i = 0; i < pathArray.length; i++) { var p = pathArray[i].points; for (var j = 0; j < p.length; j++) { if (j % 2 === 0) { if (p[j] + x < minX) { minX = p[j]; } if (p[j] + x > maxX) { maxX = p[j]; } } else { if (p[j] + y < minY) { minY = p[j]; } if (p[j] + y > maxY) { maxY = p[j]; } } } } var rect; if (minX === Number.MAX_VALUE || maxX === Number.MIN_VALUE || minY === Number.MAX_VALUE || maxY === Number.MIN_VALUE) { rect = { x: 0, y: 0, width: 0, height: 0 }; } else { rect = { x: Math.round(minX - lineWidth / 2), y: Math.round(minY - lineWidth / 2), width: maxX - minX + lineWidth, height: maxY - minY + lineWidth }; } style.__rect = rect; return rect; } }; require('../tool/util').inherits(Path, Base); return Path; });