add vc-progress

pull/9/head
wangxueliang 2018-04-03 11:00:05 +08:00
parent ab1ff471c1
commit 045f95201d
12 changed files with 414 additions and 3 deletions

View File

View File

@ -0,0 +1,42 @@
import { Line, Circle } from '../index'
import '../assets/index.less'
export default {
data () {
return {
percent: 0,
}
},
mounted () {
this.$nextTick(() => {
this.increase()
})
},
methods: {
increase () {
const percent = this.percent + 1
if (percent >= 100) {
clearTimeout(this.tm)
return
}
this.percent = percent
this.tm = setTimeout(this.increase, 10)
},
restart () {
clearTimeout(this.tm)
this.percent = 0
this.$nextTick(() => {
this.increase()
})
},
},
render () {
return (
<div style='margin: 10px;width: 200px'>
<Circle strokeWidth='6' percent={this.percent} />
<Line strokeWidth='4' percent={this.percent} />
<button onClick={this.restart}>Restart</button>
</div>
)
},
}

View File

@ -0,0 +1,72 @@
import { Circle } from '../index'
import '../assets/index.less'
export default {
data () {
return {
percent: 30,
color: '#3FC7FA',
}
},
methods: {
changeState () {
const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A']
const value = parseInt(Math.random() * 100, 10)
this.percent = value
this.color = colorMap[parseInt(Math.random() * 3, 10)]
},
},
render () {
const circleContainerStyle = {
width: '200px',
height: '200px',
}
return (
<div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='top'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='bottom'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='left'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
gapDegree='70'
gapPosition='right'
strokeWidth='6'
strokeLinecap='square'
strokeColor={this.color}
/>
</div>
<p>
<button onClick={this.changeState}>Change State</button>
</p>
</div>
)
},
}

View File

@ -0,0 +1,49 @@
import { Line, Circle } from '../index'
import '../assets/index.less'
export default {
data () {
return {
percent: 30,
color: '#3FC7FA',
}
},
methods: {
changeState () {
const colorMap = ['#3FC7FA', '#85D262', '#FE8C6A']
const value = parseInt(Math.random() * 100, 10)
this.percent = value
this.color = colorMap[parseInt(Math.random() * 3, 10)]
},
},
render () {
const containerStyle = {
width: '250px',
}
const circleContainerStyle = {
width: '250px',
height: '250px',
display: 'inline-block',
}
return (
<div>
<h3>Line Progress {this.percent}%</h3>
<div style={containerStyle}>
<Line percent={this.percent} strokeWidth='4' strokeColor={this.color} />
</div>
<h3>Circle Progress {this.percent}%</h3>
<div style={circleContainerStyle}>
<Circle
percent={this.percent}
strokeWidth='6'
strokeLinecap='round'
strokeColor={this.color}
/>
</div>
<p>
<button onClick={this.changeState}>Change State</button>
</p>
</div>
)
},
}

View File

@ -0,0 +1,8 @@
import Progress, { Line, Circle } from './src/';
export {
Line,
Circle,
};
export default Progress;

View File

@ -0,0 +1,111 @@
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.number,
}
const circleDefaultProps = {
...defaultProps,
gapPosition: 'top',
}
const Circle = {
props: initDefaultProps(circlePropTypes, circleDefaultProps),
methods: {
getPathStyles () {
const { percent, strokeWidth, gapDegree = 0, gapPosition } = this.$props
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 trailPathStyle = {
strokeDasharray: `${len - gapDegree}px ${len}px`,
strokeDashoffset: `-${gapDegree / 2}px`,
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s',
}
const strokePathStyle = {
strokeDasharray: `${(percent / 100) * (len - gapDegree)}px ${len}px`,
strokeDashoffset: `-${gapDegree / 2}px`,
transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s', // eslint-disable-line
}
return { pathString, trailPathStyle, strokePathStyle }
},
},
render () {
const {
prefixCls, strokeWidth, trailWidth, strokeColor,
trailColor, strokeLinecap, percent, ...restProps
} = this.$props
const { pathString, trailPathStyle, strokePathStyle } = this.getPathStyles()
delete restProps.percent
delete restProps.gapDegree
delete restProps.gapPosition
const pathFirst = {
attrs: {
'd': pathString,
'stroke': trailColor,
'stroke-width': trailWidth || strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-circle-trail`,
style: trailPathStyle,
}
const pathSecond = {
attrs: {
'd': pathString,
'stroke-linecap': strokeLinecap,
'stroke': strokeColor,
'stroke-width': percent === 0 ? 0 : strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-circle-path`,
style: strokePathStyle,
ref: 'svgPathRef',
}
return (
<svg
class={`${prefixCls}-circle`}
viewBox='0 0 100 100'
{...restProps}
>
<path
{...pathFirst}
/>
<path
{...pathSecond}
/>
</svg>
)
},
}
export default enhancer(Circle)

View File

@ -0,0 +1,73 @@
import { initDefaultProps } from '../../_util/props-util'
import enhancer from './enhancer'
import { propTypes, defaultProps } from './types'
const Line = {
props: initDefaultProps(propTypes, defaultProps),
render () {
const {
percent,
prefixCls,
strokeColor,
strokeLinecap,
strokeWidth,
trailColor,
trailWidth,
...restProps
} = this.$props
delete restProps.gapPosition
const pathStyle = {
strokeDasharray: '100px, 100px',
strokeDashoffset: `${(100 - percent)}px`,
transition: 'stroke-dashoffset 0.3s ease 0s, stroke 0.3s linear',
}
const center = strokeWidth / 2
const right = 100 - (strokeWidth / 2)
const pathString =
`M ${strokeLinecap === 'round' ? center : 0},${center}
L ${strokeLinecap === 'round' ? right : 100},${center}`
const viewBoxString = `0 0 100 ${strokeWidth}`
const pathFirst = {
attrs: {
'd': pathString,
'stroke-linecap': strokeLinecap,
'stroke': trailColor,
'stroke-width': trailWidth || strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-line-trail`,
}
const pathSecond = {
attrs: {
'd': pathString,
'stroke-linecap': strokeLinecap,
'stroke': strokeColor,
'stroke-width': strokeWidth,
'fill-opacity': '0',
},
class: `${prefixCls}-line-path`,
style: pathStyle,
ref: 'svgPathRef',
}
return (
<svg
class={`${prefixCls}-line`}
viewBox={viewBoxString}
preserveAspectRatio='none'
{...restProps}
>
<path
{...pathFirst}
/>
<path
{...pathSecond}
/>
</svg>
)
},
}
export default enhancer(Line)

View File

@ -0,0 +1,21 @@
function enhancer (Component) {
return {
mixins: [Component],
updated () {
this.$nextTick(() => {
if (!this.$refs.svgPathRef) {
return
}
const pathStyle = this.$refs.svgPathRef.style
pathStyle.transitionDuration = '.3s, .3s, .3s, .06s'
const now = Date.now()
if (this.prevTimeStamp && now - this.prevTimeStamp < 100) {
pathStyle.transitionDuration = '0s, 0s'
}
this.prevTimeStamp = Date.now()
})
},
}
}
export default enhancer

View File

@ -0,0 +1,12 @@
import Line from './Line'
import Circle from './Circle'
export {
Line,
Circle,
}
export default {
Line,
Circle,
}

View File

@ -0,0 +1,25 @@
import PropTypes from '../../_util/vue-types'
export const defaultProps = {
// className: '',
percent: 0,
prefixCls: 'rc-progress',
strokeColor: '#2db7f5',
strokeLinecap: 'round',
strokeWidth: 1,
// style: {},
trailColor: '#D9D9D9',
trailWidth: 1,
}
export const propTypes = {
// className: PropTypes.string,
percent: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
prefixCls: PropTypes.string,
strokeColor: PropTypes.string,
strokeLinecap: PropTypes.oneOf(['butt', 'round', 'square']),
strokeWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
// style: PropTypes.object,
trailColor: PropTypes.string,
trailWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
}

View File

@ -13,7 +13,6 @@ function noop () {}
export default function createSlider (Component) {
// const displayName = `ComponentEnhancer(${Component.displayName})`
const propTypes = {
...Component.propTypes,
min: PropTypes.number,
max: PropTypes.number,
step: PropTypes.number,
@ -41,7 +40,6 @@ export default function createSlider (Component) {
event: 'change',
},
props: initDefaultProps(propTypes, {
...Component.defaultProps,
prefixCls: 'rc-slider',
min: 0,
max: 100,

View File

@ -3,7 +3,7 @@ const AsyncComp = () => {
const hashs = window.location.hash.split('/')
const d = hashs[hashs.length - 1]
return {
component: import(`../components/table/demo/${d}`),
component: import(`../components/vc-progress/demo/${d}`),
}
}
export default [