Unverified Commit c2f34d52 authored by 偏右's avatar 偏右 Committed by GitHub

Better pie responsive (#37)

* refactor Pie

* Less js calculation

* Responsive Pie

* Fix pies height

* use react-fittext
parent 57eb471a
......@@ -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",
......
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,30 +188,31 @@ class Pie extends Component {
</div>
)
}
{
hasLegend && (
<ul className={styles.legend} style={{ marginTop: mt }}>
{
legendData.map((item, i) => (
<li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
<span className={styles.dot} style={{ backgroundColor: !item.checked ? '#aaa' : item.color }} />
<span className={styles.legendTitle}>{item.x}</span>
<Divider type="vertical" />
<span className={styles.percent}>{`${(item['..percent'] * 100).toFixed(2)}%`}</span>
<span
className={styles.value}
dangerouslySetInnerHTML={{
__html: valueFormat ? valueFormat(item.y) : item.y,
}}
/>
</li>
))
}
</ul>
)
}
</div>
</div>
</ReactFitText>
{
hasLegend && (
<ul className={styles.legend}>
{
legendData.map((item, i) => (
<li key={item.x} onClick={() => this.handleLegendClick(item, i)}>
<span className={styles.dot} style={{ backgroundColor: !item.checked ? '#aaa' : item.color }} />
<span className={styles.legendTitle}>{item.x}</span>
<Divider type="vertical" />
<span className={styles.percent}>{`${(item['..percent'] * 100).toFixed(2)}%`}</span>
<span
className={styles.value}
dangerouslySetInnerHTML={{
__html: valueFormat ? valueFormat(item.y) : item.y,
}}
/>
</li>
))
}
</ul>
)
}
</div>
);
}
......
......@@ -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;
}
}
}
......@@ -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 | - |
......
......@@ -436,18 +436,17 @@ export default class Analysis extends Component {
)}
style={{ marginTop: 24 }}
>
<div style={{ marginTop: 8, marginBottom: 77 }}>
<Pie
hasLegend
title="销售额"
subTitle="销售额"
total={yuan(salesPieData.reduce((pre, now) => now.y + pre, 0))}
data={salesPieData}
valueFormat={val => yuan(val)}
height={268}
lineWidth={4}
/>
</div>
<h4 style={{ marginTop: 8, marginBottom: 32 }}>销售额</h4>
<Pie
hasLegend
subTitle="销售额"
total={yuan(salesPieData.reduce((pre, now) => now.y + pre, 0))}
data={salesPieData}
valueFormat={val => yuan(val)}
height={240}
lineWidth={4}
style={{ marginBottom: 52 }}
/>
</Card>
</Col>
</Row>
......
......@@ -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>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment