AngleAxisView.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. var zrUtil = require("zrender/lib/core/util");
  20. var graphic = require("../../util/graphic");
  21. var Model = require("../../model/Model");
  22. var AxisView = require("./AxisView");
  23. var AxisBuilder = require("./AxisBuilder");
  24. /*
  25. * Licensed to the Apache Software Foundation (ASF) under one
  26. * or more contributor license agreements. See the NOTICE file
  27. * distributed with this work for additional information
  28. * regarding copyright ownership. The ASF licenses this file
  29. * to you under the Apache License, Version 2.0 (the
  30. * "License"); you may not use this file except in compliance
  31. * with the License. You may obtain a copy of the License at
  32. *
  33. * http://www.apache.org/licenses/LICENSE-2.0
  34. *
  35. * Unless required by applicable law or agreed to in writing,
  36. * software distributed under the License is distributed on an
  37. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  38. * KIND, either express or implied. See the License for the
  39. * specific language governing permissions and limitations
  40. * under the License.
  41. */
  42. var elementList = ['axisLine', 'axisLabel', 'axisTick', 'minorTick', 'splitLine', 'minorSplitLine', 'splitArea'];
  43. function getAxisLineShape(polar, rExtent, angle) {
  44. rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse());
  45. var start = polar.coordToPoint([rExtent[0], angle]);
  46. var end = polar.coordToPoint([rExtent[1], angle]);
  47. return {
  48. x1: start[0],
  49. y1: start[1],
  50. x2: end[0],
  51. y2: end[1]
  52. };
  53. }
  54. function getRadiusIdx(polar) {
  55. var radiusAxis = polar.getRadiusAxis();
  56. return radiusAxis.inverse ? 0 : 1;
  57. } // Remove the last tick which will overlap the first tick
  58. function fixAngleOverlap(list) {
  59. var firstItem = list[0];
  60. var lastItem = list[list.length - 1];
  61. if (firstItem && lastItem && Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4) {
  62. list.pop();
  63. }
  64. }
  65. var _default = AxisView.extend({
  66. type: 'angleAxis',
  67. axisPointerClass: 'PolarAxisPointer',
  68. render: function (angleAxisModel, ecModel) {
  69. this.group.removeAll();
  70. if (!angleAxisModel.get('show')) {
  71. return;
  72. }
  73. var angleAxis = angleAxisModel.axis;
  74. var polar = angleAxis.polar;
  75. var radiusExtent = polar.getRadiusAxis().getExtent();
  76. var ticksAngles = angleAxis.getTicksCoords();
  77. var minorTickAngles = angleAxis.getMinorTicksCoords();
  78. var labels = zrUtil.map(angleAxis.getViewLabels(), function (labelItem) {
  79. var labelItem = zrUtil.clone(labelItem);
  80. labelItem.coord = angleAxis.dataToCoord(labelItem.tickValue);
  81. return labelItem;
  82. });
  83. fixAngleOverlap(labels);
  84. fixAngleOverlap(ticksAngles);
  85. zrUtil.each(elementList, function (name) {
  86. if (angleAxisModel.get(name + '.show') && (!angleAxis.scale.isBlank() || name === 'axisLine')) {
  87. this['_' + name](angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels);
  88. }
  89. }, this);
  90. },
  91. /**
  92. * @private
  93. */
  94. _axisLine: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
  95. var lineStyleModel = angleAxisModel.getModel('axisLine.lineStyle'); // extent id of the axis radius (r0 and r)
  96. var rId = getRadiusIdx(polar);
  97. var r0Id = rId ? 0 : 1;
  98. var shape;
  99. if (radiusExtent[r0Id] === 0) {
  100. shape = new graphic.Circle({
  101. shape: {
  102. cx: polar.cx,
  103. cy: polar.cy,
  104. r: radiusExtent[rId]
  105. },
  106. style: lineStyleModel.getLineStyle(),
  107. z2: 1,
  108. silent: true
  109. });
  110. } else {
  111. shape = new graphic.Ring({
  112. shape: {
  113. cx: polar.cx,
  114. cy: polar.cy,
  115. r: radiusExtent[rId],
  116. r0: radiusExtent[r0Id]
  117. },
  118. style: lineStyleModel.getLineStyle(),
  119. z2: 1,
  120. silent: true
  121. });
  122. }
  123. shape.style.fill = null;
  124. this.group.add(shape);
  125. },
  126. /**
  127. * @private
  128. */
  129. _axisTick: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
  130. var tickModel = angleAxisModel.getModel('axisTick');
  131. var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length');
  132. var radius = radiusExtent[getRadiusIdx(polar)];
  133. var lines = zrUtil.map(ticksAngles, function (tickAngleItem) {
  134. return new graphic.Line({
  135. shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord)
  136. });
  137. });
  138. this.group.add(graphic.mergePath(lines, {
  139. style: zrUtil.defaults(tickModel.getModel('lineStyle').getLineStyle(), {
  140. stroke: angleAxisModel.get('axisLine.lineStyle.color')
  141. })
  142. }));
  143. },
  144. /**
  145. * @private
  146. */
  147. _minorTick: function (angleAxisModel, polar, tickAngles, minorTickAngles, radiusExtent) {
  148. if (!minorTickAngles.length) {
  149. return;
  150. }
  151. var tickModel = angleAxisModel.getModel('axisTick');
  152. var minorTickModel = angleAxisModel.getModel('minorTick');
  153. var tickLen = (tickModel.get('inside') ? -1 : 1) * minorTickModel.get('length');
  154. var radius = radiusExtent[getRadiusIdx(polar)];
  155. var lines = [];
  156. for (var i = 0; i < minorTickAngles.length; i++) {
  157. for (var k = 0; k < minorTickAngles[i].length; k++) {
  158. lines.push(new graphic.Line({
  159. shape: getAxisLineShape(polar, [radius, radius + tickLen], minorTickAngles[i][k].coord)
  160. }));
  161. }
  162. }
  163. this.group.add(graphic.mergePath(lines, {
  164. style: zrUtil.defaults(minorTickModel.getModel('lineStyle').getLineStyle(), zrUtil.defaults(tickModel.getLineStyle(), {
  165. stroke: angleAxisModel.get('axisLine.lineStyle.color')
  166. }))
  167. }));
  168. },
  169. /**
  170. * @private
  171. */
  172. _axisLabel: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels) {
  173. var rawCategoryData = angleAxisModel.getCategories(true);
  174. var commonLabelModel = angleAxisModel.getModel('axisLabel');
  175. var labelMargin = commonLabelModel.get('margin');
  176. var triggerEvent = angleAxisModel.get('triggerEvent'); // Use length of ticksAngles because it may remove the last tick to avoid overlapping
  177. zrUtil.each(labels, function (labelItem, idx) {
  178. var labelModel = commonLabelModel;
  179. var tickValue = labelItem.tickValue;
  180. var r = radiusExtent[getRadiusIdx(polar)];
  181. var p = polar.coordToPoint([r + labelMargin, labelItem.coord]);
  182. var cx = polar.cx;
  183. var cy = polar.cy;
  184. var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3 ? 'center' : p[0] > cx ? 'left' : 'right';
  185. var labelTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3 ? 'middle' : p[1] > cy ? 'top' : 'bottom';
  186. if (rawCategoryData && rawCategoryData[tickValue] && rawCategoryData[tickValue].textStyle) {
  187. labelModel = new Model(rawCategoryData[tickValue].textStyle, commonLabelModel, commonLabelModel.ecModel);
  188. }
  189. var textEl = new graphic.Text({
  190. silent: AxisBuilder.isLabelSilent(angleAxisModel)
  191. });
  192. this.group.add(textEl);
  193. graphic.setTextStyle(textEl.style, labelModel, {
  194. x: p[0],
  195. y: p[1],
  196. textFill: labelModel.getTextColor() || angleAxisModel.get('axisLine.lineStyle.color'),
  197. text: labelItem.formattedLabel,
  198. textAlign: labelTextAlign,
  199. textVerticalAlign: labelTextVerticalAlign
  200. }); // Pack data for mouse event
  201. if (triggerEvent) {
  202. textEl.eventData = AxisBuilder.makeAxisEventDataBase(angleAxisModel);
  203. textEl.eventData.targetType = 'axisLabel';
  204. textEl.eventData.value = labelItem.rawLabel;
  205. }
  206. }, this);
  207. },
  208. /**
  209. * @private
  210. */
  211. _splitLine: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
  212. var splitLineModel = angleAxisModel.getModel('splitLine');
  213. var lineStyleModel = splitLineModel.getModel('lineStyle');
  214. var lineColors = lineStyleModel.get('color');
  215. var lineCount = 0;
  216. lineColors = lineColors instanceof Array ? lineColors : [lineColors];
  217. var splitLines = [];
  218. for (var i = 0; i < ticksAngles.length; i++) {
  219. var colorIndex = lineCount++ % lineColors.length;
  220. splitLines[colorIndex] = splitLines[colorIndex] || [];
  221. splitLines[colorIndex].push(new graphic.Line({
  222. shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord)
  223. }));
  224. } // Simple optimization
  225. // Batching the lines if color are the same
  226. for (var i = 0; i < splitLines.length; i++) {
  227. this.group.add(graphic.mergePath(splitLines[i], {
  228. style: zrUtil.defaults({
  229. stroke: lineColors[i % lineColors.length]
  230. }, lineStyleModel.getLineStyle()),
  231. silent: true,
  232. z: angleAxisModel.get('z')
  233. }));
  234. }
  235. },
  236. /**
  237. * @private
  238. */
  239. _minorSplitLine: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
  240. if (!minorTickAngles.length) {
  241. return;
  242. }
  243. var minorSplitLineModel = angleAxisModel.getModel('minorSplitLine');
  244. var lineStyleModel = minorSplitLineModel.getModel('lineStyle');
  245. var lines = [];
  246. for (var i = 0; i < minorTickAngles.length; i++) {
  247. for (var k = 0; k < minorTickAngles[i].length; k++) {
  248. lines.push(new graphic.Line({
  249. shape: getAxisLineShape(polar, radiusExtent, minorTickAngles[i][k].coord)
  250. }));
  251. }
  252. }
  253. this.group.add(graphic.mergePath(lines, {
  254. style: lineStyleModel.getLineStyle(),
  255. silent: true,
  256. z: angleAxisModel.get('z')
  257. }));
  258. },
  259. /**
  260. * @private
  261. */
  262. _splitArea: function (angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) {
  263. if (!ticksAngles.length) {
  264. return;
  265. }
  266. var splitAreaModel = angleAxisModel.getModel('splitArea');
  267. var areaStyleModel = splitAreaModel.getModel('areaStyle');
  268. var areaColors = areaStyleModel.get('color');
  269. var lineCount = 0;
  270. areaColors = areaColors instanceof Array ? areaColors : [areaColors];
  271. var splitAreas = [];
  272. var RADIAN = Math.PI / 180;
  273. var prevAngle = -ticksAngles[0].coord * RADIAN;
  274. var r0 = Math.min(radiusExtent[0], radiusExtent[1]);
  275. var r1 = Math.max(radiusExtent[0], radiusExtent[1]);
  276. var clockwise = angleAxisModel.get('clockwise');
  277. for (var i = 1; i < ticksAngles.length; i++) {
  278. var colorIndex = lineCount++ % areaColors.length;
  279. splitAreas[colorIndex] = splitAreas[colorIndex] || [];
  280. splitAreas[colorIndex].push(new graphic.Sector({
  281. shape: {
  282. cx: polar.cx,
  283. cy: polar.cy,
  284. r0: r0,
  285. r: r1,
  286. startAngle: prevAngle,
  287. endAngle: -ticksAngles[i].coord * RADIAN,
  288. clockwise: clockwise
  289. },
  290. silent: true
  291. }));
  292. prevAngle = -ticksAngles[i].coord * RADIAN;
  293. } // Simple optimization
  294. // Batching the lines if color are the same
  295. for (var i = 0; i < splitAreas.length; i++) {
  296. this.group.add(graphic.mergePath(splitAreas[i], {
  297. style: zrUtil.defaults({
  298. fill: areaColors[i % areaColors.length]
  299. }, areaStyleModel.getAreaStyle()),
  300. silent: true
  301. }));
  302. }
  303. }
  304. });
  305. module.exports = _default;