128 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Vue
		
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Vue
		
	
	
| <script>
 | |
| import BaseMixin from '../_util/BaseMixin'
 | |
| 
 | |
| function getNumberArray (num) {
 | |
|   return num
 | |
|     ? num.toString()
 | |
|       .split('')
 | |
|       .reverse()
 | |
|       .map(i => Number(i)) : []
 | |
| }
 | |
| export default {
 | |
|   name: 'ScrollNumber',
 | |
|   props: {
 | |
|     className: Object,
 | |
|     prefixCls: String,
 | |
|     count: [Number, String],
 | |
|     titleNumber: [Number, String],
 | |
|     styleNumber: {
 | |
|       type: Object,
 | |
|       default: () => ({}),
 | |
|     },
 | |
|   },
 | |
|   mixins: [BaseMixin],
 | |
|   data () {
 | |
|     const { count } = this
 | |
|     return {
 | |
|       animateStarted: true,
 | |
|       lastCount: 0,
 | |
|       stateCount: count,
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     count (newValue, oldValue) {
 | |
|       // 复原数字初始位置
 | |
|       this.setState({
 | |
|         animateStarted: true,
 | |
|         lastCount: oldValue,
 | |
|       }, () => {
 | |
|         // 等待数字位置复原完毕
 | |
|         // 开始设置完整的数字
 | |
|         setTimeout(() => {
 | |
|           this.setState({
 | |
|             animateStarted: false,
 | |
|             stateCount: newValue,
 | |
|           })
 | |
|         }, 30)
 | |
|       })
 | |
|     },
 | |
|   },
 | |
|   methods: {
 | |
|     getPositionByNum (num, i) {
 | |
|       const { animateStarted, lastCount, stateCount } = this
 | |
|       if (animateStarted) {
 | |
|         return 10 + num
 | |
|       }
 | |
|       const currentDigit = getNumberArray(stateCount)[i]
 | |
|       const lastDigit = getNumberArray(lastCount)[i]
 | |
|       // 同方向则在同一侧切换数字
 | |
|       if (stateCount > lastCount) {
 | |
|         if (currentDigit >= lastDigit) {
 | |
|           return 10 + num
 | |
|         }
 | |
|         return 20 + num
 | |
|       }
 | |
|       if (currentDigit <= lastDigit) {
 | |
|         return 10 + num
 | |
|       }
 | |
|       return num
 | |
|     },
 | |
|     renderNumberList (position) {
 | |
|       const childrenArr = new Array(30).fill(1)
 | |
|       const childrenHtml = childrenArr.map((item, i) => {
 | |
|         const currentClassName = (position === i) ? 'current' : ''
 | |
|         return <p key={i.toString()} class={currentClassName}>{i % 10}</p>
 | |
|       })
 | |
|       return childrenHtml
 | |
|     },
 | |
|     renderCurrentNumber (num, i) {
 | |
|       const { animateStarted, prefixCls } = this
 | |
|       const position = this.getPositionByNum(num, i)
 | |
|       let removeTransition = animateStarted ||
 | |
|         (getNumberArray(this.lastCount)[i] === undefined)
 | |
|       if (!removeTransition) {
 | |
|         removeTransition = ''
 | |
|       }
 | |
|       const styleSpan = {
 | |
|         transition: `${removeTransition}` && 'none',
 | |
|         msTransform: `translateY(${-position * 100}%)`,
 | |
|         WebkitTransform: `translateY(${-position * 100}%)`,
 | |
|         transform: `translateY(${-position * 100}%)`,
 | |
|       }
 | |
|       return (
 | |
|         <span
 | |
|           key={i}
 | |
|           class={`${prefixCls}-only`}
 | |
|           style = {styleSpan}
 | |
|         >
 | |
|           {
 | |
|             this.renderNumberList(position)
 | |
|           }
 | |
|         </span>
 | |
|       )
 | |
|     },
 | |
|     renderNumberElement () {
 | |
|       const { stateCount } = this
 | |
|       if (!stateCount || isNaN(Number(stateCount))) {
 | |
|         return stateCount
 | |
|       }
 | |
|       return getNumberArray(stateCount)
 | |
|         .map((num, i) => this.renderCurrentNumber(num, i)).reverse()
 | |
|     },
 | |
|   },
 | |
|   render () {
 | |
|     const { prefixCls, className, titleNumber, styleNumber } = this
 | |
|     return (
 | |
|       <sup
 | |
|         class={[prefixCls, className]}
 | |
|         title={titleNumber}
 | |
|         style={styleNumber}>
 | |
|         {
 | |
|           this.renderNumberElement()
 | |
|         }
 | |
|       </sup>
 | |
|     )
 | |
|   },
 | |
| }
 | |
| </script>
 |