radar.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. define('echarts/chart/radar', [
  2. 'require',
  3. './base',
  4. 'zrender/shape/Polygon',
  5. '../component/polar',
  6. '../config',
  7. '../util/ecData',
  8. 'zrender/tool/util',
  9. 'zrender/tool/color',
  10. '../util/accMath',
  11. '../chart'
  12. ], function (require) {
  13. var ChartBase = require('./base');
  14. var PolygonShape = require('zrender/shape/Polygon');
  15. require('../component/polar');
  16. var ecConfig = require('../config');
  17. ecConfig.radar = {
  18. zlevel: 0,
  19. z: 2,
  20. clickable: true,
  21. legendHoverLink: true,
  22. polarIndex: 0,
  23. itemStyle: {
  24. normal: {
  25. label: { show: false },
  26. lineStyle: {
  27. width: 2,
  28. type: 'solid'
  29. }
  30. },
  31. emphasis: { label: { show: false } }
  32. },
  33. symbolSize: 2
  34. };
  35. var ecData = require('../util/ecData');
  36. var zrUtil = require('zrender/tool/util');
  37. var zrColor = require('zrender/tool/color');
  38. function Radar(ecTheme, messageCenter, zr, option, myChart) {
  39. ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart);
  40. this.refresh(option);
  41. }
  42. Radar.prototype = {
  43. type: ecConfig.CHART_TYPE_RADAR,
  44. _buildShape: function () {
  45. this.selectedMap = {};
  46. this._symbol = this.option.symbolList;
  47. this._queryTarget;
  48. this._dropBoxList = [];
  49. this._radarDataCounter = 0;
  50. var series = this.series;
  51. var legend = this.component.legend;
  52. var serieName;
  53. for (var i = 0, l = series.length; i < l; i++) {
  54. if (series[i].type === ecConfig.CHART_TYPE_RADAR) {
  55. this.serie = this.reformOption(series[i]);
  56. this.legendHoverLink = series[i].legendHoverLink || this.legendHoverLink;
  57. serieName = this.serie.name || '';
  58. this.selectedMap[serieName] = legend ? legend.isSelected(serieName) : true;
  59. if (this.selectedMap[serieName]) {
  60. this._queryTarget = [
  61. this.serie,
  62. this.option
  63. ];
  64. if (this.deepQuery(this._queryTarget, 'calculable')) {
  65. this._addDropBox(i);
  66. }
  67. this._buildSingleRadar(i);
  68. this.buildMark(i);
  69. }
  70. }
  71. }
  72. this.addShapeList();
  73. },
  74. _buildSingleRadar: function (index) {
  75. var legend = this.component.legend;
  76. var iconShape;
  77. var data = this.serie.data;
  78. var defaultColor;
  79. var name;
  80. var pointList;
  81. var calculable = this.deepQuery(this._queryTarget, 'calculable');
  82. for (var i = 0; i < data.length; i++) {
  83. name = data[i].name || '';
  84. this.selectedMap[name] = legend ? legend.isSelected(name) : true;
  85. if (!this.selectedMap[name]) {
  86. continue;
  87. }
  88. if (legend) {
  89. defaultColor = legend.getColor(name);
  90. iconShape = legend.getItemShape(name);
  91. if (iconShape) {
  92. iconShape.style.brushType = this.deepQuery([
  93. data[i],
  94. this.serie
  95. ], 'itemStyle.normal.areaStyle') ? 'both' : 'stroke';
  96. legend.setItemShape(name, iconShape);
  97. }
  98. } else {
  99. defaultColor = this.zr.getColor(i);
  100. }
  101. pointList = this._getPointList(this.serie.polarIndex, data[i]);
  102. this._addSymbol(pointList, defaultColor, i, index, this.serie.polarIndex);
  103. this._addDataShape(pointList, defaultColor, data[i], index, i, calculable);
  104. this._radarDataCounter++;
  105. }
  106. },
  107. _getPointList: function (polarIndex, dataArr) {
  108. var pointList = [];
  109. var vector;
  110. var polar = this.component.polar;
  111. var value;
  112. for (var i = 0, l = dataArr.value.length; i < l; i++) {
  113. value = this.getDataFromOption(dataArr.value[i]);
  114. vector = value != '-' ? polar.getVector(polarIndex, i, value) : false;
  115. if (vector) {
  116. pointList.push(vector);
  117. }
  118. }
  119. return pointList;
  120. },
  121. _addSymbol: function (pointList, defaultColor, dataIndex, seriesIndex, polarIndex) {
  122. var series = this.series;
  123. var itemShape;
  124. var polar = this.component.polar;
  125. for (var i = 0, l = pointList.length; i < l; i++) {
  126. itemShape = this.getSymbolShape(this.deepMerge([
  127. series[seriesIndex].data[dataIndex],
  128. series[seriesIndex]
  129. ]), seriesIndex, series[seriesIndex].data[dataIndex].value[i], i, polar.getIndicatorText(polarIndex, i), pointList[i][0], pointList[i][1], this._symbol[this._radarDataCounter % this._symbol.length], defaultColor, '#fff', 'vertical');
  130. itemShape.zlevel = this.getZlevelBase();
  131. itemShape.z = this.getZBase() + 1;
  132. ecData.set(itemShape, 'data', series[seriesIndex].data[dataIndex]);
  133. ecData.set(itemShape, 'value', series[seriesIndex].data[dataIndex].value);
  134. ecData.set(itemShape, 'dataIndex', dataIndex);
  135. ecData.set(itemShape, 'special', i);
  136. this.shapeList.push(itemShape);
  137. }
  138. },
  139. _addDataShape: function (pointList, defaultColor, data, seriesIndex, dataIndex, calculable) {
  140. var series = this.series;
  141. var queryTarget = [
  142. data,
  143. this.serie
  144. ];
  145. var nColor = this.getItemStyleColor(this.deepQuery(queryTarget, 'itemStyle.normal.color'), seriesIndex, dataIndex, data);
  146. var nLineWidth = this.deepQuery(queryTarget, 'itemStyle.normal.lineStyle.width');
  147. var nLineType = this.deepQuery(queryTarget, 'itemStyle.normal.lineStyle.type');
  148. var nAreaColor = this.deepQuery(queryTarget, 'itemStyle.normal.areaStyle.color');
  149. var nIsAreaFill = this.deepQuery(queryTarget, 'itemStyle.normal.areaStyle');
  150. var shape = {
  151. zlevel: this.getZlevelBase(),
  152. z: this.getZBase(),
  153. style: {
  154. pointList: pointList,
  155. brushType: nIsAreaFill ? 'both' : 'stroke',
  156. color: nAreaColor || nColor || (typeof defaultColor === 'string' ? zrColor.alpha(defaultColor, 0.5) : defaultColor),
  157. strokeColor: nColor || defaultColor,
  158. lineWidth: nLineWidth,
  159. lineType: nLineType
  160. },
  161. highlightStyle: {
  162. brushType: this.deepQuery(queryTarget, 'itemStyle.emphasis.areaStyle') || nIsAreaFill ? 'both' : 'stroke',
  163. color: this.deepQuery(queryTarget, 'itemStyle.emphasis.areaStyle.color') || nAreaColor || nColor || (typeof defaultColor === 'string' ? zrColor.alpha(defaultColor, 0.5) : defaultColor),
  164. strokeColor: this.getItemStyleColor(this.deepQuery(queryTarget, 'itemStyle.emphasis.color'), seriesIndex, dataIndex, data) || nColor || defaultColor,
  165. lineWidth: this.deepQuery(queryTarget, 'itemStyle.emphasis.lineStyle.width') || nLineWidth,
  166. lineType: this.deepQuery(queryTarget, 'itemStyle.emphasis.lineStyle.type') || nLineType
  167. }
  168. };
  169. ecData.pack(shape, series[seriesIndex], seriesIndex, data, dataIndex, data.name, this.component.polar.getIndicator(series[seriesIndex].polarIndex));
  170. if (calculable) {
  171. shape.draggable = true;
  172. this.setCalculable(shape);
  173. }
  174. shape = new PolygonShape(shape);
  175. this.shapeList.push(shape);
  176. },
  177. _addDropBox: function (index) {
  178. var series = this.series;
  179. var polarIndex = this.deepQuery(this._queryTarget, 'polarIndex');
  180. if (!this._dropBoxList[polarIndex]) {
  181. var shape = this.component.polar.getDropBox(polarIndex);
  182. shape.zlevel = this.getZlevelBase();
  183. shape.z = this.getZBase();
  184. this.setCalculable(shape);
  185. ecData.pack(shape, series, index, undefined, -1);
  186. this.shapeList.push(shape);
  187. this._dropBoxList[polarIndex] = true;
  188. }
  189. },
  190. ondragend: function (param, status) {
  191. var series = this.series;
  192. if (!this.isDragend || !param.target) {
  193. return;
  194. }
  195. var target = param.target;
  196. var seriesIndex = ecData.get(target, 'seriesIndex');
  197. var dataIndex = ecData.get(target, 'dataIndex');
  198. this.component.legend && this.component.legend.del(series[seriesIndex].data[dataIndex].name);
  199. series[seriesIndex].data.splice(dataIndex, 1);
  200. status.dragOut = true;
  201. status.needRefresh = true;
  202. this.isDragend = false;
  203. return;
  204. },
  205. ondrop: function (param, status) {
  206. var series = this.series;
  207. if (!this.isDrop || !param.target) {
  208. return;
  209. }
  210. var target = param.target;
  211. var dragged = param.dragged;
  212. var seriesIndex = ecData.get(target, 'seriesIndex');
  213. var dataIndex = ecData.get(target, 'dataIndex');
  214. var data;
  215. var legend = this.component.legend;
  216. var value;
  217. if (dataIndex === -1) {
  218. data = {
  219. value: ecData.get(dragged, 'value'),
  220. name: ecData.get(dragged, 'name')
  221. };
  222. series[seriesIndex].data.push(data);
  223. legend && legend.add(data.name, dragged.style.color || dragged.style.strokeColor);
  224. } else {
  225. var accMath = require('../util/accMath');
  226. data = series[seriesIndex].data[dataIndex];
  227. legend && legend.del(data.name);
  228. data.name += this.option.nameConnector + ecData.get(dragged, 'name');
  229. value = ecData.get(dragged, 'value');
  230. for (var i = 0; i < value.length; i++) {
  231. data.value[i] = accMath.accAdd(data.value[i], value[i]);
  232. }
  233. legend && legend.add(data.name, dragged.style.color || dragged.style.strokeColor);
  234. }
  235. status.dragIn = status.dragIn || true;
  236. this.isDrop = false;
  237. return;
  238. },
  239. refresh: function (newOption) {
  240. if (newOption) {
  241. this.option = newOption;
  242. this.series = newOption.series;
  243. }
  244. this.backupShapeList();
  245. this._buildShape();
  246. }
  247. };
  248. zrUtil.inherits(Radar, ChartBase);
  249. require('../chart').define('radar', Radar);
  250. return Radar;
  251. });define('echarts/component/polar', [
  252. 'require',
  253. './base',
  254. 'zrender/shape/Text',
  255. 'zrender/shape/Line',
  256. 'zrender/shape/Polygon',
  257. 'zrender/shape/Circle',
  258. 'zrender/shape/Ring',
  259. '../config',
  260. 'zrender/tool/util',
  261. '../util/coordinates',
  262. '../util/accMath',
  263. '../util/smartSteps',
  264. '../component'
  265. ], function (require) {
  266. var Base = require('./base');
  267. var TextShape = require('zrender/shape/Text');
  268. var LineShape = require('zrender/shape/Line');
  269. var PolygonShape = require('zrender/shape/Polygon');
  270. var Circle = require('zrender/shape/Circle');
  271. var Ring = require('zrender/shape/Ring');
  272. var ecConfig = require('../config');
  273. ecConfig.polar = {
  274. zlevel: 0,
  275. z: 0,
  276. center: [
  277. '50%',
  278. '50%'
  279. ],
  280. radius: '75%',
  281. startAngle: 90,
  282. boundaryGap: [
  283. 0,
  284. 0
  285. ],
  286. splitNumber: 5,
  287. name: {
  288. show: true,
  289. textStyle: { color: '#333' }
  290. },
  291. axisLine: {
  292. show: true,
  293. lineStyle: {
  294. color: '#ccc',
  295. width: 1,
  296. type: 'solid'
  297. }
  298. },
  299. axisLabel: {
  300. show: false,
  301. textStyle: { color: '#333' }
  302. },
  303. splitArea: {
  304. show: true,
  305. areaStyle: {
  306. color: [
  307. 'rgba(250,250,250,0.3)',
  308. 'rgba(200,200,200,0.3)'
  309. ]
  310. }
  311. },
  312. splitLine: {
  313. show: true,
  314. lineStyle: {
  315. width: 1,
  316. color: '#ccc'
  317. }
  318. },
  319. type: 'polygon'
  320. };
  321. var zrUtil = require('zrender/tool/util');
  322. var ecCoordinates = require('../util/coordinates');
  323. function Polar(ecTheme, messageCenter, zr, option, myChart) {
  324. Base.call(this, ecTheme, messageCenter, zr, option, myChart);
  325. this.refresh(option);
  326. }
  327. Polar.prototype = {
  328. type: ecConfig.COMPONENT_TYPE_POLAR,
  329. _buildShape: function () {
  330. for (var i = 0; i < this.polar.length; i++) {
  331. this._index = i;
  332. this.reformOption(this.polar[i]);
  333. this._queryTarget = [
  334. this.polar[i],
  335. this.option
  336. ];
  337. this._createVector(i);
  338. this._buildSpiderWeb(i);
  339. this._buildText(i);
  340. this._adjustIndicatorValue(i);
  341. this._addAxisLabel(i);
  342. }
  343. for (var i = 0; i < this.shapeList.length; i++) {
  344. this.zr.addShape(this.shapeList[i]);
  345. }
  346. },
  347. _createVector: function (index) {
  348. var item = this.polar[index];
  349. var indicator = this.deepQuery(this._queryTarget, 'indicator');
  350. var length = indicator.length;
  351. var startAngle = item.startAngle;
  352. var dStep = 2 * Math.PI / length;
  353. var radius = this._getRadius();
  354. var __ecIndicator = item.__ecIndicator = [];
  355. var vector;
  356. for (var i = 0; i < length; i++) {
  357. vector = ecCoordinates.polar2cartesian(radius, startAngle * Math.PI / 180 + dStep * i);
  358. __ecIndicator.push({
  359. vector: [
  360. vector[1],
  361. -vector[0]
  362. ]
  363. });
  364. }
  365. },
  366. _getRadius: function () {
  367. var item = this.polar[this._index];
  368. return this.parsePercent(item.radius, Math.min(this.zr.getWidth(), this.zr.getHeight()) / 2);
  369. },
  370. _buildSpiderWeb: function (index) {
  371. var item = this.polar[index];
  372. var __ecIndicator = item.__ecIndicator;
  373. var splitArea = item.splitArea;
  374. var splitLine = item.splitLine;
  375. var center = this.getCenter(index);
  376. var splitNumber = item.splitNumber;
  377. var strokeColor = splitLine.lineStyle.color;
  378. var lineWidth = splitLine.lineStyle.width;
  379. var show = splitLine.show;
  380. var axisLine = this.deepQuery(this._queryTarget, 'axisLine');
  381. this._addArea(__ecIndicator, splitNumber, center, splitArea, strokeColor, lineWidth, show);
  382. axisLine.show && this._addLine(__ecIndicator, center, axisLine);
  383. },
  384. _addAxisLabel: function (index) {
  385. var accMath = require('../util/accMath');
  386. var item = this.polar[index];
  387. var indicator = this.deepQuery(this._queryTarget, 'indicator');
  388. var __ecIndicator = item.__ecIndicator;
  389. var axisLabel;
  390. var vector;
  391. var style;
  392. var newStyle;
  393. var splitNumber = this.deepQuery(this._queryTarget, 'splitNumber');
  394. var center = this.getCenter(index);
  395. var vector;
  396. var value;
  397. var text;
  398. var theta;
  399. var offset;
  400. var interval;
  401. for (var i = 0; i < indicator.length; i++) {
  402. axisLabel = this.deepQuery([
  403. indicator[i],
  404. item,
  405. this.option
  406. ], 'axisLabel');
  407. if (axisLabel.show) {
  408. var textStyle = this.deepQuery([
  409. axisLabel,
  410. item,
  411. this.option
  412. ], 'textStyle');
  413. var formatter = this.deepQuery([
  414. axisLabel,
  415. item
  416. ], 'formatter');
  417. style = {};
  418. style.textFont = this.getFont(textStyle);
  419. style.color = textStyle.color;
  420. style = zrUtil.merge(style, axisLabel);
  421. style.lineWidth = style.width;
  422. vector = __ecIndicator[i].vector;
  423. value = __ecIndicator[i].value;
  424. theta = i / indicator.length * 2 * Math.PI;
  425. offset = axisLabel.offset || 10;
  426. interval = axisLabel.interval || 0;
  427. if (!value) {
  428. return;
  429. }
  430. for (var j = 1; j <= splitNumber; j += interval + 1) {
  431. newStyle = zrUtil.merge({}, style);
  432. text = accMath.accAdd(value.min, accMath.accMul(value.step, j));
  433. if (typeof formatter === 'function') {
  434. text = formatter(text);
  435. } else if (typeof formatter === 'string') {
  436. text = formatter.replace('{a}', '{a0}').replace('{a0}', text);
  437. } else {
  438. text = this.numAddCommas(text);
  439. }
  440. newStyle.text = text;
  441. newStyle.x = j * vector[0] / splitNumber + Math.cos(theta) * offset + center[0];
  442. newStyle.y = j * vector[1] / splitNumber + Math.sin(theta) * offset + center[1];
  443. this.shapeList.push(new TextShape({
  444. zlevel: this.getZlevelBase(),
  445. z: this.getZBase(),
  446. style: newStyle,
  447. draggable: false,
  448. hoverable: false
  449. }));
  450. }
  451. }
  452. }
  453. },
  454. _buildText: function (index) {
  455. var item = this.polar[index];
  456. var __ecIndicator = item.__ecIndicator;
  457. var vector;
  458. var indicator = this.deepQuery(this._queryTarget, 'indicator');
  459. var center = this.getCenter(index);
  460. var style;
  461. var textAlign;
  462. var name;
  463. var rotation;
  464. var x = 0;
  465. var y = 0;
  466. var margin;
  467. var textStyle;
  468. for (var i = 0; i < indicator.length; i++) {
  469. name = this.deepQuery([
  470. indicator[i],
  471. item,
  472. this.option
  473. ], 'name');
  474. if (!name.show) {
  475. continue;
  476. }
  477. textStyle = this.deepQuery([
  478. name,
  479. item,
  480. this.option
  481. ], 'textStyle');
  482. style = {};
  483. style.textFont = this.getFont(textStyle);
  484. style.color = textStyle.color;
  485. if (typeof name.formatter == 'function') {
  486. style.text = name.formatter.call(this.myChart, indicator[i].text, i);
  487. } else if (typeof name.formatter == 'string') {
  488. style.text = name.formatter.replace('{value}', indicator[i].text);
  489. } else {
  490. style.text = indicator[i].text;
  491. }
  492. __ecIndicator[i].text = style.text;
  493. vector = __ecIndicator[i].vector;
  494. if (Math.round(vector[0]) > 0) {
  495. textAlign = 'left';
  496. } else if (Math.round(vector[0]) < 0) {
  497. textAlign = 'right';
  498. } else {
  499. textAlign = 'center';
  500. }
  501. if (name.margin == null) {
  502. vector = this._mapVector(vector, center, 1.1);
  503. } else {
  504. margin = name.margin;
  505. x = vector[0] > 0 ? margin : -margin;
  506. y = vector[1] > 0 ? margin : -margin;
  507. x = vector[0] === 0 ? 0 : x;
  508. y = vector[1] === 0 ? 0 : y;
  509. vector = this._mapVector(vector, center, 1);
  510. }
  511. style.textAlign = textAlign;
  512. style.x = vector[0] + x;
  513. style.y = vector[1] + y;
  514. if (name.rotate) {
  515. rotation = [
  516. name.rotate / 180 * Math.PI,
  517. vector[0],
  518. vector[1]
  519. ];
  520. } else {
  521. rotation = [
  522. 0,
  523. 0,
  524. 0
  525. ];
  526. }
  527. this.shapeList.push(new TextShape({
  528. zlevel: this.getZlevelBase(),
  529. z: this.getZBase(),
  530. style: style,
  531. draggable: false,
  532. hoverable: false,
  533. rotation: rotation
  534. }));
  535. }
  536. },
  537. getIndicatorText: function (polarIndex, indicatorIndex) {
  538. return this.polar[polarIndex] && this.polar[polarIndex].__ecIndicator[indicatorIndex] && this.polar[polarIndex].__ecIndicator[indicatorIndex].text;
  539. },
  540. getDropBox: function (index) {
  541. var index = index || 0;
  542. var item = this.polar[index];
  543. var center = this.getCenter(index);
  544. var __ecIndicator = item.__ecIndicator;
  545. var len = __ecIndicator.length;
  546. var pointList = [];
  547. var vector;
  548. var shape;
  549. var type = item.type;
  550. if (type == 'polygon') {
  551. for (var i = 0; i < len; i++) {
  552. vector = __ecIndicator[i].vector;
  553. pointList.push(this._mapVector(vector, center, 1.2));
  554. }
  555. shape = this._getShape(pointList, 'fill', 'rgba(0,0,0,0)', '', 1);
  556. } else if (type == 'circle') {
  557. shape = this._getCircle('', 1, 1.2, center, 'fill', 'rgba(0,0,0,0)');
  558. }
  559. return shape;
  560. },
  561. _addArea: function (__ecIndicator, splitNumber, center, splitArea, strokeColor, lineWidth, show) {
  562. var shape;
  563. var scale;
  564. var scale1;
  565. var pointList;
  566. var type = this.deepQuery(this._queryTarget, 'type');
  567. for (var i = 0; i < splitNumber; i++) {
  568. scale = (splitNumber - i) / splitNumber;
  569. if (show) {
  570. if (type == 'polygon') {
  571. pointList = this._getPointList(__ecIndicator, scale, center);
  572. shape = this._getShape(pointList, 'stroke', '', strokeColor, lineWidth);
  573. } else if (type == 'circle') {
  574. shape = this._getCircle(strokeColor, lineWidth, scale, center, 'stroke');
  575. }
  576. this.shapeList.push(shape);
  577. }
  578. if (splitArea.show) {
  579. scale1 = (splitNumber - i - 1) / splitNumber;
  580. this._addSplitArea(__ecIndicator, splitArea, scale, scale1, center, i);
  581. }
  582. }
  583. },
  584. _getCircle: function (strokeColor, lineWidth, scale, center, brushType, color) {
  585. var radius = this._getRadius();
  586. return new Circle({
  587. zlevel: this.getZlevelBase(),
  588. z: this.getZBase(),
  589. style: {
  590. x: center[0],
  591. y: center[1],
  592. r: radius * scale,
  593. brushType: brushType,
  594. strokeColor: strokeColor,
  595. lineWidth: lineWidth,
  596. color: color
  597. },
  598. hoverable: false,
  599. draggable: false
  600. });
  601. },
  602. _getRing: function (color, scale0, scale1, center) {
  603. var radius = this._getRadius();
  604. return new Ring({
  605. zlevel: this.getZlevelBase(),
  606. z: this.getZBase(),
  607. style: {
  608. x: center[0],
  609. y: center[1],
  610. r: scale0 * radius,
  611. r0: scale1 * radius,
  612. color: color,
  613. brushType: 'fill'
  614. },
  615. hoverable: false,
  616. draggable: false
  617. });
  618. },
  619. _getPointList: function (__ecIndicator, scale, center) {
  620. var pointList = [];
  621. var len = __ecIndicator.length;
  622. var vector;
  623. for (var i = 0; i < len; i++) {
  624. vector = __ecIndicator[i].vector;
  625. pointList.push(this._mapVector(vector, center, scale));
  626. }
  627. return pointList;
  628. },
  629. _getShape: function (pointList, brushType, color, strokeColor, lineWidth) {
  630. return new PolygonShape({
  631. zlevel: this.getZlevelBase(),
  632. z: this.getZBase(),
  633. style: {
  634. pointList: pointList,
  635. brushType: brushType,
  636. color: color,
  637. strokeColor: strokeColor,
  638. lineWidth: lineWidth
  639. },
  640. hoverable: false,
  641. draggable: false
  642. });
  643. },
  644. _addSplitArea: function (__ecIndicator, splitArea, scale, scale1, center, colorInd) {
  645. var indLen = __ecIndicator.length;
  646. var color;
  647. var colorArr = splitArea.areaStyle.color;
  648. var colorLen;
  649. var vector;
  650. var vector1;
  651. var pointList = [];
  652. var indLen = __ecIndicator.length;
  653. var shape;
  654. var type = this.deepQuery(this._queryTarget, 'type');
  655. if (typeof colorArr == 'string') {
  656. colorArr = [colorArr];
  657. }
  658. colorLen = colorArr.length;
  659. color = colorArr[colorInd % colorLen];
  660. if (type == 'polygon') {
  661. for (var i = 0; i < indLen; i++) {
  662. pointList = [];
  663. vector = __ecIndicator[i].vector;
  664. vector1 = __ecIndicator[(i + 1) % indLen].vector;
  665. pointList.push(this._mapVector(vector, center, scale));
  666. pointList.push(this._mapVector(vector, center, scale1));
  667. pointList.push(this._mapVector(vector1, center, scale1));
  668. pointList.push(this._mapVector(vector1, center, scale));
  669. shape = this._getShape(pointList, 'fill', color, '', 1);
  670. this.shapeList.push(shape);
  671. }
  672. } else if (type == 'circle') {
  673. shape = this._getRing(color, scale, scale1, center);
  674. this.shapeList.push(shape);
  675. }
  676. },
  677. _mapVector: function (vector, center, scale) {
  678. return [
  679. vector[0] * scale + center[0],
  680. vector[1] * scale + center[1]
  681. ];
  682. },
  683. getCenter: function (index) {
  684. var index = index || 0;
  685. return this.parseCenter(this.zr, this.polar[index].center);
  686. },
  687. _addLine: function (__ecIndicator, center, axisLine) {
  688. var indLen = __ecIndicator.length;
  689. var line;
  690. var vector;
  691. var lineStyle = axisLine.lineStyle;
  692. var strokeColor = lineStyle.color;
  693. var lineWidth = lineStyle.width;
  694. var lineType = lineStyle.type;
  695. for (var i = 0; i < indLen; i++) {
  696. vector = __ecIndicator[i].vector;
  697. line = this._getLine(center[0], center[1], vector[0] + center[0], vector[1] + center[1], strokeColor, lineWidth, lineType);
  698. this.shapeList.push(line);
  699. }
  700. },
  701. _getLine: function (xStart, yStart, xEnd, yEnd, strokeColor, lineWidth, lineType) {
  702. return new LineShape({
  703. zlevel: this.getZlevelBase(),
  704. z: this.getZBase(),
  705. style: {
  706. xStart: xStart,
  707. yStart: yStart,
  708. xEnd: xEnd,
  709. yEnd: yEnd,
  710. strokeColor: strokeColor,
  711. lineWidth: lineWidth,
  712. lineType: lineType
  713. },
  714. hoverable: false
  715. });
  716. },
  717. _adjustIndicatorValue: function (index) {
  718. var item = this.polar[index];
  719. var indicator = this.deepQuery(this._queryTarget, 'indicator');
  720. var len = indicator.length;
  721. var __ecIndicator = item.__ecIndicator;
  722. var max;
  723. var min;
  724. var data = this._getSeriesData(index);
  725. var boundaryGap = item.boundaryGap;
  726. var splitNumber = item.splitNumber;
  727. var scale = item.scale;
  728. var opts;
  729. var smartSteps = require('../util/smartSteps');
  730. for (var i = 0; i < len; i++) {
  731. if (typeof indicator[i].max == 'number') {
  732. max = indicator[i].max;
  733. min = indicator[i].min || 0;
  734. opts = {
  735. max: max,
  736. min: min
  737. };
  738. } else {
  739. var value = this._findValue(data, i, splitNumber, boundaryGap);
  740. min = value.min;
  741. max = value.max;
  742. }
  743. if (!scale && min >= 0 && max >= 0) {
  744. min = 0;
  745. }
  746. if (!scale && min <= 0 && max <= 0) {
  747. max = 0;
  748. }
  749. var stepOpt = smartSteps(min, max, splitNumber, opts);
  750. __ecIndicator[i].value = {
  751. min: stepOpt.min,
  752. max: stepOpt.max,
  753. step: stepOpt.step
  754. };
  755. }
  756. },
  757. _getSeriesData: function (index) {
  758. var data = [];
  759. var serie;
  760. var serieData;
  761. var legend = this.component.legend;
  762. var polarIndex;
  763. for (var i = 0; i < this.series.length; i++) {
  764. serie = this.series[i];
  765. if (serie.type != ecConfig.CHART_TYPE_RADAR) {
  766. continue;
  767. }
  768. serieData = serie.data || [];
  769. for (var j = 0; j < serieData.length; j++) {
  770. polarIndex = this.deepQuery([
  771. serieData[j],
  772. serie,
  773. this.option
  774. ], 'polarIndex') || 0;
  775. if (polarIndex == index && (!legend || legend.isSelected(serieData[j].name))) {
  776. data.push(serieData[j]);
  777. }
  778. }
  779. }
  780. return data;
  781. },
  782. _findValue: function (data, index, splitNumber, boundaryGap) {
  783. var max;
  784. var min;
  785. var one;
  786. if (!data || data.length === 0) {
  787. return;
  788. }
  789. function _compare(item) {
  790. (item > max || max === undefined) && (max = item);
  791. (item < min || min === undefined) && (min = item);
  792. }
  793. if (data.length == 1) {
  794. min = 0;
  795. }
  796. if (data.length != 1) {
  797. for (var i = 0; i < data.length; i++) {
  798. _compare(this.getDataFromOption(data[i].value[index]));
  799. }
  800. } else {
  801. one = data[0];
  802. for (var i = 0; i < one.value.length; i++) {
  803. _compare(this.getDataFromOption(one.value[i]));
  804. }
  805. }
  806. var gap = Math.abs(max - min);
  807. min = min - Math.abs(gap * boundaryGap[0]);
  808. max = max + Math.abs(gap * boundaryGap[1]);
  809. if (min === max) {
  810. if (max === 0) {
  811. max = 1;
  812. } else if (max > 0) {
  813. min = max / splitNumber;
  814. } else {
  815. max = max / splitNumber;
  816. }
  817. }
  818. return {
  819. max: max,
  820. min: min
  821. };
  822. },
  823. getVector: function (polarIndex, indicatorIndex, value) {
  824. polarIndex = polarIndex || 0;
  825. indicatorIndex = indicatorIndex || 0;
  826. var __ecIndicator = this.polar[polarIndex].__ecIndicator;
  827. if (indicatorIndex >= __ecIndicator.length) {
  828. return;
  829. }
  830. var indicator = this.polar[polarIndex].__ecIndicator[indicatorIndex];
  831. var center = this.getCenter(polarIndex);
  832. var vector = indicator.vector;
  833. var max = indicator.value.max;
  834. var min = indicator.value.min;
  835. var alpha;
  836. if (typeof value == 'undefined') {
  837. return center;
  838. }
  839. switch (value) {
  840. case 'min':
  841. value = min;
  842. break;
  843. case 'max':
  844. value = max;
  845. break;
  846. case 'center':
  847. value = (max + min) / 2;
  848. break;
  849. }
  850. if (max != min) {
  851. alpha = (value - min) / (max - min);
  852. } else {
  853. alpha = 0.5;
  854. }
  855. return this._mapVector(vector, center, alpha);
  856. },
  857. isInside: function (vector) {
  858. var polar = this.getNearestIndex(vector);
  859. if (polar) {
  860. return polar.polarIndex;
  861. }
  862. return -1;
  863. },
  864. getNearestIndex: function (vector) {
  865. var item;
  866. var center;
  867. var radius;
  868. var polarVector;
  869. var startAngle;
  870. var indicator;
  871. var len;
  872. var angle;
  873. var finalAngle;
  874. for (var i = 0; i < this.polar.length; i++) {
  875. item = this.polar[i];
  876. center = this.getCenter(i);
  877. if (vector[0] == center[0] && vector[1] == center[1]) {
  878. return {
  879. polarIndex: i,
  880. valueIndex: 0
  881. };
  882. }
  883. radius = this._getRadius();
  884. startAngle = item.startAngle;
  885. indicator = item.indicator;
  886. len = indicator.length;
  887. angle = 2 * Math.PI / len;
  888. polarVector = ecCoordinates.cartesian2polar(vector[0] - center[0], center[1] - vector[1]);
  889. if (vector[0] - center[0] < 0) {
  890. polarVector[1] += Math.PI;
  891. }
  892. if (polarVector[1] < 0) {
  893. polarVector[1] += 2 * Math.PI;
  894. }
  895. finalAngle = polarVector[1] - startAngle / 180 * Math.PI + Math.PI * 2;
  896. if (Math.abs(Math.cos(finalAngle % (angle / 2))) * radius > polarVector[0]) {
  897. return {
  898. polarIndex: i,
  899. valueIndex: Math.floor((finalAngle + angle / 2) / angle) % len
  900. };
  901. }
  902. }
  903. },
  904. getIndicator: function (index) {
  905. var index = index || 0;
  906. return this.polar[index].indicator;
  907. },
  908. refresh: function (newOption) {
  909. if (newOption) {
  910. this.option = newOption;
  911. this.polar = this.option.polar;
  912. this.series = this.option.series;
  913. }
  914. this.clear();
  915. this._buildShape();
  916. }
  917. };
  918. zrUtil.inherits(Polar, Base);
  919. require('../component').define('polar', Polar);
  920. return Polar;
  921. });define('echarts/util/coordinates', [
  922. 'require',
  923. 'zrender/tool/math'
  924. ], function (require) {
  925. var zrMath = require('zrender/tool/math');
  926. function polar2cartesian(r, theta) {
  927. return [
  928. r * zrMath.sin(theta),
  929. r * zrMath.cos(theta)
  930. ];
  931. }
  932. function cartesian2polar(x, y) {
  933. return [
  934. Math.sqrt(x * x + y * y),
  935. Math.atan(y / x)
  936. ];
  937. }
  938. return {
  939. polar2cartesian: polar2cartesian,
  940. cartesian2polar: cartesian2polar
  941. };
  942. });