in src/Wcapacity/percentBar/index.tsx [25:191]
function PercentBar(props: IProps) {
const { data, config, prefix } = props;
const ref = useRef(null);
const [width, setWidth] = useState(0);
const [offsetX, setOffsetX] = useState(0);
const unityAnimation = (waterWidth: number) => {
const currentX = ref?.current?.getBoundingClientRect()?.left ?? 0;
const capcityList = document.getElementsByClassName(`${prefix}-percent-container`);
let minX = 9999999;
for (let i = 0; i < capcityList?.length; i++) {
const x_position = capcityList[i].getBoundingClientRect().left;
minX = Math.min(minX, x_position);
};
// 计算距离
const distance = Math.ceil(currentX) === Math.ceil(minX) ? 0 : currentX - minX - waterWidth;
// 计算偏移,减去最左侧的水位
const offsetX = distance - Math.floor(distance / waterWidth) * waterWidth;
setOffsetX(offsetX);
};
useEffect(() => {
let timer: any;
const handleResize = () => {
clearTimeout(timer);
timer = setTimeout(() => {
if (!ref.current) return;
const waterWidth = ref?.current?.clientWidth ?? 0;
setWidth(waterWidth);
if (!config.closeUniAnimation || (!themes['widgets-global-uni-animation'] && themes['widgets-global-uni-animation'] !== 'true')) {
unityAnimation(waterWidth);
}
}, 0);
};
handleResize();
const parent = ref.current && ref.current.parentElement;
if (parent) {
GlobalResizeObserver.observe(parent, handleResize);
}
return () => {
clearTimeout(timer);
const parent = ref.current && ref.current.parentElement;
if (parent) {
GlobalResizeObserver.unobserve(parent);
}
};
}, [ref]);
// 默认态是图表主色
const statusColors: any = {
normal: themes['widgets-capacity-color-grey'], // 平常态是灰色
success: themes['widgets-color-green'],
warning: themes['widgets-color-orange'],
error: themes['widgets-color-red'],
};
const translateStartColor = (data: any, config: any) => {
if (data.percent.displayNumber === 0 || data.percent.displayNumber === '-' || !data.percent.displayNumber) {
return {
status: 'empty',
color: themes['widgets-tooltip-cross-line'],
};
} else if (config?.guide) {
const threshold = Number((config?.guide?.threshold ?? '80%')?.replace('%', ''));
if (data.percent.displayNumber >= threshold) {
return {
status: config?.guide?.status ?? 'error',
color: statusColors[config?.guide?.status ?? 'error'],
};
} else {
return {
status: Object.keys(statusColors)?.includes(config?.startColor) ? config?.startColor : 'normal',
color: statusColors[config?.startColor] || config?.startColor || themes['widgets-color-normal'],
};
}
} else {
return {
status: Object.keys(statusColors)?.includes(config?.startColor) ? config?.startColor : 'normal',
color: statusColors[config?.startColor] || config?.startColor || themes['widgets-color-normal'],
};
}
};
return (
<div
className={`${prefix}-percent-container`}
style={{
width: config?.barSize || '100%',
...config?.percentConfig,
}}
ref={ref}
>
<div className={`${prefix}-bar-container ${translateStartColor(data, config)?.status}`} style={config?.barConfig}>
{config?.guide && (
<div
className={`${prefix}-bar-guide-line ${config?.guide?.status ?? 'error'}`}
style={{
height: config?.guide?.threshold ?? '80%',
borderTopColor: statusColors[config?.guide?.status ?? 'error'],
}}
>
<Wnumber
className={`${prefix}-bar-guide-text ${config?.guide?.status ?? 'error'}`}
style={{
color: statusColors[config?.guide?.status ?? 'error'],
}}
>
{config?.guide?.threshold ?? '-'}
</Wnumber>
</div>
)}
<div
className={`${prefix}-process-bar`}
style={{
width: config?.barSize || config?.percentConfig?.width || '100%',
height:
data.percent.displayNumber === 0 || data.percent.displayNumber === '-'
? '15px'
: `calc(${data.percent.displayNumber}% + 15px)`,
...config?.processBarConfig,
}}
>
<div
className={`${prefix}-process-back`}
style={{
background: `linear-gradient(180deg, transparent 19px, ${translateStartColor(data, config).color} 0%, ${
config?.endColor || tinycolor(translateStartColor(data, config).color).setAlpha(0.1).toRgbString()
} 100%)`,
...config?.processBarBackConfig,
transform: `translate3d(${-offsetX}px,0,0) scale(1, 1) perspective(1px)`,
}}
>
<svg className="process-svg" width="100%" height={20} version="1.1" xmlns="http://www.w3.org/2000/svg">
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
<path
d={getClipPath(width * 2, 20)}
fill={translateStartColor(data, config).color}
opacity="0.5"
transform={`translate(${-0.5 * width},0)`}
/>
<path d={getClipPath(width * 2, 20)} fill={translateStartColor(data, config).color} />
</g>
</svg>
</div>
</div>
<Wnumber
className={`${prefix}-percent-bar-label-content ${config?.size || 'medium'}`}
style={config?.labelConfig}
>
{data.percent.displayNumber}
<span className={`${prefix}-percent-bar-label-unit`}>{config?.labelConfig?.unit || '%'}</span>
</Wnumber>
<div className={`${prefix}-percent-bar-label-title`} style={config?.titleConfig}>
{data.percent.name}
</div>
</div>
</div>
);
}