ant-design-vue/components/vc-progress/src/Circle.js

163 lines
4.3 KiB
JavaScript

import Vue from 'vue';
import ref from 'vue-ref';
import PropTypes from '../../_util/vue-types';
import { initDefaultProps } from '../../_util/props-util';
import enhancer from './enhancer';
import { propTypes, defaultProps } from './types';
const circlePropTypes = {
...propTypes,
gapPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
gapDegree: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
};
const circleDefaultProps = {
...defaultProps,
gapPosition: 'top',
};
Vue.use(ref, { name: 'ant-ref' });
const Circle = {
props: initDefaultProps(circlePropTypes, circleDefaultProps),
data() {
this.paths = {};
return {};
},
methods: {
getPathStyles(offset, percent, strokeColor, strokeWidth, gapDegree = 0, gapPosition) {
const radius = 50 - strokeWidth / 2;
let beginPositionX = 0;
let beginPositionY = -radius;
let endPositionX = 0;
let endPositionY = -2 * radius;
switch (gapPosition) {
case 'left':
beginPositionX = -radius;
beginPositionY = 0;
endPositionX = 2 * radius;
endPositionY = 0;
break;
case 'right':
beginPositionX = radius;
beginPositionY = 0;
endPositionX = -2 * radius;
endPositionY = 0;
break;
case 'bottom':
beginPositionY = radius;
endPositionY = 2 * radius;
break;
default:
}
const pathString = `M 50,50 m ${beginPositionX},${beginPositionY}
a ${radius},${radius} 0 1 1 ${endPositionX},${-endPositionY}
a ${radius},${radius} 0 1 1 ${-endPositionX},${endPositionY}`;
const len = Math.PI * 2 * radius;
const pathStyle = {
stroke: strokeColor,
strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`,
strokeDashoffset: `-${gapDegree / 2 + (offset / 100) * (len - gapDegree)}px`,
transition:
'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s', // eslint-disable-line
};
return {
pathString,
pathStyle,
};
},
getStokeList() {
const {
prefixCls,
percent,
strokeColor,
strokeWidth,
strokeLinecap,
gapDegree,
gapPosition,
} = this.$props;
const percentList = Array.isArray(percent) ? percent : [percent];
const strokeColorList = Array.isArray(strokeColor) ? strokeColor : [strokeColor];
let stackPtg = 0;
return percentList.map((ptg, index) => {
const color = strokeColorList[index] || strokeColorList[strokeColorList.length - 1];
const { pathString, pathStyle } = this.getPathStyles(
stackPtg,
ptg,
color,
strokeWidth,
gapDegree,
gapPosition,
);
stackPtg += ptg;
const pathProps = {
key: index,
attrs: {
d: pathString,
'stroke-linecap': strokeLinecap,
'stroke-width': ptg === 0 ? 0 : strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-circle-path`,
style: pathStyle,
directives: [
{
name: 'ant-ref',
value: c => {
this.paths[index] = c;
},
},
],
};
return <path {...pathProps} />;
});
},
},
render() {
const {
prefixCls,
strokeWidth,
trailWidth,
gapDegree,
gapPosition,
trailColor,
strokeLinecap,
...restProps
} = this.$props;
const { pathString, pathStyle } = this.getPathStyles(
0,
100,
trailColor,
strokeWidth,
gapDegree,
gapPosition,
);
delete restProps.percent;
delete restProps.strokeColor;
const pathFirst = {
attrs: {
d: pathString,
stroke: trailColor,
'stroke-linecap': strokeLinecap,
'stroke-width': trailWidth || strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-circle-trail`,
style: pathStyle,
};
return (
<svg class={`${prefixCls}-circle`} viewBox="0 0 100 100" {...restProps}>
<path {...pathFirst} />
{this.getStokeList()}
</svg>
);
},
};
export default enhancer(Circle);