Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
feat: 自定义图例基本实现
Browse files Browse the repository at this point in the history
  • Loading branch information
wangxingkang committed Jul 3, 2019
1 parent eba220c commit ae20b28
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 2 deletions.
2 changes: 1 addition & 1 deletion docs/bar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import Bar from '@charts/bar';
/>
</Playground>

# 堆叠柱状图
## 堆叠柱状图

<Playground>
<Bar
Expand Down
18 changes: 18 additions & 0 deletions docs/pie.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ import Pie from '@charts/pie';
/>
</Playground>

## 显示详细图例

<Playground>
<Pie
data={[
{ x: 'chrome', y: 100 },
{ x: 'IE', y: 30 },
{ x: 'Firefox', y: 50 }
]}
tooltip={true}
innerRadius={0.75}
subTitle="总预警数"
total={100}
height={300}
hasLegend={true}
/>
</Playground>

## 自定义

<Playground>
Expand Down
58 changes: 58 additions & 0 deletions src/pie/pie-chart.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,64 @@
position: relative;
}

&.show-legend &__chart {
width: 60%;
}

&__legend {
position: absolute;
top: 50%;
right: 0;
width: 40%;
margin-left: 15px;
padding: 0;
list-style: none;
transform: translateY(-50%);

li {
position: relative;
display: flex;
height: 22px;
padding: 12px 0;
margin-bottom: 16px;
line-height: 22px;
border-bottom: 1px solid #dfdfdf;
cursor: pointer;
align-items: center;

&:last-child {
margin-bottom: 0;
}

> div {
width: 33%;
}
}

.dot {
position: relative;
top: -1px;
display: inline-block;
width: 8px;
height: 8px;
margin-right: 8px;
border-radius: 8px;
}

.title {
color: @text-color;
}

.percent {
text-align: right;
color: @text-color-secondary;
}

.value {
text-align: right;
}
}

&__content {
position: absolute;
display: flex;
Expand Down
117 changes: 116 additions & 1 deletion src/pie/pie-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,23 @@ import FitText from 'rc-fit-text';
import { TPadding } from '@/global';
import './pie-chart.less';

let chartInstance: G2.Chart = null;
let requestRef = null;
const prefixCls = 'rc-pie-chart';

export interface IDataItem {
x: string;
y: number;
}

interface ILegendDataItem {
x: string;
y: string;
checked: boolean;
color: string;
percent: number;
}

export interface IPieProps {
className?: string;
style?: React.CSSProperties;
Expand All @@ -46,6 +56,9 @@ export interface IPieProps {
showLabel?: boolean;
// 标注文本
label?: LabelProps;
// 详细图例显示开关
hasLegend?: boolean;
valueFormat?: (value: string) => string | React.ReactNode;
titleMap?: {
[key: string]: any;
};
Expand Down Expand Up @@ -85,6 +98,7 @@ const defaultScale = {
};

const PieChart: React.FC<IPieProps> = (props) => {
const rootRef = React.useRef(null);
const {
className,
style,
Expand All @@ -98,6 +112,8 @@ const PieChart: React.FC<IPieProps> = (props) => {
colors,
title,
subTitle,
hasLegend,
valueFormat,
label,
showLabel,
total,
Expand All @@ -108,8 +124,77 @@ const PieChart: React.FC<IPieProps> = (props) => {
onGetG2Instance
} = props;
const [innerWidth, setInnerWidth] = React.useState<number>(0);
const [legendBlock, setLegendBlock] = React.useState<boolean>(false);
const [legendData, setLegendData] = React.useState<ILegendDataItem[]>([]);

React.useEffect(() => {
window.addEventListener('resize', () => {
requestRef = requestAnimationFrame(() => resize());
}, { passive: true })
}, []);

React.useEffect(() => {
getLegendData();
}, [props.data]);

// 用于自定义图例
const getLegendData = () => {
if (!chartInstance) return;
const geom = chartInstance.getAllGeoms()[0];
if (!geom) return;
// @ts-ignore
const items = geom.get('dataArray') || [];

const data = items.map((item: { color: any; _origin: any }[]) => {
const origin = item[0]._origin;
origin.color = item[0].color;
origin.checked = true;
return origin;
});

setLegendData(data);
};

const handleLegendClick = (item: any, i: string | number) => {
const newItem = item;
newItem.checked = !newItem.checked;
const newLegendData = [...legendData];
newLegendData[i] = newItem;

const filteredLegendData = newLegendData.filter(l => l.checked).map(l => l.x);

if (chartInstance) {
chartInstance.filter('x', val => filteredLegendData.indexOf(val + '') > -1);
}

setLegendData(newLegendData);
};

const resize = () => {
const root: HTMLDivElement = rootRef.current;

if (!hasLegend || !root) {
window.removeEventListener('resize', resize);
return;
}

if (
root &&
root.parentNode &&
(root.parentNode as HTMLElement).clientWidth <= 380
) {
if (!legendBlock) {
setLegendBlock(true);
}
} else {
setLegendBlock(false);
}
};



const handleGetG2Instance = (chart: G2.Chart) => {
chartInstance = chart;
setInnerWidth(chart.get('height') * innerRadius);
onGetG2Instance && onGetG2Instance(chart);
};
Expand Down Expand Up @@ -166,8 +251,11 @@ const PieChart: React.FC<IPieProps> = (props) => {
return (
<div
className={classNames(className, {
[`${prefixCls}`]: true
[`${prefixCls}`]: true,
[`show-legend`]: !!hasLegend,
['legend-block']: legendBlock
})}
ref={rootRef}
style={style}
>
<div className={`${prefixCls}__chart`}>
Expand Down Expand Up @@ -234,6 +322,32 @@ const PieChart: React.FC<IPieProps> = (props) => {
</div>
</FitText>
</div>

{hasLegend && (
<ul className={`${prefixCls}__legend`}>
{legendData.map((item, i) => (
<li key={item.x} onClick={() => handleLegendClick(item, i)}>
<div className="title">
<span
className="dot"
style={{
backgroundColor: !item.checked ? '#aaa' : item.color,
}}
/>
<span>{item.x}</span>
</div>
<div className="value">
<span className="value">{valueFormat ? valueFormat(item.y) : item.y}</span>
</div>
<div className="percent">
<span className="percent">
{`${(Number.isNaN(item.percent) ? 0 : item.percent * 100).toFixed(2)}%`}
</span>
</div>
</li>
))}
</ul>
)}
</div>
)
};
Expand All @@ -242,6 +356,7 @@ PieChart.defaultProps = {
type: 'theta',
animate: true,
forceFit: true,
hasLegend: false,
showLabel: false,
height: 400,
radius: 1,
Expand Down

0 comments on commit ae20b28

Please sign in to comment.