Pie.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * 封装的饼图
  3. * @zjf-2021-06-30
  4. * */
  5. import React, { Component, Fragment } from 'react';
  6. import global from '@/global.less';
  7. import DataSet from '@antv/data-set';
  8. import { noDataPlaceholder } from '@/utils/utils';
  9. import {
  10. Chart,
  11. Geom,
  12. Axis,
  13. Tooltip,
  14. Coord,
  15. Label,
  16. Legend,
  17. } from 'bizcharts';
  18. export default class Pie extends Component {
  19. constructor(props) {
  20. super(props);
  21. this.state = {
  22. cols: {
  23. month: {
  24. range: [0, 1],
  25. },
  26. },
  27. pieData: props.data,
  28. dv: '',
  29. colsPie: {
  30. percent: {
  31. formatter: val => {
  32. val = (val * 100).toFixed(2) + '%';
  33. return val;
  34. },
  35. },
  36. },
  37. scaleWidth: window.innerWidth,
  38. axisType: props.axisType === 'amount' ? props.axisType : 'number',
  39. };
  40. }
  41. componentDidMount() {
  42. this.initData();
  43. window.addEventListener('resize', () => {
  44. this.setState({ scaleWidth: 0 }, () => {
  45. this.setState({ scaleWidth: window.innerWidth });
  46. });
  47. });
  48. }
  49. componentWillReceiveProps(nextProps, nextContext) {
  50. let _this = this;
  51. if (JSON.stringify(nextProps.data) != JSON.stringify(this.props.data)) {
  52. this.setState({ pieData: nextProps.data, axisType: nextProps.axisType }, () => {
  53. _this.initData();
  54. });
  55. }
  56. }
  57. initData = () => {
  58. let { pieData } = this.state;
  59. const { DataView } = DataSet;
  60. let dv = new DataView();
  61. if (pieData.length > 0) {
  62. dv.source(pieData).transform({
  63. type: 'percent',
  64. field: 'count',
  65. dimension: 'item',
  66. as: 'percent',
  67. });
  68. } else {
  69. dv = '';
  70. }
  71. this.setState({
  72. dv,
  73. });
  74. };
  75. render() {
  76. const { colsPie, dv, scaleWidth, axisType } = this.state;
  77. const { tipTitle, showNumPrecision } = this.props;
  78. return (
  79. <Fragment>
  80. {dv ? <div class='pie_charts_custom_style'>
  81. <Chart
  82. data={dv}
  83. scale={colsPie}
  84. padding={[130000 / scaleWidth, 0, 130000 / scaleWidth, 0]}
  85. forceFit
  86. onGetG2Instance={c => {
  87. function getXY(c, { index: idx = 0, field = 'percent', radius = 0.5 }) {
  88. const d = c.get('data');
  89. if (idx > d.length) return;
  90. const scales = c.get('scales');
  91. let sum = 0;
  92. for (let i = 0; i < idx + 1; i++) {
  93. let val = d[i][field];
  94. if (i === idx) {
  95. val = val / 2;
  96. }
  97. sum += val;
  98. }
  99. const pt = {
  100. y: scales[field].scale(sum),
  101. x: radius,
  102. };
  103. const coord = c.get('coord');
  104. let xy = coord.convert(pt);
  105. return xy;
  106. }
  107. const xy = getXY(c, { index: 0 });
  108. c.showTooltip(xy);
  109. }}
  110. >
  111. <Coord type="theta" radius={0.75}/>
  112. <Axis name="percent"/>
  113. <Legend
  114. position="top"
  115. offsetY={-30}
  116. allowAllCanceled={true}
  117. />
  118. <Tooltip
  119. itemTpl='<li><span style="background-color:{color};" class="g2-tooltip-marker"></span>{name}: {value}</li>'
  120. g2-tooltip={{
  121. backgroundColor: 'black',
  122. color: '#fff',
  123. opacity: '0.9',
  124. }}
  125. />
  126. <Geom
  127. type="intervalStack"
  128. position="percent"
  129. color="item"
  130. tooltip={[
  131. 'item*percent*count',
  132. (item, percent, count) => {
  133. return {
  134. title: tipTitle ? tipTitle : '销售额',
  135. name: item,
  136. value: `<span style="margin-right: 8px;margin-left: 12px;">${axisType === 'amount' ? '¥' : ''}${count.toFixed(showNumPrecision != undefined ? showNumPrecision : 2)}</span>` + (percent * 100).toFixed(2) + '%',
  137. };
  138. },
  139. ]}
  140. style={{
  141. lineWidth: 1,
  142. stroke: '#fff',
  143. }}
  144. >
  145. <Label
  146. content="percent"
  147. formatter={(val, item) => {
  148. return item.point.item + ': ' + val;
  149. }}
  150. />
  151. </Geom>
  152. </Chart>
  153. </div> : noDataPlaceholder()}
  154. </Fragment>
  155. );
  156. }
  157. }