Browse Source

Better pie responsive (#37)

* refactor Pie

* Less js calculation

* Responsive Pie

* Fix pies height

* use react-fittext
pull/39/head
偏右 9 years ago
committed by GitHub
parent
commit
c2f34d5246
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      package.json
  2. 70
      src/components/Charts/Pie/index.js
  3. 32
      src/components/Charts/Pie/index.less
  4. 1
      src/components/Charts/index.md
  5. 7
      src/routes/Dashboard/Analysis.js
  6. 6
      src/routes/Dashboard/Monitor.js

3
package.json

@ -30,7 +30,8 @@
"qs": "^6.5.0",
"react": "^16.0.0",
"react-document-title": "^2.0.3",
"react-dom": "^16.0.0"
"react-dom": "^16.0.0",
"react-fittext": "^1.0.0"
},
"devDependencies": {
"babel-eslint": "^8.0.1",

70
src/components/Charts/Pie/index.js

@ -1,6 +1,8 @@
import React, { Component } from 'react';
import G2 from 'g2';
import { Divider } from 'antd';
import classNames from 'classnames';
import ReactFitText from 'react-fittext';
import equal from '../equal';
import styles from './index.less';
@ -8,8 +10,7 @@ import styles from './index.less';
class Pie extends Component {
state = {
legendData: [],
left: undefined,
}
};
componentDidMount() {
this.renderChart(this.props.data);
@ -30,9 +31,6 @@ class Pie extends Component {
handleRef = (n) => {
this.node = n;
}
handleTotalRef = (n) => {
this.totalNode = n;
}
handleLegendClick = (item, i) => {
const newItem = item;
@ -54,8 +52,9 @@ class Pie extends Component {
renderChart(data) {
const {
title, height = 0,
hasLegend, fit = true,
height = 0,
hasLegend,
fit = true,
margin, percent, color,
inner = 0.75,
animate = true,
@ -97,19 +96,6 @@ class Pie extends Component {
return;
}
let m = margin;
if (!margin) {
if (hasLegend) {
m = [24, 240, 24, 8];
} else if (percent) {
m = [0, 0, 0, 0];
} else {
m = [24, 0, 24, 0];
}
}
const h = title ? (height + m[0] + m[2] + (-46)) : (height + m[0] + m[2]);
// clean
this.node.innerHTML = '';
@ -118,9 +104,9 @@ class Pie extends Component {
const chart = new G2.Chart({
container: this.node,
forceFit: fit,
height: h,
height,
plotCfg: {
margin: m,
margin,
},
animate,
});
@ -176,36 +162,25 @@ class Pie extends Component {
this.setState({
legendData,
}, () => {
let left = 0;
if (this.totalNode) {
left = -((this.totalNode.offsetWidth / 2) + ((margin || m)[1] / 2)) + lineWidth;
}
this.setState({ left });
});
}
render() {
const { height, title, valueFormat, subTitle, total, hasLegend } = this.props;
const { legendData, left } = this.state;
const mt = -(((legendData.length * 38) - 16) / 2);
const { valueFormat, subTitle, total, hasLegend, className, style } = this.props;
const { legendData } = this.state;
const pieClassName = classNames(styles.pie, className, {
[styles.hasLegend]: !!hasLegend,
});
return (
<div className={styles.pie} style={{ height }}>
<div>
{title && <h4 className={styles.title}>{title}</h4>}
<div className={styles.content}>
<div ref={this.handleRef} />
<div className={pieClassName} style={style}>
<ReactFitText maxFontSize={40}>
<div className={styles.chart}>
<div ref={this.handleRef} style={{ fontSize: 0 }} />
{
(subTitle || total) && (
<div
className={styles.total}
ref={this.handleTotalRef}
style={{ marginLeft: left, opacity: left ? 1 : 0 }}
>
{
subTitle && <h4 className="pie-sub-title">{subTitle}</h4>
}
<div className={styles.total}>
{subTitle && <h4 className="pie-sub-title">{subTitle}</h4>}
{
// eslint-disable-next-line
total && <p className="pie-stat" dangerouslySetInnerHTML={{ __html: total }} />
@ -213,9 +188,12 @@ class Pie extends Component {
</div>
)
}
</div>
</ReactFitText>
{
hasLegend && (
<ul className={styles.legend} style={{ marginTop: mt }}>
<ul className={styles.legend}>
{
legendData.map((item, i) => (
<li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
@ -236,8 +214,6 @@ class Pie extends Component {
)
}
</div>
</div>
</div>
);
}
}

32
src/components/Charts/Pie/index.less

@ -2,19 +2,28 @@
@import "../../../utils/utils.less";
.pie {
.content {
position: relative;
.chart {
position: relative;
}
&.hasLegend .chart {
width: ~"calc(100% - 264px)";
margin-left: 24px;
}
.legend {
position: absolute;
top: 50%;
right: 0;
min-width: 200px;
top: 50%;
transform: translateY(-50%);
li {
cursor: pointer;
margin-bottom: 16px;
height: 22px;
line-height: 22px;
&:last-child {
margin-bottom: 0;
}
}
}
.dot {
@ -47,13 +56,12 @@
margin-bottom: 8px;
}
.total {
opacity: 0;
position: absolute;
left: 50%;
top: 50%;
margin-top: -34px;
text-align: center;
height: 62px;
transform: translate(-50%, -50%);
& > h4 {
color: @text-color-secondary;
font-size: 14px;
@ -65,9 +73,23 @@
& > p {
color: @heading-color;
display: block;
font-size: 30px;
font-size: 1.3em;
height: 32px;
line-height: 32px;
white-space: nowrap;
}
}
}
@media screen and (max-width: @screen-sm) {
.pie {
&.hasLegend .chart {
width: 100%;
margin: 0 0 32px 0;
}
.legend {
position: static;
transform: none;
}
}
}

1
src/components/Charts/index.md

@ -71,7 +71,6 @@ Ant Design Pro 提供的业务中常用的图表类型,都是基于 [G2](https
| hasLegend | 是否显示 legend | boolean | `false` |
| margin | 图表内部间距 | array | \[24, 0, 24, 0\] |
| percent | 占比 | number | - |
| title | 图表标题 | ReactNode\|string | - |
| tooltip | 是否显示 tooltip | boolean | true |
| valueFormat | 显示值的格式化函数 | function | - |
| subTitle | 图表子标题 | ReactNode\|string | - |

7
src/routes/Dashboard/Analysis.js

@ -436,18 +436,17 @@ export default class Analysis extends Component {
)}
style={{ marginTop: 24 }}
>
<div style={{ marginTop: 8, marginBottom: 77 }}>
<h4 style={{ marginTop: 8, marginBottom: 32 }}>销售额</h4>
<Pie
hasLegend
title="销售额"
subTitle="销售额"
total={yuan(salesPieData.reduce((pre, now) => now.y + pre, 0))}
data={salesPieData}
valueFormat={val => yuan(val)}
height={268}
height={240}
lineWidth={4}
style={{ marginBottom: 52 }}
/>
</div>
</Card>
</Col>
</Row>

6
src/routes/Dashboard/Monitor.js

@ -119,7 +119,7 @@ export default class Monitor extends PureComponent {
percent={28}
subTitle="中式快餐"
total="28%"
height={129}
height={128}
lineWidth={2}
/>
</Col>
@ -130,7 +130,7 @@ export default class Monitor extends PureComponent {
percent={22}
subTitle="西餐"
total="22%"
height={129}
height={128}
lineWidth={2}
/>
</Col>
@ -141,7 +141,7 @@ export default class Monitor extends PureComponent {
percent={32}
subTitle="火锅"
total="32%"
height={129}
height={128}
lineWidth={2}
/>
</Col>

Loading…
Cancel
Save