PieSeries.js 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253
  1. /* *
  2. *
  3. * (c) 2010-2020 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. import H from './Globals.js';
  12. import LegendSymbolMixin from '../mixins/legend-symbol.js';
  13. import Point from './Point.js';
  14. import U from './Utilities.js';
  15. var addEvent = U.addEvent, clamp = U.clamp, defined = U.defined, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, pick = U.pick, relativeLength = U.relativeLength, seriesType = U.seriesType, setAnimation = U.setAnimation;
  16. import './ColumnSeries.js';
  17. import '../mixins/centered-series.js';
  18. import './Options.js';
  19. import './Series.js';
  20. var CenteredSeriesMixin = H.CenteredSeriesMixin, getStartAndEndRadians = CenteredSeriesMixin.getStartAndEndRadians, noop = H.noop, Series = H.Series, seriesTypes = H.seriesTypes;
  21. /**
  22. * Pie series type.
  23. *
  24. * @private
  25. * @class
  26. * @name Highcharts.seriesTypes.pie
  27. *
  28. * @augments Highcharts.Series
  29. */
  30. seriesType('pie', 'line',
  31. /**
  32. * A pie chart is a circular graphic which is divided into slices to
  33. * illustrate numerical proportion.
  34. *
  35. * @sample highcharts/demo/pie-basic/
  36. * Pie chart
  37. *
  38. * @extends plotOptions.line
  39. * @excluding animationLimit, boostThreshold, connectEnds, connectNulls,
  40. * cropThreshold, dashStyle, dataSorting, dragDrop,
  41. * findNearestPointBy, getExtremesFromAll, label, lineWidth,
  42. * marker, negativeColor, pointInterval, pointIntervalUnit,
  43. * pointPlacement, pointStart, softThreshold, stacking, step,
  44. * threshold, turboThreshold, zoneAxis, zones, dataSorting
  45. * @product highcharts
  46. * @optionparent plotOptions.pie
  47. */
  48. {
  49. /**
  50. * @excluding legendItemClick
  51. * @apioption plotOptions.pie.events
  52. */
  53. /**
  54. * Fires when the checkbox next to the point name in the legend is
  55. * clicked. One parameter, event, is passed to the function. The state
  56. * of the checkbox is found by event.checked. The checked item is found
  57. * by event.item. Return false to prevent the default action which is to
  58. * toggle the select state of the series.
  59. *
  60. * @sample {highcharts} highcharts/plotoptions/series-events-checkboxclick/
  61. * Alert checkbox status
  62. *
  63. * @type {Function}
  64. * @since 1.2.0
  65. * @product highcharts
  66. * @context Highcharts.Point
  67. * @apioption plotOptions.pie.events.checkboxClick
  68. */
  69. /**
  70. * Fires when the legend item belonging to the pie point (slice) is
  71. * clicked. The `this` keyword refers to the point itself. One
  72. * parameter, `event`, is passed to the function, containing common
  73. * event information. The default action is to toggle the visibility of
  74. * the point. This can be prevented by calling `event.preventDefault()`.
  75. *
  76. * @sample {highcharts} highcharts/plotoptions/pie-point-events-legenditemclick/
  77. * Confirm toggle visibility
  78. *
  79. * @type {Highcharts.PointLegendItemClickCallbackFunction}
  80. * @since 1.2.0
  81. * @product highcharts
  82. * @apioption plotOptions.pie.point.events.legendItemClick
  83. */
  84. /**
  85. * The center of the pie chart relative to the plot area. Can be
  86. * percentages or pixel values. The default behaviour (as of 3.0) is to
  87. * center the pie so that all slices and data labels are within the plot
  88. * area. As a consequence, the pie may actually jump around in a chart
  89. * with dynamic values, as the data labels move. In that case, the
  90. * center should be explicitly set, for example to `["50%", "50%"]`.
  91. *
  92. * @sample {highcharts} highcharts/plotoptions/pie-center/
  93. * Centered at 100, 100
  94. *
  95. * @type {Array<(number|string|null),(number|string|null)>}
  96. * @default [null, null]
  97. * @product highcharts
  98. *
  99. * @private
  100. */
  101. center: [null, null],
  102. /**
  103. * The color of the pie series. A pie series is represented as an empty
  104. * circle if the total sum of its values is 0. Use this property to
  105. * define the color of its border.
  106. *
  107. * In styled mode, the color can be defined by the
  108. * [colorIndex](#plotOptions.series.colorIndex) option. Also, the series
  109. * color can be set with the `.highcharts-series`,
  110. * `.highcharts-color-{n}`, `.highcharts-{type}-series` or
  111. * `.highcharts-series-{n}` class, or individual classes given by the
  112. * `className` option.
  113. *
  114. * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
  115. * Empty pie series
  116. *
  117. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  118. * @default #cccccc
  119. * @apioption plotOptions.pie.color
  120. */
  121. /**
  122. * @product highcharts
  123. *
  124. * @private
  125. */
  126. clip: false,
  127. /**
  128. * @ignore-option
  129. *
  130. * @private
  131. */
  132. colorByPoint: true,
  133. /**
  134. * A series specific or series type specific color set to use instead
  135. * of the global [colors](#colors).
  136. *
  137. * @sample {highcharts} highcharts/demo/pie-monochrome/
  138. * Set default colors for all pies
  139. *
  140. * @type {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
  141. * @since 3.0
  142. * @product highcharts
  143. * @apioption plotOptions.pie.colors
  144. */
  145. /**
  146. * @declare Highcharts.SeriesPieDataLabelsOptionsObject
  147. * @extends plotOptions.series.dataLabels
  148. * @excluding align, allowOverlap, inside, staggerLines, step
  149. * @private
  150. */
  151. dataLabels: {
  152. /**
  153. * Alignment method for data labels. Possible values are:
  154. *
  155. * - `toPlotEdges`: Each label touches the nearest vertical edge of
  156. * the plot area.
  157. *
  158. * - `connectors`: Connectors have the same x position and the
  159. * widest label of each half (left & right) touches the nearest
  160. * vertical edge of the plot area.
  161. *
  162. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-connectors/
  163. * alignTo: connectors
  164. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-alignto-plotedges/
  165. * alignTo: plotEdges
  166. *
  167. * @type {string}
  168. * @since 7.0.0
  169. * @product highcharts
  170. * @apioption plotOptions.pie.dataLabels.alignTo
  171. */
  172. allowOverlap: true,
  173. /**
  174. * The color of the line connecting the data label to the pie slice.
  175. * The default color is the same as the point's color.
  176. *
  177. * In styled mode, the connector stroke is given in the
  178. * `.highcharts-data-label-connector` class.
  179. *
  180. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorcolor/
  181. * Blue connectors
  182. * @sample {highcharts} highcharts/css/pie-point/
  183. * Styled connectors
  184. *
  185. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  186. * @since 2.1
  187. * @product highcharts
  188. * @apioption plotOptions.pie.dataLabels.connectorColor
  189. */
  190. /**
  191. * The distance from the data label to the connector. Note that
  192. * data labels also have a default `padding`, so in order for the
  193. * connector to touch the text, the `padding` must also be 0.
  194. *
  195. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorpadding/
  196. * No padding
  197. *
  198. * @since 2.1
  199. * @product highcharts
  200. */
  201. connectorPadding: 5,
  202. /**
  203. * Specifies the method that is used to generate the connector path.
  204. * Highcharts provides 3 built-in connector shapes: `'fixedOffset'`
  205. * (default), `'straight'` and `'crookedLine'`. Using
  206. * `'crookedLine'` has the most sense (in most of the cases) when
  207. * `'alignTo'` is set.
  208. *
  209. * Users can provide their own method by passing a function instead
  210. * of a String. 3 arguments are passed to the callback:
  211. *
  212. * - Object that holds the information about the coordinates of the
  213. * label (`x` & `y` properties) and how the label is located in
  214. * relation to the pie (`alignment` property). `alignment` can by
  215. * one of the following:
  216. * `'left'` (pie on the left side of the data label),
  217. * `'right'` (pie on the right side of the data label) or
  218. * `'center'` (data label overlaps the pie).
  219. *
  220. * - Object that holds the information about the position of the
  221. * connector. Its `touchingSliceAt` porperty tells the position
  222. * of the place where the connector touches the slice.
  223. *
  224. * - Data label options
  225. *
  226. * The function has to return an SVG path definition in array form
  227. * (see the example).
  228. *
  229. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-string/
  230. * connectorShape is a String
  231. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorshape-function/
  232. * connectorShape is a function
  233. *
  234. * @type {string|Function}
  235. * @since 7.0.0
  236. * @product highcharts
  237. */
  238. connectorShape: 'fixedOffset',
  239. /**
  240. * The width of the line connecting the data label to the pie slice.
  241. *
  242. * In styled mode, the connector stroke width is given in the
  243. * `.highcharts-data-label-connector` class.
  244. *
  245. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-connectorwidth-disabled/
  246. * Disable the connector
  247. * @sample {highcharts} highcharts/css/pie-point/
  248. * Styled connectors
  249. *
  250. * @type {number}
  251. * @default 1
  252. * @since 2.1
  253. * @product highcharts
  254. * @apioption plotOptions.pie.dataLabels.connectorWidth
  255. */
  256. /**
  257. * Works only if `connectorShape` is `'crookedLine'`. It defines how
  258. * far from the vertical plot edge the coonnector path should be
  259. * crooked.
  260. *
  261. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-crookdistance/
  262. * crookDistance set to 90%
  263. *
  264. * @since 7.0.0
  265. * @product highcharts
  266. */
  267. crookDistance: '70%',
  268. /**
  269. * The distance of the data label from the pie's edge. Negative
  270. * numbers put the data label on top of the pie slices. Can also be
  271. * defined as a percentage of pie's radius. Connectors are only
  272. * shown for data labels outside the pie.
  273. *
  274. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-distance/
  275. * Data labels on top of the pie
  276. *
  277. * @type {number|string}
  278. * @since 2.1
  279. * @product highcharts
  280. */
  281. distance: 30,
  282. enabled: true,
  283. formatter: function () {
  284. return this.point.isNull ? void 0 : this.point.name;
  285. },
  286. /**
  287. * Whether to render the connector as a soft arc or a line with
  288. * sharp break. Works only if `connectorShape` equals to
  289. * `fixedOffset`.
  290. *
  291. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-true/
  292. * Soft
  293. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-softconnector-false/
  294. * Non soft
  295. *
  296. * @since 2.1.7
  297. * @product highcharts
  298. */
  299. softConnector: true,
  300. /**
  301. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow
  302. * Long labels truncated with an ellipsis
  303. * @sample {highcharts} highcharts/plotoptions/pie-datalabels-overflow-wrap
  304. * Long labels are wrapped
  305. *
  306. * @type {Highcharts.CSSObject}
  307. * @apioption plotOptions.pie.dataLabels.style
  308. */
  309. x: 0
  310. },
  311. /**
  312. * If the total sum of the pie's values is 0, the series is represented
  313. * as an empty circle . The `fillColor` option defines the color of that
  314. * circle. Use [pie.borderWidth](#plotOptions.pie.borderWidth) to set
  315. * the border thickness.
  316. *
  317. * @sample {highcharts} highcharts/plotoptions/pie-emptyseries/
  318. * Empty pie series
  319. *
  320. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  321. * @private
  322. */
  323. fillColor: void 0,
  324. /**
  325. * The end angle of the pie in degrees where 0 is top and 90 is right.
  326. * Defaults to `startAngle` plus 360.
  327. *
  328. * @sample {highcharts} highcharts/demo/pie-semi-circle/
  329. * Semi-circle donut
  330. *
  331. * @type {number}
  332. * @since 1.3.6
  333. * @product highcharts
  334. * @apioption plotOptions.pie.endAngle
  335. */
  336. /**
  337. * Equivalent to [chart.ignoreHiddenSeries](#chart.ignoreHiddenSeries),
  338. * this option tells whether the series shall be redrawn as if the
  339. * hidden point were `null`.
  340. *
  341. * The default value changed from `false` to `true` with Highcharts
  342. * 3.0.
  343. *
  344. * @sample {highcharts} highcharts/plotoptions/pie-ignorehiddenpoint/
  345. * True, the hiddden point is ignored
  346. *
  347. * @since 2.3.0
  348. * @product highcharts
  349. *
  350. * @private
  351. */
  352. ignoreHiddenPoint: true,
  353. /**
  354. * @ignore-option
  355. *
  356. * @private
  357. */
  358. inactiveOtherPoints: true,
  359. /**
  360. * The size of the inner diameter for the pie. A size greater than 0
  361. * renders a donut chart. Can be a percentage or pixel value.
  362. * Percentages are relative to the pie size. Pixel values are given as
  363. * integers.
  364. *
  365. *
  366. * Note: in Highcharts < 4.1.2, the percentage was relative to the plot
  367. * area, not the pie size.
  368. *
  369. * @sample {highcharts} highcharts/plotoptions/pie-innersize-80px/
  370. * 80px inner size
  371. * @sample {highcharts} highcharts/plotoptions/pie-innersize-50percent/
  372. * 50% of the plot area
  373. * @sample {highcharts} highcharts/demo/3d-pie-donut/
  374. * 3D donut
  375. *
  376. * @type {number|string}
  377. * @default 0
  378. * @since 2.0
  379. * @product highcharts
  380. * @apioption plotOptions.pie.innerSize
  381. */
  382. /**
  383. * @ignore-option
  384. *
  385. * @private
  386. */
  387. legendType: 'point',
  388. /**
  389. * @ignore-option
  390. *
  391. * @private
  392. */
  393. marker: null,
  394. /**
  395. * The minimum size for a pie in response to auto margins. The pie will
  396. * try to shrink to make room for data labels in side the plot area,
  397. * but only to this size.
  398. *
  399. * @type {number|string}
  400. * @default 80
  401. * @since 3.0
  402. * @product highcharts
  403. * @apioption plotOptions.pie.minSize
  404. */
  405. /**
  406. * The diameter of the pie relative to the plot area. Can be a
  407. * percentage or pixel value. Pixel values are given as integers. The
  408. * default behaviour (as of 3.0) is to scale to the plot area and give
  409. * room for data labels within the plot area.
  410. * [slicedOffset](#plotOptions.pie.slicedOffset) is also included in the
  411. * default size calculation. As a consequence, the size of the pie may
  412. * vary when points are updated and data labels more around. In that
  413. * case it is best to set a fixed value, for example `"75%"`.
  414. *
  415. * @sample {highcharts} highcharts/plotoptions/pie-size/
  416. * Smaller pie
  417. *
  418. * @type {number|string|null}
  419. * @product highcharts
  420. *
  421. * @private
  422. */
  423. size: null,
  424. /**
  425. * Whether to display this particular series or series type in the
  426. * legend. Since 2.1, pies are not shown in the legend by default.
  427. *
  428. * @sample {highcharts} highcharts/plotoptions/series-showinlegend/
  429. * One series in the legend, one hidden
  430. *
  431. * @product highcharts
  432. *
  433. * @private
  434. */
  435. showInLegend: false,
  436. /**
  437. * If a point is sliced, moved out from the center, how many pixels
  438. * should it be moved?.
  439. *
  440. * @sample {highcharts} highcharts/plotoptions/pie-slicedoffset-20/
  441. * 20px offset
  442. *
  443. * @product highcharts
  444. *
  445. * @private
  446. */
  447. slicedOffset: 10,
  448. /**
  449. * The start angle of the pie slices in degrees where 0 is top and 90
  450. * right.
  451. *
  452. * @sample {highcharts} highcharts/plotoptions/pie-startangle-90/
  453. * Start from right
  454. *
  455. * @type {number}
  456. * @default 0
  457. * @since 2.3.4
  458. * @product highcharts
  459. * @apioption plotOptions.pie.startAngle
  460. */
  461. /**
  462. * Sticky tracking of mouse events. When true, the `mouseOut` event
  463. * on a series isn't triggered until the mouse moves over another
  464. * series, or out of the plot area. When false, the `mouseOut` event on
  465. * a series is triggered when the mouse leaves the area around the
  466. * series' graph or markers. This also implies the tooltip. When
  467. * `stickyTracking` is false and `tooltip.shared` is false, the tooltip
  468. * will be hidden when moving the mouse between series.
  469. *
  470. * @product highcharts
  471. *
  472. * @private
  473. */
  474. stickyTracking: false,
  475. tooltip: {
  476. followPointer: true
  477. },
  478. /**
  479. * The color of the border surrounding each slice. When `null`, the
  480. * border takes the same color as the slice fill. This can be used
  481. * together with a `borderWidth` to fill drawing gaps created by
  482. * antialiazing artefacts in borderless pies.
  483. *
  484. * In styled mode, the border stroke is given in the `.highcharts-point`
  485. * class.
  486. *
  487. * @sample {highcharts} highcharts/plotoptions/pie-bordercolor-black/
  488. * Black border
  489. *
  490. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  491. * @default #ffffff
  492. * @product highcharts
  493. *
  494. * @private
  495. */
  496. borderColor: '#ffffff',
  497. /**
  498. * The width of the border surrounding each slice.
  499. *
  500. * When setting the border width to 0, there may be small gaps between
  501. * the slices due to SVG antialiasing artefacts. To work around this,
  502. * keep the border width at 0.5 or 1, but set the `borderColor` to
  503. * `null` instead.
  504. *
  505. * In styled mode, the border stroke width is given in the
  506. * `.highcharts-point` class.
  507. *
  508. * @sample {highcharts} highcharts/plotoptions/pie-borderwidth/
  509. * 3px border
  510. *
  511. * @product highcharts
  512. *
  513. * @private
  514. */
  515. borderWidth: 1,
  516. /**
  517. * @ignore-options
  518. * @private
  519. */
  520. lineWidth: void 0,
  521. states: {
  522. /**
  523. * @extends plotOptions.series.states.hover
  524. * @excluding marker, lineWidth, lineWidthPlus
  525. * @product highcharts
  526. */
  527. hover: {
  528. /**
  529. * How much to brighten the point on interaction. Requires the
  530. * main color to be defined in hex or rgb(a) format.
  531. *
  532. * In styled mode, the hover brightness is by default replaced
  533. * by a fill-opacity given in the `.highcharts-point-hover`
  534. * class.
  535. *
  536. * @sample {highcharts} highcharts/plotoptions/pie-states-hover-brightness/
  537. * Brightened by 0.5
  538. *
  539. * @product highcharts
  540. */
  541. brightness: 0.1
  542. }
  543. }
  544. },
  545. /* eslint-disable valid-jsdoc */
  546. /**
  547. * @lends seriesTypes.pie.prototype
  548. */
  549. {
  550. isCartesian: false,
  551. requireSorting: false,
  552. directTouch: true,
  553. noSharedTooltip: true,
  554. trackerGroups: ['group', 'dataLabelsGroup'],
  555. axisTypes: [],
  556. pointAttribs: seriesTypes.column.prototype.pointAttribs,
  557. /**
  558. * Animate the pies in
  559. *
  560. * @private
  561. * @function Highcharts.seriesTypes.pie#animate
  562. *
  563. * @param {boolean} [init=false]
  564. */
  565. animate: function (init) {
  566. var series = this, points = series.points, startAngleRad = series.startAngleRad;
  567. if (!init) {
  568. points.forEach(function (point) {
  569. var graphic = point.graphic, args = point.shapeArgs;
  570. if (graphic && args) {
  571. // start values
  572. graphic.attr({
  573. // animate from inner radius (#779)
  574. r: pick(point.startR, (series.center && series.center[3] / 2)),
  575. start: startAngleRad,
  576. end: startAngleRad
  577. });
  578. // animate
  579. graphic.animate({
  580. r: args.r,
  581. start: args.start,
  582. end: args.end
  583. }, series.options.animation);
  584. }
  585. });
  586. }
  587. },
  588. // Define hasData function for non-cartesian series.
  589. // Returns true if the series has points at all.
  590. hasData: function () {
  591. return !!this.processedXData.length; // != 0
  592. },
  593. /**
  594. * Recompute total chart sum and update percentages of points.
  595. *
  596. * @private
  597. * @function Highcharts.seriesTypes.pie#updateTotals
  598. * @return {void}
  599. */
  600. updateTotals: function () {
  601. var i, total = 0, points = this.points, len = points.length, point, ignoreHiddenPoint = this.options.ignoreHiddenPoint;
  602. // Get the total sum
  603. for (i = 0; i < len; i++) {
  604. point = points[i];
  605. total += (ignoreHiddenPoint && !point.visible) ?
  606. 0 :
  607. point.isNull ?
  608. 0 :
  609. point.y;
  610. }
  611. this.total = total;
  612. // Set each point's properties
  613. for (i = 0; i < len; i++) {
  614. point = points[i];
  615. point.percentage =
  616. (total > 0 && (point.visible || !ignoreHiddenPoint)) ?
  617. point.y / total * 100 :
  618. 0;
  619. point.total = total;
  620. }
  621. },
  622. /**
  623. * Extend the generatePoints method by adding total and percentage
  624. * properties to each point
  625. *
  626. * @private
  627. * @function Highcharts.seriesTypes.pie#generatePoints
  628. * @return {void}
  629. */
  630. generatePoints: function () {
  631. Series.prototype.generatePoints.call(this);
  632. this.updateTotals();
  633. },
  634. /**
  635. * Utility for getting the x value from a given y, used for
  636. * anticollision logic in data labels. Added point for using specific
  637. * points' label distance.
  638. * @private
  639. */
  640. getX: function (y, left, point) {
  641. var center = this.center,
  642. // Variable pie has individual radius
  643. radius = this.radii ?
  644. this.radii[point.index] :
  645. center[2] / 2, angle, x;
  646. angle = Math.asin(clamp((y - center[1]) / (radius + point.labelDistance), -1, 1));
  647. x = center[0] +
  648. (left ? -1 : 1) *
  649. (Math.cos(angle) * (radius + point.labelDistance)) +
  650. (point.labelDistance > 0 ?
  651. (left ? -1 : 1) * this.options.dataLabels.padding :
  652. 0);
  653. return x;
  654. },
  655. /**
  656. * Do translation for pie slices
  657. *
  658. * @private
  659. * @function Highcharts.seriesTypes.pie#translate
  660. * @param {Array<number>} [positions]
  661. * @return {void}
  662. */
  663. translate: function (positions) {
  664. this.generatePoints();
  665. var series = this, cumulative = 0, precision = 1000, // issue #172
  666. options = series.options, slicedOffset = options.slicedOffset, connectorOffset = slicedOffset + (options.borderWidth || 0), finalConnectorOffset, start, end, angle, radians = getStartAndEndRadians(options.startAngle, options.endAngle), startAngleRad = series.startAngleRad = radians.start, endAngleRad = series.endAngleRad = radians.end, circ = endAngleRad - startAngleRad, // 2 * Math.PI,
  667. points = series.points,
  668. // the x component of the radius vector for a given point
  669. radiusX, radiusY, labelDistance = options.dataLabels.distance, ignoreHiddenPoint = options.ignoreHiddenPoint, i, len = points.length, point;
  670. // Get positions - either an integer or a percentage string must be
  671. // given. If positions are passed as a parameter, we're in a
  672. // recursive loop for adjusting space for data labels.
  673. if (!positions) {
  674. series.center = positions = series.getCenter();
  675. }
  676. // Calculate the geometry for each point
  677. for (i = 0; i < len; i++) {
  678. point = points[i];
  679. // set start and end angle
  680. start = startAngleRad + (cumulative * circ);
  681. if (!ignoreHiddenPoint || point.visible) {
  682. cumulative += point.percentage / 100;
  683. }
  684. end = startAngleRad + (cumulative * circ);
  685. // set the shape
  686. point.shapeType = 'arc';
  687. point.shapeArgs = {
  688. x: positions[0],
  689. y: positions[1],
  690. r: positions[2] / 2,
  691. innerR: positions[3] / 2,
  692. start: Math.round(start * precision) / precision,
  693. end: Math.round(end * precision) / precision
  694. };
  695. // Used for distance calculation for specific point.
  696. point.labelDistance = pick((point.options.dataLabels &&
  697. point.options.dataLabels.distance), labelDistance);
  698. // Compute point.labelDistance if it's defined as percentage
  699. // of slice radius (#8854)
  700. point.labelDistance = relativeLength(point.labelDistance, point.shapeArgs.r);
  701. // Saved for later dataLabels distance calculation.
  702. series.maxLabelDistance = Math.max(series.maxLabelDistance || 0, point.labelDistance);
  703. // The angle must stay within -90 and 270 (#2645)
  704. angle = (end + start) / 2;
  705. if (angle > 1.5 * Math.PI) {
  706. angle -= 2 * Math.PI;
  707. }
  708. else if (angle < -Math.PI / 2) {
  709. angle += 2 * Math.PI;
  710. }
  711. // Center for the sliced out slice
  712. point.slicedTranslation = {
  713. translateX: Math.round(Math.cos(angle) * slicedOffset),
  714. translateY: Math.round(Math.sin(angle) * slicedOffset)
  715. };
  716. // set the anchor point for tooltips
  717. radiusX = Math.cos(angle) * positions[2] / 2;
  718. radiusY = Math.sin(angle) * positions[2] / 2;
  719. point.tooltipPos = [
  720. positions[0] + radiusX * 0.7,
  721. positions[1] + radiusY * 0.7
  722. ];
  723. point.half = angle < -Math.PI / 2 || angle > Math.PI / 2 ?
  724. 1 :
  725. 0;
  726. point.angle = angle;
  727. // Set the anchor point for data labels. Use point.labelDistance
  728. // instead of labelDistance // #1174
  729. // finalConnectorOffset - not override connectorOffset value.
  730. finalConnectorOffset = Math.min(connectorOffset, point.labelDistance / 5); // #1678
  731. point.labelPosition = {
  732. natural: {
  733. // initial position of the data label - it's utilized for
  734. // finding the final position for the label
  735. x: positions[0] + radiusX + Math.cos(angle) *
  736. point.labelDistance,
  737. y: positions[1] + radiusY + Math.sin(angle) *
  738. point.labelDistance
  739. },
  740. 'final': {
  741. // used for generating connector path -
  742. // initialized later in drawDataLabels function
  743. // x: undefined,
  744. // y: undefined
  745. },
  746. // left - pie on the left side of the data label
  747. // right - pie on the right side of the data label
  748. // center - data label overlaps the pie
  749. alignment: point.labelDistance < 0 ?
  750. 'center' : point.half ? 'right' : 'left',
  751. connectorPosition: {
  752. breakAt: {
  753. x: positions[0] + radiusX + Math.cos(angle) *
  754. finalConnectorOffset,
  755. y: positions[1] + radiusY + Math.sin(angle) *
  756. finalConnectorOffset
  757. },
  758. touchingSliceAt: {
  759. x: positions[0] + radiusX,
  760. y: positions[1] + radiusY
  761. }
  762. }
  763. };
  764. }
  765. fireEvent(series, 'afterTranslate');
  766. },
  767. /**
  768. * Called internally to draw auxiliary graph in pie-like series in
  769. * situtation when the default graph is not sufficient enough to present
  770. * the data well. Auxiliary graph is saved in the same object as
  771. * regular graph.
  772. *
  773. * @private
  774. * @function Highcharts.seriesTypes.pie#drawEmpty
  775. */
  776. drawEmpty: function () {
  777. var centerX, centerY, start = this.startAngleRad, end = this.endAngleRad, options = this.options;
  778. // Draw auxiliary graph if there're no visible points.
  779. if (this.total === 0) {
  780. centerX = this.center[0];
  781. centerY = this.center[1];
  782. if (!this.graph) {
  783. this.graph = this.chart.renderer
  784. .arc(centerX, centerY, this.center[1] / 2, 0, start, end)
  785. .addClass('highcharts-empty-series')
  786. .add(this.group);
  787. }
  788. this.graph.attr({
  789. d: Highcharts.SVGRenderer.prototype.symbols.arc(centerX, centerY, this.center[2] / 2, 0, {
  790. start: start,
  791. end: end,
  792. innerR: this.center[3] / 2
  793. })
  794. });
  795. if (!this.chart.styledMode) {
  796. this.graph.attr({
  797. 'stroke-width': options.borderWidth,
  798. fill: options.fillColor || 'none',
  799. stroke: options.color ||
  800. '#cccccc'
  801. });
  802. }
  803. }
  804. else if (this.graph) { // Destroy the graph object.
  805. this.graph = this.graph.destroy();
  806. }
  807. },
  808. /**
  809. * Draw the data points
  810. *
  811. * @private
  812. * @function Highcharts.seriesTypes.pie#drawPoints
  813. * @return {void}
  814. */
  815. redrawPoints: function () {
  816. var series = this, chart = series.chart, renderer = chart.renderer, groupTranslation, graphic, pointAttr, shapeArgs, shadow = series.options.shadow;
  817. this.drawEmpty();
  818. if (shadow && !series.shadowGroup && !chart.styledMode) {
  819. series.shadowGroup = renderer.g('shadow')
  820. .attr({ zIndex: -1 })
  821. .add(series.group);
  822. }
  823. // draw the slices
  824. series.points.forEach(function (point) {
  825. var animateTo = {};
  826. graphic = point.graphic;
  827. if (!point.isNull && graphic) {
  828. shapeArgs = point.shapeArgs;
  829. // If the point is sliced, use special translation, else use
  830. // plot area translation
  831. groupTranslation = point.getTranslate();
  832. if (!chart.styledMode) {
  833. // Put the shadow behind all points
  834. var shadowGroup = point.shadowGroup;
  835. if (shadow && !shadowGroup) {
  836. shadowGroup = point.shadowGroup = renderer
  837. .g('shadow')
  838. .add(series.shadowGroup);
  839. }
  840. if (shadowGroup) {
  841. shadowGroup.attr(groupTranslation);
  842. }
  843. pointAttr = series.pointAttribs(point, (point.selected && 'select'));
  844. }
  845. // Draw the slice
  846. if (!point.delayedRendering) {
  847. graphic
  848. .setRadialReference(series.center);
  849. if (!chart.styledMode) {
  850. merge(true, animateTo, pointAttr);
  851. }
  852. merge(true, animateTo, shapeArgs, groupTranslation);
  853. graphic.animate(animateTo);
  854. }
  855. else {
  856. graphic
  857. .setRadialReference(series.center)
  858. .attr(shapeArgs)
  859. .attr(groupTranslation);
  860. if (!chart.styledMode) {
  861. graphic
  862. .attr(pointAttr)
  863. .attr({ 'stroke-linejoin': 'round' })
  864. .shadow(shadow, shadowGroup);
  865. }
  866. point.delayedRendering = false;
  867. }
  868. graphic.attr({
  869. visibility: point.visible ? 'inherit' : 'hidden'
  870. });
  871. graphic.addClass(point.getClassName());
  872. }
  873. else if (graphic) {
  874. point.graphic = graphic.destroy();
  875. }
  876. });
  877. },
  878. /**
  879. * Slices in pie chart are initialized in DOM, but it's shapes and
  880. * animations are normally run in `drawPoints()`.
  881. * @private
  882. */
  883. drawPoints: function () {
  884. var renderer = this.chart.renderer;
  885. this.points.forEach(function (point) {
  886. // When updating a series between 2d and 3d or cartesian and
  887. // polar, the shape type changes.
  888. if (point.graphic && point.hasNewShapeType()) {
  889. point.graphic = point.graphic.destroy();
  890. }
  891. if (!point.graphic) {
  892. point.graphic = renderer[point.shapeType](point.shapeArgs)
  893. .add(point.series.group);
  894. point.delayedRendering = true;
  895. }
  896. });
  897. },
  898. /**
  899. * @private
  900. * @deprecated
  901. * @function Highcharts.seriesTypes.pie#searchPoint
  902. */
  903. searchPoint: noop,
  904. /**
  905. * Utility for sorting data labels
  906. *
  907. * @private
  908. * @function Highcharts.seriesTypes.pie#sortByAngle
  909. * @param {Array<Highcharts.Point>} points
  910. * @param {number} sign
  911. * @return {void}
  912. */
  913. sortByAngle: function (points, sign) {
  914. points.sort(function (a, b) {
  915. return ((typeof a.angle !== 'undefined') &&
  916. (b.angle - a.angle) * sign);
  917. });
  918. },
  919. /**
  920. * Use a simple symbol from LegendSymbolMixin.
  921. *
  922. * @private
  923. * @borrows Highcharts.LegendSymbolMixin.drawRectangle as Highcharts.seriesTypes.pie#drawLegendSymbol
  924. */
  925. drawLegendSymbol: LegendSymbolMixin.drawRectangle,
  926. /**
  927. * Use the getCenter method from drawLegendSymbol.
  928. *
  929. * @private
  930. * @borrows Highcharts.CenteredSeriesMixin.getCenter as Highcharts.seriesTypes.pie#getCenter
  931. */
  932. getCenter: CenteredSeriesMixin.getCenter,
  933. /**
  934. * Pies don't have point marker symbols.
  935. *
  936. * @deprecated
  937. * @private
  938. * @function Highcharts.seriesTypes.pie#getSymbol
  939. */
  940. getSymbol: noop,
  941. /**
  942. * @private
  943. * @type {null}
  944. */
  945. drawGraph: null
  946. },
  947. /**
  948. * @lends seriesTypes.pie.prototype.pointClass.prototype
  949. */
  950. {
  951. /**
  952. * Initialize the pie slice
  953. *
  954. * @private
  955. * @function Highcharts.seriesTypes.pie#pointClass#init
  956. * @return {Highcharts.Point}
  957. */
  958. init: function () {
  959. Point.prototype.init.apply(this, arguments);
  960. var point = this, toggleSlice;
  961. point.name = pick(point.name, 'Slice');
  962. // add event listener for select
  963. toggleSlice = function (e) {
  964. point.slice(e.type === 'select');
  965. };
  966. addEvent(point, 'select', toggleSlice);
  967. addEvent(point, 'unselect', toggleSlice);
  968. return point;
  969. },
  970. /**
  971. * Negative points are not valid (#1530, #3623, #5322)
  972. *
  973. * @private
  974. * @function Highcharts.seriesTypes.pie#pointClass#isValid
  975. * @return {boolean}
  976. */
  977. isValid: function () {
  978. return isNumber(this.y) && this.y >= 0;
  979. },
  980. /**
  981. * Toggle the visibility of the pie slice
  982. *
  983. * @private
  984. * @function Highcharts.seriesTypes.pie#pointClass#setVisible
  985. * @param {boolean} vis
  986. * Whether to show the slice or not. If undefined, the visibility
  987. * is toggled.
  988. * @param {boolean} [redraw=false]
  989. * @return {void}
  990. */
  991. setVisible: function (vis, redraw) {
  992. var point = this, series = point.series, chart = series.chart, ignoreHiddenPoint = series.options.ignoreHiddenPoint;
  993. redraw = pick(redraw, ignoreHiddenPoint);
  994. if (vis !== point.visible) {
  995. // If called without an argument, toggle visibility
  996. point.visible = point.options.visible = vis =
  997. typeof vis === 'undefined' ? !point.visible : vis;
  998. // update userOptions.data
  999. series.options.data[series.data.indexOf(point)] =
  1000. point.options;
  1001. // Show and hide associated elements. This is performed
  1002. // regardless of redraw or not, because chart.redraw only
  1003. // handles full series.
  1004. ['graphic', 'dataLabel', 'connector', 'shadowGroup'].forEach(function (key) {
  1005. if (point[key]) {
  1006. point[key][vis ? 'show' : 'hide'](true);
  1007. }
  1008. });
  1009. if (point.legendItem) {
  1010. chart.legend.colorizeItem(point, vis);
  1011. }
  1012. // #4170, hide halo after hiding point
  1013. if (!vis && point.state === 'hover') {
  1014. point.setState('');
  1015. }
  1016. // Handle ignore hidden slices
  1017. if (ignoreHiddenPoint) {
  1018. series.isDirty = true;
  1019. }
  1020. if (redraw) {
  1021. chart.redraw();
  1022. }
  1023. }
  1024. },
  1025. /**
  1026. * Set or toggle whether the slice is cut out from the pie
  1027. *
  1028. * @private
  1029. * @function Highcharts.seriesTypes.pie#pointClass#slice
  1030. * @param {boolean} sliced
  1031. * When undefined, the slice state is toggled.
  1032. * @param {boolean} redraw
  1033. * Whether to redraw the chart. True by default.
  1034. * @param {boolean|Highcharts.AnimationOptionsObject}
  1035. * Animation options.
  1036. * @return {void}
  1037. */
  1038. slice: function (sliced, redraw, animation) {
  1039. var point = this, series = point.series, chart = series.chart;
  1040. setAnimation(animation, chart);
  1041. // redraw is true by default
  1042. redraw = pick(redraw, true);
  1043. /**
  1044. * Pie series only. Whether to display a slice offset from the
  1045. * center.
  1046. * @name Highcharts.Point#sliced
  1047. * @type {boolean|undefined}
  1048. */
  1049. // if called without an argument, toggle
  1050. point.sliced = point.options.sliced = sliced =
  1051. defined(sliced) ? sliced : !point.sliced;
  1052. // update userOptions.data
  1053. series.options.data[series.data.indexOf(point)] =
  1054. point.options;
  1055. if (point.graphic) {
  1056. point.graphic.animate(this.getTranslate());
  1057. }
  1058. if (point.shadowGroup) {
  1059. point.shadowGroup.animate(this.getTranslate());
  1060. }
  1061. },
  1062. /**
  1063. * @private
  1064. * @function Highcharts.seriesTypes.pie#pointClass#getTranslate
  1065. * @return {Highcharts.TranslationAttributes}
  1066. */
  1067. getTranslate: function () {
  1068. return this.sliced ? this.slicedTranslation : {
  1069. translateX: 0,
  1070. translateY: 0
  1071. };
  1072. },
  1073. /**
  1074. * @private
  1075. * @function Highcharts.seriesTypes.pie#pointClass#haloPath
  1076. * @param {number} size
  1077. * @return {Highcharts.SVGPathArray}
  1078. */
  1079. haloPath: function (size) {
  1080. var shapeArgs = this.shapeArgs;
  1081. return this.sliced || !this.visible ?
  1082. [] :
  1083. this.series.chart.renderer.symbols.arc(shapeArgs.x, shapeArgs.y, shapeArgs.r + size, shapeArgs.r + size, {
  1084. // Substract 1px to ensure the background is not bleeding
  1085. // through between the halo and the slice (#7495).
  1086. innerR: shapeArgs.r - 1,
  1087. start: shapeArgs.start,
  1088. end: shapeArgs.end
  1089. });
  1090. },
  1091. connectorShapes: {
  1092. // only one available before v7.0.0
  1093. fixedOffset: function (labelPosition, connectorPosition, options) {
  1094. var breakAt = connectorPosition.breakAt, touchingSliceAt = connectorPosition.touchingSliceAt, lineSegment = options.softConnector ? [
  1095. 'C',
  1096. // 1st control point (of the curve)
  1097. labelPosition.x +
  1098. // 5 gives the connector a little horizontal bend
  1099. (labelPosition.alignment === 'left' ? -5 : 5),
  1100. labelPosition.y,
  1101. 2 * breakAt.x - touchingSliceAt.x,
  1102. 2 * breakAt.y - touchingSliceAt.y,
  1103. breakAt.x,
  1104. breakAt.y //
  1105. ] : [
  1106. 'L',
  1107. breakAt.x,
  1108. breakAt.y
  1109. ];
  1110. // assemble the path
  1111. return ([
  1112. ['M', labelPosition.x, labelPosition.y],
  1113. lineSegment,
  1114. ['L', touchingSliceAt.x, touchingSliceAt.y]
  1115. ]);
  1116. },
  1117. straight: function (labelPosition, connectorPosition) {
  1118. var touchingSliceAt = connectorPosition.touchingSliceAt;
  1119. // direct line to the slice
  1120. return [
  1121. ['M', labelPosition.x, labelPosition.y],
  1122. ['L', touchingSliceAt.x, touchingSliceAt.y]
  1123. ];
  1124. },
  1125. crookedLine: function (labelPosition, connectorPosition, options) {
  1126. var touchingSliceAt = connectorPosition.touchingSliceAt, series = this.series, pieCenterX = series.center[0], plotWidth = series.chart.plotWidth, plotLeft = series.chart.plotLeft, alignment = labelPosition.alignment, radius = this.shapeArgs.r, crookDistance = relativeLength(// % to fraction
  1127. options.crookDistance, 1), crookX = alignment === 'left' ?
  1128. pieCenterX + radius + (plotWidth + plotLeft -
  1129. pieCenterX - radius) * (1 - crookDistance) :
  1130. plotLeft + (pieCenterX - radius) * crookDistance, segmentWithCrook = [
  1131. 'L',
  1132. crookX,
  1133. labelPosition.y
  1134. ], useCrook = true;
  1135. // crookedLine formula doesn't make sense if the path overlaps
  1136. // the label - use straight line instead in that case
  1137. if (alignment === 'left' ?
  1138. (crookX > labelPosition.x || crookX < touchingSliceAt.x) :
  1139. (crookX < labelPosition.x || crookX > touchingSliceAt.x)) {
  1140. useCrook = false;
  1141. }
  1142. // assemble the path
  1143. var path = [
  1144. ['M', labelPosition.x, labelPosition.y]
  1145. ];
  1146. if (useCrook) {
  1147. path.push(segmentWithCrook);
  1148. }
  1149. path.push(['L', touchingSliceAt.x, touchingSliceAt.y]);
  1150. return path;
  1151. }
  1152. },
  1153. /**
  1154. * Extendable method for getting the path of the connector between the
  1155. * data label and the pie slice.
  1156. */
  1157. getConnectorPath: function () {
  1158. var labelPosition = this.labelPosition, options = this.series.options.dataLabels, connectorShape = options.connectorShape, predefinedShapes = this.connectorShapes;
  1159. // find out whether to use the predefined shape
  1160. if (predefinedShapes[connectorShape]) {
  1161. connectorShape = predefinedShapes[connectorShape];
  1162. }
  1163. return connectorShape.call(this, {
  1164. // pass simplified label position object for user's convenience
  1165. x: labelPosition.final.x,
  1166. y: labelPosition.final.y,
  1167. alignment: labelPosition.alignment
  1168. }, labelPosition.connectorPosition, options);
  1169. }
  1170. }
  1171. /* eslint-enable valid-jsdoc */
  1172. );
  1173. /**
  1174. * A `pie` series. If the [type](#series.pie.type) option is not specified,
  1175. * it is inherited from [chart.type](#chart.type).
  1176. *
  1177. * @extends series,plotOptions.pie
  1178. * @excluding dataParser, dataURL, stack, xAxis, yAxis, dataSorting, step
  1179. * @product highcharts
  1180. * @apioption series.pie
  1181. */
  1182. /**
  1183. * An array of data points for the series. For the `pie` series type,
  1184. * points can be given in the following ways:
  1185. *
  1186. * 1. An array of numerical values. In this case, the numerical values will be
  1187. * interpreted as `y` options. Example:
  1188. * ```js
  1189. * data: [0, 5, 3, 5]
  1190. * ```
  1191. *
  1192. * 2. An array of objects with named values. The following snippet shows only a
  1193. * few settings, see the complete options set below. If the total number of
  1194. * data points exceeds the series'
  1195. * [turboThreshold](#series.pie.turboThreshold),
  1196. * this option is not available.
  1197. * ```js
  1198. * data: [{
  1199. * y: 1,
  1200. * name: "Point2",
  1201. * color: "#00FF00"
  1202. * }, {
  1203. * y: 7,
  1204. * name: "Point1",
  1205. * color: "#FF00FF"
  1206. * }]
  1207. * ```
  1208. *
  1209. * @sample {highcharts} highcharts/chart/reflow-true/
  1210. * Numerical values
  1211. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1212. * Arrays of numeric x and y
  1213. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1214. * Arrays of datetime x and y
  1215. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1216. * Arrays of point.name and y
  1217. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1218. * Config objects
  1219. *
  1220. * @type {Array<number|Array<string,(number|null)>|null|*>}
  1221. * @extends series.line.data
  1222. * @excluding marker, x
  1223. * @product highcharts
  1224. * @apioption series.pie.data
  1225. */
  1226. /**
  1227. * @type {Highcharts.SeriesPieDataLabelsOptionsObject}
  1228. * @product highcharts
  1229. * @apioption series.pie.data.dataLabels
  1230. */
  1231. /**
  1232. * The sequential index of the data point in the legend.
  1233. *
  1234. * @type {number}
  1235. * @product highcharts
  1236. * @apioption series.pie.data.legendIndex
  1237. */
  1238. /**
  1239. * Whether to display a slice offset from the center.
  1240. *
  1241. * @sample {highcharts} highcharts/point/sliced/
  1242. * One sliced point
  1243. *
  1244. * @type {boolean}
  1245. * @product highcharts
  1246. * @apioption series.pie.data.sliced
  1247. */
  1248. /**
  1249. * @excluding legendItemClick
  1250. * @product highcharts
  1251. * @apioption series.pie.events
  1252. */
  1253. ''; // placeholder for transpiled doclets above