feat(slider): add new slider component
This commit is contained in:
		
							parent
							
								
									3bfe6684d6
								
							
						
					
					
						commit
						3ad8a6a329
					
				|  | @ -218,6 +218,11 @@ input-item-placeholder = color-text-placeholder | ||||||
| input-item-placeholder-highlight = color-primary | input-item-placeholder-highlight = color-primary | ||||||
| input-item-icon = color-text-placeholder // delete icon | input-item-icon = color-text-placeholder // delete icon | ||||||
| 
 | 
 | ||||||
|  | // slider | ||||||
|  | slider-bg-base = color-bg-base | ||||||
|  | slider-bg-tap = color-primary | ||||||
|  | slider-handle-bg = color-bg-inverse | ||||||
|  | 
 | ||||||
| // landscape | // landscape | ||||||
| landscape-width = 540px | landscape-width = 540px | ||||||
| landscape-radius = radius-normal | landscape-radius = radius-normal | ||||||
|  |  | ||||||
|  | @ -57,6 +57,7 @@ import WaterMark from './water-mark' | ||||||
| import Transition from './transition' | import Transition from './transition' | ||||||
| import DetailItem from './detail-item' | import DetailItem from './detail-item' | ||||||
| import Overlay from './overlay' | import Overlay from './overlay' | ||||||
|  | import Slider from './slider' | ||||||
| /* @init<%import ${componentNameUpper} from './${componentName}'%> */ | /* @init<%import ${componentNameUpper} from './${componentName}'%> */ | ||||||
| 
 | 
 | ||||||
| // 全量引入提醒
 | // 全量引入提醒
 | ||||||
|  | @ -124,6 +125,7 @@ export const components = { | ||||||
|   Transition, |   Transition, | ||||||
|   DetailItem, |   DetailItem, | ||||||
|   Overlay, |   Overlay, | ||||||
|  |   Slider, | ||||||
|   /* @init<%${componentNameUpper},%> */ |   /* @init<%${componentNameUpper},%> */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -208,6 +210,7 @@ export { | ||||||
|   Transition, |   Transition, | ||||||
|   DetailItem, |   DetailItem, | ||||||
|   Overlay, |   Overlay, | ||||||
|  |   Slider, | ||||||
|   /* @init<%${componentNameUpper},%> */ |   /* @init<%${componentNameUpper},%> */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | --- | ||||||
|  | title: Slider | ||||||
|  | preview: https://didi.github.io/mand-mobile/examples/#/slider | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | ### Import | ||||||
|  | 
 | ||||||
|  | ```javascript | ||||||
|  | import { Slider } from 'mand-mobile' | ||||||
|  | 
 | ||||||
|  | Vue.component(Slider.name, Slider) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### Code Examples | ||||||
|  | <!-- DEMO --> | ||||||
|  | 
 | ||||||
|  | ### API | ||||||
|  | 
 | ||||||
|  | #### Slider Props | ||||||
|  | |Props | Description | Type | Default | Note| | ||||||
|  | |----|-----|------|------|------| | ||||||
|  | |v-model|the value of slider, when <code>range</code> is false, use <code>number</code>, otherwise, use <code>[number, number]</code>|number | number[]|`0`|-| | ||||||
|  | |disabled|whether to disable slider|Boolean|`false`|-| | ||||||
|  | |min|the minimum value the slider can slide from|number|`0`|-| | ||||||
|  | |max|the maximum value the slider can slide to|number|`100`|-| | ||||||
|  | |step|the granularity the slider can step through|number|`1`|-| | ||||||
|  | |range|dual thumb mode|Boolean|`false`|-| | ||||||
|  | |format|slider will pass its value to <code>format</code>, and display its value in tooltip|Function|`(val) => {return val}`|-| | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | --- | ||||||
|  | title: Slider 滑块 | ||||||
|  | preview: https://didi.github.io/mand-mobile/examples/#/slider | ||||||
|  | --- | ||||||
|  | 
 | ||||||
|  | ### 引入 | ||||||
|  | 
 | ||||||
|  | ```javascript | ||||||
|  | import { Slider } from '@didi/mand-mobile' | ||||||
|  | 
 | ||||||
|  | Vue.component(Slider.name, Slider) | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### 代码演示 | ||||||
|  | <!-- DEMO --> | ||||||
|  | 
 | ||||||
|  | ### API | ||||||
|  | 
 | ||||||
|  | #### Slider Props | ||||||
|  | |属性 | 说明 | 类型 | 默认值 | 备注| | ||||||
|  | |----|-----|------|------|------| | ||||||
|  | |v-model|双向绑定的值, 当开启<code>range</code>时, 其值为数组形式</code>|number | number[]|`0`|-| | ||||||
|  | |disabled|是否禁用滑块|Boolean|`false`|-| | ||||||
|  | |min|可拖动的最小值|number|`0`|-| | ||||||
|  | |max|可拖动的最大值|number|`100`|-| | ||||||
|  | |step|步长|number|`1`|-| | ||||||
|  | |range|是否启动双向拖动|Boolean|`false`|-| | ||||||
|  | |format|显示文本的格式化函数|Function|`(val) => {return val}`|-| | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | export default { | ||||||
|  |   'name': 'slider', | ||||||
|  |   'text': '滑块', | ||||||
|  |   'category': 'form', | ||||||
|  |   'description': '', | ||||||
|  |   'author': 'moyu <moyuboy@gmail.com>' | ||||||
|  | } | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-example-child md-example-child-slider"> | ||||||
|  |     <md-slider v-model="quantity"></md-slider> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
import {Slider} from 'mand-mobile' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   name: 'slider-demo', | ||||||
|  |   /* DELETE */ | ||||||
|  |   title: '基本', | ||||||
|  |   titleEnUS: 'Basic', | ||||||
|  |   /* DELETE */ | ||||||
|  |   components: { | ||||||
|  |     [Slider.name]: Slider, | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       quantity: 25, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-example-child md-example-child-slider"> | ||||||
|  |     <md-slider v-model="quantity" disabled></md-slider> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
import {Slider} from 'mand-mobile' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   name: 'slider-demo', | ||||||
|  |   /* DELETE */ | ||||||
|  |   title: '禁用', | ||||||
|  |   titleEnUS: 'Disabled', | ||||||
|  |   /* DELETE */ | ||||||
|  |   components: { | ||||||
|  |     [Slider.name]: Slider, | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       quantity: 50, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,32 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-example-child md-example-child-slider"> | ||||||
|  |     <md-slider v-model="quantity" :format="format"></md-slider> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
import {Slider} from 'mand-mobile' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   name: 'slider-demo', | ||||||
|  |   /* DELETE */ | ||||||
|  |   title: '格式化', | ||||||
|  |   titleEnUS: 'Format', | ||||||
|  |   /* DELETE */ | ||||||
|  |   components: { | ||||||
|  |     [Slider.name]: Slider, | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       quantity: 50, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   methods: { | ||||||
|  |     format(val) { | ||||||
|  |       return '¥' + val | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-example-child md-example-child-slider"> | ||||||
|  |     <md-slider v-model="range" range></md-slider> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
import {Slider} from 'mand-mobile' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   name: 'slider-demo', | ||||||
|  |   /* DELETE */ | ||||||
|  |   title: '范围', | ||||||
|  |   titleEnUS: 'Range', | ||||||
|  |   /* DELETE */ | ||||||
|  |   components: { | ||||||
|  |     [Slider.name]: Slider, | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       range: [25, 50], | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-example-child md-example-child-slider"> | ||||||
|  |     <md-slider v-model="bucket" :step="10"></md-slider> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
import {Slider} from 'mand-mobile' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   name: 'slider-demo', | ||||||
|  |   /* DELETE */ | ||||||
|  |   title: '步长', | ||||||
|  |   titleEnUS: 'Steps', | ||||||
|  |   /* DELETE */ | ||||||
|  |   components: { | ||||||
|  |     [Slider.name]: Slider, | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       bucket: 10, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-example-child md-example-child-slider"> | ||||||
|  |     <md-slider v-model="range" :min="15" :max="80" range></md-slider> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
import {Slider} from 'mand-mobile' | ||||||
|  | 
 | ||||||
|  | export default { | ||||||
|  |   name: 'slider-demo', | ||||||
|  |   /* DELETE */ | ||||||
|  |   title: '边界值', | ||||||
|  |   titleEnUS: 'Min & Max', | ||||||
|  |   /* DELETE */ | ||||||
|  |   components: { | ||||||
|  |     [Slider.name]: Slider, | ||||||
|  |   }, | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       range: [25, 50], | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-example slider"> | ||||||
|  |     <section class="md-example-section" v-for="(demo, index) in demos" :key="index"> | ||||||
|  |       <div class="md-example-title" v-html="demo.title"></div> | ||||||
|  |       <div class="md-example-describe" v-html="demo.describe"></div> | ||||||
|  |       <div class="md-example-content"> | ||||||
|  |         <component :is="demo"></component> | ||||||
|  |       </div> | ||||||
|  |     </section> | ||||||
|  | 	</div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
import createDemoModule from '../../../examples/create-demo-module' | ||||||
|  | import Demo0 from './cases/demo0' | ||||||
|  | import Demo1 from './cases/demo1' | ||||||
|  | import Demo2 from './cases/demo2' | ||||||
|  | import Demo3 from './cases/demo3' | ||||||
|  | import Demo4 from './cases/demo4' | ||||||
|  | import Demo5 from './cases/demo5' | ||||||
|  | 
 | ||||||
|  | export default createDemoModule('slider', [Demo0, Demo1, Demo2, Demo3, Demo4, Demo5]) | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus"> | ||||||
|  | .md-example.slider | ||||||
|  |   position relative | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,324 @@ | ||||||
|  | <template> | ||||||
|  |   <div class="md-slider" :class="{'is-disabled': disabled}"> | ||||||
|  |     <template v-if="range"> | ||||||
|  |       <div class="md-slider-bar" :style="barStyle"></div> | ||||||
|  |       <div class="md-slider-handle is-lower" | ||||||
|  |         :data-hint="format(values[0])" | ||||||
|  |         :class="{ | ||||||
|  |           'is-active': isDragging && !isDragingUpper | ||||||
|  |         }" | ||||||
|  |         :style="{'left': lowerHandlePosition + '%'}"> | ||||||
|  |         <span | ||||||
|  |           @mousedown="$_startLowerDrag" | ||||||
|  |           @touchstart="$_startLowerDrag" | ||||||
|  |         ></span> | ||||||
|  |       </div> | ||||||
|  |       <div class="md-slider-handle is-higher" | ||||||
|  |         :data-hint="format(values[1])" | ||||||
|  |         :class="{ | ||||||
|  |           'is-active': isDragging && isDragingUpper | ||||||
|  |         }" | ||||||
|  |         :style="{'left': upperHandlePosition + '%'}"> | ||||||
|  |         <span | ||||||
|  |           @mousedown="$_startUpperDrag" | ||||||
|  |           @touchstart="$_startUpperDrag" | ||||||
|  |         ></span> | ||||||
|  |       </div> | ||||||
|  |     </template> | ||||||
|  |     <template v-else> | ||||||
|  |       <div class="md-slider-bar" :style="barStyle"></div> | ||||||
|  |       <div class="md-slider-handle" | ||||||
|  |         :data-hint="format(values[0])" | ||||||
|  |         :class="{ | ||||||
|  |           'is-active': isDragging | ||||||
|  |         }" | ||||||
|  |         :style="{'left': lowerHandlePosition + '%'}"> | ||||||
|  |         <span | ||||||
|  |           @mousedown="$_startLowerDrag" | ||||||
|  |           @touchstart="$_startLowerDrag" | ||||||
|  |         ></span> | ||||||
|  |       </div> | ||||||
|  |     </template> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script>
export default { | ||||||
|  |   name: 'md-slider', | ||||||
|  | 
 | ||||||
|  |   props: { | ||||||
|  |     value: { | ||||||
|  |       type: [Array, Number], | ||||||
|  |       default: 0, | ||||||
|  |     }, | ||||||
|  |     min: { | ||||||
|  |       type: Number, | ||||||
|  |       default: 0, | ||||||
|  |     }, | ||||||
|  |     max: { | ||||||
|  |       type: Number, | ||||||
|  |       default: 100, | ||||||
|  |     }, | ||||||
|  |     step: { | ||||||
|  |       type: Number, | ||||||
|  |       default: 1, | ||||||
|  |     }, | ||||||
|  |     range: { | ||||||
|  |       type: Boolean, | ||||||
|  |       default: false, | ||||||
|  |     }, | ||||||
|  |     format: { | ||||||
|  |       type: Function, | ||||||
|  |       default(val) { | ||||||
|  |         return val | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     disabled: { | ||||||
|  |       type: Boolean, | ||||||
|  |       default: false, | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   data() { | ||||||
|  |     return { | ||||||
|  |       isDragging: false, | ||||||
|  |       isDragingUpper: false, | ||||||
|  |       values: [this.min, this.max], | ||||||
|  |       startDragMousePos: 0, | ||||||
|  |       startVal: 0, | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   watch: { | ||||||
|  |     value: { | ||||||
|  |       immediate: true, | ||||||
|  |       handler(val) { | ||||||
|  |         if ( | ||||||
|  |           (Array.isArray(val) && (val[0] !== this.values[0] || val[1] !== this.values[1])) || | ||||||
|  |           val !== this.values[0] | ||||||
|  |         ) { | ||||||
|  |           this.$_updateValue(val) | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     disabled(newVal) { | ||||||
|  |       if (!newVal) { | ||||||
|  |         this.$_stopDrag() | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   computed: { | ||||||
|  |     lowerHandlePosition() { | ||||||
|  |       return (this.values[0] - this.min) / (this.max - this.min) * 100 | ||||||
|  |     }, | ||||||
|  |     upperHandlePosition() { | ||||||
|  |       return (this.values[1] - this.min) / (this.max - this.min) * 100 | ||||||
|  |     }, | ||||||
|  |     barStyle() { | ||||||
|  |       if (this.range) { | ||||||
|  |         return { | ||||||
|  |           width: (this.values[1] - this.values[0]) / (this.max - this.min) * 100 + '%', | ||||||
|  |           left: this.lowerHandlePosition + '%', | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         return { | ||||||
|  |           width: this.values[0] / (this.max - this.min) * 100 + '%', | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   methods: { | ||||||
|  |     $_updateValue(newVal) { | ||||||
|  |       let newValues = [] | ||||||
|  | 
 | ||||||
|  |       if (Array.isArray(newVal)) { | ||||||
|  |         newValues = [newVal[0], newVal[1]] | ||||||
|  |       } else { | ||||||
|  |         newValues[0] = newVal | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (typeof newValues[0] !== 'number') { | ||||||
|  |         newValues[0] = this.values[0] | ||||||
|  |       } else { | ||||||
|  |         newValues[0] = Math.round((newValues[0] - this.min) / this.step) * this.step + this.min | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (typeof newValues[1] !== 'number') { | ||||||
|  |         newValues[1] = this.values[1] | ||||||
|  |       } else { | ||||||
|  |         newValues[1] = Math.round((newValues[1] - this.min) / this.step) * this.step + this.min | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // value boundary adjust | ||||||
|  |       if (newValues[0] < this.min) { | ||||||
|  |         newValues[0] = this.min | ||||||
|  |       } | ||||||
|  |       if (newValues[1] > this.max) { | ||||||
|  |         newValues[1] = this.max | ||||||
|  |       } | ||||||
|  |       if (newValues[0] > newValues[1]) { | ||||||
|  |         if (newValues[0] === this.values[0]) { | ||||||
|  |           newValues[1] = newValues[0] | ||||||
|  |         } else { | ||||||
|  |           newValues[0] = newValues[1] | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if (this.values[0] === newValues[0] && this.values[1] === newValues[1]) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       this.values = newValues | ||||||
|  | 
 | ||||||
|  |       if (this.range) { | ||||||
|  |         this.$emit('input', this.values) | ||||||
|  |       } else { | ||||||
|  |         this.$emit('input', this.values[0]) | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     $_startLowerDrag(e) { | ||||||
|  |       if (this.disabled) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |       e.preventDefault() | ||||||
|  |       e.stopPropagation() | ||||||
|  |       e = e.changedTouches ? e.changedTouches[0] : e | ||||||
|  |       this.startDragMousePos = e.pageX | ||||||
|  |       this.startVal = this.values[0] | ||||||
|  |       this.isDragingUpper = false | ||||||
|  |       this.isDragging = true | ||||||
|  |       window.addEventListener('mousemove', this.$_onDrag) | ||||||
|  |       window.addEventListener('touchmove', this.$_onDrag) | ||||||
|  |       window.addEventListener('mouseup', this.$_onUp) | ||||||
|  |       window.addEventListener('touchend', this.$_onUp) | ||||||
|  |     }, | ||||||
|  |     $_startUpperDrag(e) { | ||||||
|  |       if (this.disabled) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |       e.preventDefault() | ||||||
|  |       e.stopPropagation() | ||||||
|  |       e = e.changedTouches ? e.changedTouches[0] : e | ||||||
|  |       this.startDragMousePos = e.pageX | ||||||
|  |       this.startVal = this.values[1] | ||||||
|  |       this.isDragingUpper = true | ||||||
|  |       this.isDragging = true | ||||||
|  |       window.addEventListener('mousemove', this.$_onDrag) | ||||||
|  |       window.addEventListener('touchmove', this.$_onDrag) | ||||||
|  |       window.addEventListener('mouseup', this.$_onUp) | ||||||
|  |       window.addEventListener('touchend', this.$_onUp) | ||||||
|  |     }, | ||||||
|  |     $_onDrag(e) { | ||||||
|  |       if (this.disabled) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |       e.preventDefault() | ||||||
|  |       e.stopPropagation() | ||||||
|  |       if (!this.isDragging) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |       e = e.changedTouches ? e.changedTouches[0] : e | ||||||
|  |       window.requestAnimationFrame(() => { | ||||||
|  |         let diff = (e.pageX - this.startDragMousePos) / this.$el.offsetWidth * (this.max - this.min) | ||||||
|  |         let nextVal = this.startVal + diff | ||||||
|  |         if (this.isDragging) { | ||||||
|  |           if (this.isDragingUpper) { | ||||||
|  |             this.$_updateValue([null, nextVal]) | ||||||
|  |           } else { | ||||||
|  |             this.$_updateValue([nextVal, null]) | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|  |     }, | ||||||
|  |     $_onUp(e) { | ||||||
|  |       e.preventDefault() | ||||||
|  |       e.stopPropagation() | ||||||
|  |       this.$_stopDrag() | ||||||
|  |     }, | ||||||
|  |     $_stopDrag() { | ||||||
|  |       this.isDragging = false | ||||||
|  |       this.isDragingUpper = false | ||||||
|  |       window.removeEventListener('mousemove', this.$_onDrag) | ||||||
|  |       window.removeEventListener('touchmove', this.$_onDrag) | ||||||
|  |       window.removeEventListener('mouseup', this.$_onUp) | ||||||
|  |       window.removeEventListener('touchend', this.$_onUp) | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | } | ||||||
|  | 
</script> | ||||||
|  | 
 | ||||||
|  | <style lang="stylus"> | ||||||
|  | .md-slider | ||||||
|  |   position relative | ||||||
|  |   width 100% | ||||||
|  |   height 60px | ||||||
|  |   &::before | ||||||
|  |     content '' | ||||||
|  |     position absolute | ||||||
|  |     top 28px | ||||||
|  |     left 0 | ||||||
|  |     right 0 | ||||||
|  |     height 4px | ||||||
|  |     border-radius 2px | ||||||
|  |     background-color slider-bg-base | ||||||
|  |   &.is-disabled | ||||||
|  |     .md-slider-bar | ||||||
|  |       opacity 0.35 | ||||||
|  |     .md-slider-handle span | ||||||
|  |       cursor: not-allowed | ||||||
|  | 
 | ||||||
|  | .md-slider-bar | ||||||
|  |   position absolute | ||||||
|  |   left 0 | ||||||
|  |   top 28px | ||||||
|  |   height 4px | ||||||
|  |   background-color slider-bg-tap | ||||||
|  |   border-radius 2px | ||||||
|  |   z-index 5 | ||||||
|  | 
 | ||||||
|  | .md-slider-handle | ||||||
|  |   position absolute | ||||||
|  |   top 10px | ||||||
|  |   left 0 | ||||||
|  |   margin-left -20px | ||||||
|  |   z-index 15 | ||||||
|  |   overflow visible | ||||||
|  |   &::after | ||||||
|  |     content attr(data-hint) | ||||||
|  |     color tip-color | ||||||
|  |     position absolute | ||||||
|  |     pointer-events none | ||||||
|  |     opacity 0 | ||||||
|  |     visibility hidden | ||||||
|  |     z-index 15 | ||||||
|  |     font-size font-minor-normal | ||||||
|  |     line-height 1.25 | ||||||
|  |     padding 8px 16px | ||||||
|  |     border-radius radius-normal | ||||||
|  |     background-color tip-fill | ||||||
|  |     white-space nowrap | ||||||
|  |     left 50% | ||||||
|  |     bottom 100% | ||||||
|  |     margin-bottom 20px | ||||||
|  |     transform translateX(-50%) | ||||||
|  | 
 | ||||||
|  |   &:hover::after, | ||||||
|  |   &:active::after | ||||||
|  |     opacity 1 | ||||||
|  |     visibility visible | ||||||
|  | 
 | ||||||
|  |   &.is-higher | ||||||
|  |     z-index 20 | ||||||
|  |   &.is-active span | ||||||
|  |     transform scale(1.3) | ||||||
|  |   span | ||||||
|  |     display block | ||||||
|  |     cursor pointer | ||||||
|  |     width 40px | ||||||
|  |     height 40px | ||||||
|  |     background-color slider-handle-bg | ||||||
|  |     border-radius 50% | ||||||
|  |     box-shadow 0 1px 2px rgba(0, 0, 0, 0.2) | ||||||
|  |     transition transform 200ms | ||||||
|  | </style> | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | import Slider from '../index' | ||||||
|  | import {mount} from 'avoriaz' | ||||||
|  | 
 | ||||||
|  | describe('Slider', () => { | ||||||
|  |   let wrapper | ||||||
|  | 
 | ||||||
|  |   afterEach(() => { | ||||||
|  |     wrapper && wrapper.destroy() | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   it('create a simple slider', () => { | ||||||
|  |     wrapper = mount(Slider) | ||||||
|  | 
 | ||||||
|  |     expect(wrapper.hasClass('md-slider')).to.be.true | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  | @ -227,6 +227,11 @@ | ||||||
|     "path": "/radio", |     "path": "/radio", | ||||||
|     "icon": "radio", |     "icon": "radio", | ||||||
|     "text": "单选框" |     "text": "单选框" | ||||||
|  |   }, { | ||||||
|  |     "name": "Slider", | ||||||
|  |     "path": "/slider", | ||||||
|  |     "icon": "slider", | ||||||
|  |     "text": "滑块" | ||||||
|   }, { |   }, { | ||||||
|     "name": "Switch", |     "name": "Switch", | ||||||
|     "path": "/switch", |     "path": "/switch", | ||||||
|  |  | ||||||
|  | @ -45,4 +45,4 @@ export {default as WaterMark} from '../components/water-mark/demo' | ||||||
| export {default as Transition} from '../components/transition/demo' | export {default as Transition} from '../components/transition/demo' | ||||||
| export {default as DetailItem} from '../components/detail-item/demo' | export {default as DetailItem} from '../components/detail-item/demo' | ||||||
| export {default as Overlay} from '../components/overlay/demo' | export {default as Overlay} from '../components/overlay/demo' | ||||||
| /* @init<%export {default as ${componentNameUpper}} from '../components/${componentName}/demo'%> */ | export {default as Slider} from '../components/slider/demo'
/* @init<%export {default as ${componentNameUpper}} from '../components/${componentName}/demo'%> */ | ||||||
|  |  | ||||||
|  | @ -45,4 +45,4 @@ export const Bill =  r => require.ensure([], () => r(require('../components/bill | ||||||
| export const WaterMark =  r => require.ensure([], () => r(require('../components/water-mark/demo')), 'water-mark') | export const WaterMark =  r => require.ensure([], () => r(require('../components/water-mark/demo')), 'water-mark') | ||||||
| export const Transition =  r => require.ensure([], () => r(require('../components/transition/demo')), 'transition') | export const Transition =  r => require.ensure([], () => r(require('../components/transition/demo')), 'transition') | ||||||
| export const DetailItem =  r => require.ensure([], () => r(require('../components/detail-item/demo')), 'detail-item') | export const DetailItem =  r => require.ensure([], () => r(require('../components/detail-item/demo')), 'detail-item') | ||||||
| export const Overlay =  r => require.ensure([], () => r(require('../components/overlay/demo')), 'overlay')
/* @init<%export const ${componentNameUpper} =  r => require.ensure([], () => r(require('../components/${componentName}/demo')), '${componentName}')%> */ | export const Overlay =  r => require.ensure([], () => r(require('../components/overlay/demo')), 'overlay')
export const Slider =  r => require.ensure([], () => r(require('../components/slider/demo')), 'slider')
/* @init<%export const ${componentNameUpper} =  r => require.ensure([], () => r(require('../components/${componentName}/demo')), '${componentName}')%> */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue