mirror of
https://gitee.com/vant-contrib/vant-weapp.git
synced 2025-04-05 10:22:44 +08:00
[new feature] add slider component (#453)
This commit is contained in:
parent
8dd0faa3dc
commit
eecc4bbdaa
4
dist/actionsheet/index.js
vendored
4
dist/actionsheet/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
show: Boolean,
|
||||
title: String,
|
||||
|
4
dist/badge-group/index.js
vendored
4
dist/badge-group/index.js
vendored
@ -1,6 +1,10 @@
|
||||
const BADGE_PATH = '../badge/index';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
relations: {
|
||||
|
4
dist/badge/index.js
vendored
4
dist/badge/index.js
vendored
@ -1,6 +1,10 @@
|
||||
const BADGE_GROUP_PATH = '../badge-group/index';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
relations: {
|
||||
|
57
dist/behaviors/button.js
vendored
Normal file
57
dist/behaviors/button.js
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
module.exports = Behavior({
|
||||
properties: {
|
||||
loading: Boolean,
|
||||
// 在自定义组件中,无法与外界的 form 组件联动,暂时不开放
|
||||
// formType: String,
|
||||
openType: String,
|
||||
appParameter: String,
|
||||
// 暂时不开放,直接传入无法设置样式
|
||||
// hoverClass: {
|
||||
// type: String,
|
||||
// value: 'button-hover'
|
||||
// },
|
||||
hoverStopPropagation: Boolean,
|
||||
hoverStartTime: {
|
||||
type: Number,
|
||||
value: 20
|
||||
},
|
||||
hoverStayTime: {
|
||||
type: Number,
|
||||
value: 70
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
value: 'en'
|
||||
},
|
||||
sessionFrom: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
sendMessageTitle: String,
|
||||
sendMessagePath: String,
|
||||
sendMessageImg: String,
|
||||
showMessageCard: String
|
||||
},
|
||||
|
||||
methods: {
|
||||
bindgetuserinfo(event = {}) {
|
||||
this.triggerEvent('getuserinfo', event.detail || {});
|
||||
},
|
||||
|
||||
bindcontact(event = {}) {
|
||||
this.triggerEvent('contact', event.detail || {});
|
||||
},
|
||||
|
||||
bindgetphonenumber(event = {}) {
|
||||
this.triggerEvent('getphonenumber', event.detail || {});
|
||||
},
|
||||
|
||||
bindopensetting(event = {}) {
|
||||
this.triggerEvent('opensetting', event.detail || {});
|
||||
},
|
||||
|
||||
binderror(event = {}) {
|
||||
this.triggerEvent('error', event.detail || {});
|
||||
}
|
||||
}
|
||||
});
|
22
dist/behaviors/touch.js
vendored
Normal file
22
dist/behaviors/touch.js
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
module.exports = Behavior({
|
||||
methods: {
|
||||
touchStart(event) {
|
||||
this.direction = '';
|
||||
this.deltaX = 0;
|
||||
this.deltaY = 0;
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
this.startX = event.touches[0].clientX;
|
||||
this.startY = event.touches[0].clientY;
|
||||
},
|
||||
|
||||
touchMove(event) {
|
||||
const touch = event.touches[0];
|
||||
this.deltaX = touch.clientX - this.startX;
|
||||
this.deltaY = touch.clientY - this.startY;
|
||||
this.offsetX = Math.abs(this.deltaX);
|
||||
this.offsetY = Math.abs(this.deltaY);
|
||||
this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : '';
|
||||
}
|
||||
}
|
||||
});
|
8
dist/button/index.js
vendored
8
dist/button/index.js
vendored
@ -1,4 +1,4 @@
|
||||
const nativeBehaviors = require('./behaviors');
|
||||
const buttonBehaviors = require('../behaviors/button');
|
||||
const classnames = require('../common/classnames');
|
||||
|
||||
const observer = function() {
|
||||
@ -6,9 +6,13 @@ const observer = function() {
|
||||
};
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class', 'loading-class'],
|
||||
|
||||
behaviors: [nativeBehaviors],
|
||||
behaviors: [buttonBehaviors],
|
||||
|
||||
properties: {
|
||||
type: {
|
||||
|
3
dist/card/index.js
vendored
3
dist/card/index.js
vendored
@ -1,6 +1,7 @@
|
||||
Component({
|
||||
options: {
|
||||
multipleSlots: true
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: [
|
||||
|
4
dist/cell-group/index.js
vendored
4
dist/cell-group/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
|
3
dist/cell/index.js
vendored
3
dist/cell/index.js
vendored
@ -9,7 +9,8 @@ Component({
|
||||
],
|
||||
|
||||
options: {
|
||||
multipleSlots: true
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
|
4
dist/col/index.js
vendored
4
dist/col/index.js
vendored
@ -1,6 +1,10 @@
|
||||
const ROW_PATH = '../row/index';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
relations: {
|
||||
|
3
dist/field/index.js
vendored
3
dist/field/index.js
vendored
@ -6,7 +6,8 @@ Component({
|
||||
],
|
||||
|
||||
options: {
|
||||
multipleSlots: true
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
|
4
dist/icon/index.js
vendored
4
dist/icon/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
|
4
dist/loading/index.js
vendored
4
dist/loading/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
|
3
dist/nav-bar/index.js
vendored
3
dist/nav-bar/index.js
vendored
@ -5,7 +5,8 @@ Component({
|
||||
],
|
||||
|
||||
options: {
|
||||
multipleSlots: true
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
|
4
dist/notice-bar/index.js
vendored
4
dist/notice-bar/index.js
vendored
@ -3,6 +3,10 @@ const FONT_COLOR = '#f60';
|
||||
const BG_COLOR = '#fff7cc';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
|
32
dist/notify/index.js
vendored
32
dist/notify/index.js
vendored
@ -1,4 +1,10 @@
|
||||
import Notify from './notify';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
text: String,
|
||||
color: {
|
||||
@ -40,28 +46,4 @@ Component({
|
||||
}
|
||||
});
|
||||
|
||||
const defaultOptions = {
|
||||
selector: '#van-notify',
|
||||
duration: 3000
|
||||
};
|
||||
|
||||
export default function Notify(options = {}) {
|
||||
const pages = getCurrentPages();
|
||||
const ctx = pages[pages.length - 1];
|
||||
|
||||
options = Object.assign({}, defaultOptions, parseParam(options));
|
||||
|
||||
const el = ctx.selectComponent(options.selector);
|
||||
delete options.selector;
|
||||
|
||||
if (el) {
|
||||
el.setData({
|
||||
...options
|
||||
});
|
||||
el.show();
|
||||
}
|
||||
}
|
||||
|
||||
function parseParam(params = '') {
|
||||
return typeof params === 'object' ? params : { text: params };
|
||||
}
|
||||
export default Notify;
|
||||
|
4
dist/overlay/index.js
vendored
4
dist/overlay/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
show: Boolean,
|
||||
mask: Boolean,
|
||||
|
3
dist/panel/index.js
vendored
3
dist/panel/index.js
vendored
@ -5,7 +5,8 @@ Component({
|
||||
],
|
||||
|
||||
options: {
|
||||
multipleSlots: true
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
|
4
dist/popup/index.js
vendored
4
dist/popup/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: [
|
||||
'custom-class',
|
||||
'overlay-class'
|
||||
|
4
dist/row/index.js
vendored
4
dist/row/index.js
vendored
@ -1,6 +1,10 @@
|
||||
const COL_PATH = '../col/index';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
relations: {
|
||||
|
3
dist/search/index.js
vendored
3
dist/search/index.js
vendored
@ -2,7 +2,8 @@ Component({
|
||||
externalClasses: ['custom-class', 'cancel-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
|
98
dist/slider/index.js
vendored
Normal file
98
dist/slider/index.js
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
const touchBehaviors = require('../behaviors/touch');
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
behaviors: [touchBehaviors],
|
||||
|
||||
properties: {
|
||||
disabled: Boolean,
|
||||
max: {
|
||||
type: Number,
|
||||
value: 100
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
value: 1
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
barHeight: {
|
||||
type: String,
|
||||
value: '2px'
|
||||
}
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.updateValue(this.data.value);
|
||||
},
|
||||
|
||||
methods: {
|
||||
getRect(callback) {
|
||||
wx.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('.van-slider')
|
||||
.boundingClientRect(callback)
|
||||
.exec();
|
||||
},
|
||||
|
||||
onTouchStart(event) {
|
||||
if (this.data.disabled) return;
|
||||
|
||||
this.touchStart(event);
|
||||
this.startValue = this.format(this.data.value);
|
||||
},
|
||||
|
||||
onTouchMove(event) {
|
||||
if (this.data.disabled) return;
|
||||
|
||||
this.touchMove(event);
|
||||
this.getRect(rect => {
|
||||
const diff = this.deltaX / rect.width * 100;
|
||||
this.updateValue(this.startValue + diff);
|
||||
});
|
||||
},
|
||||
|
||||
onTouchEnd() {
|
||||
if (this.data.disabled) return;
|
||||
this.updateValue(this.data.value, true);
|
||||
},
|
||||
|
||||
onClick(event) {
|
||||
if (this.data.disabled) return;
|
||||
|
||||
this.getRect(rect => {
|
||||
const value = (event.detail.x - rect.left) / rect.width * 100;
|
||||
this.updateValue(value, true);
|
||||
});
|
||||
},
|
||||
|
||||
updateValue(value, end) {
|
||||
value = this.format(value);
|
||||
|
||||
this.setData({
|
||||
value,
|
||||
barStyle: `width: ${value}%; height: ${this.data.barHeight};`
|
||||
});
|
||||
|
||||
if (end) {
|
||||
this.triggerEvent('change', value);
|
||||
}
|
||||
},
|
||||
|
||||
format(value) {
|
||||
const { max, min, step } = this.data;
|
||||
return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
|
||||
}
|
||||
}
|
||||
});
|
3
dist/slider/index.json
vendored
Normal file
3
dist/slider/index.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
11
dist/slider/index.wxml
vendored
Normal file
11
dist/slider/index.wxml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<view class="custom-class van-slider {{ disabled ? 'van-slider--disabled' : '' }}" bind:tap="onClick">
|
||||
<view class="van-slider__bar" style="{{ barStyle }}">
|
||||
<view
|
||||
class="van-slider__button"
|
||||
bind:touchstart="onTouchStart"
|
||||
catch:touchmove="onTouchMove"
|
||||
bind:touchend="onTouchEnd"
|
||||
bind:touchcancel="onTouchEnd"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
1
dist/slider/index.wxss
vendored
Normal file
1
dist/slider/index.wxss
vendored
Normal file
@ -0,0 +1 @@
|
||||
.van-slider{position:relative;border-radius:999px;background-color:#e5e5e5}.van-slider__bar{position:relative;border-radius:inherit;background-color:#38f}.van-slider__button{position:absolute;top:50%;right:0;width:20px;height:20px;border-radius:50%;background-color:#fff;-webkit-transform:translate3d(50%,-50%,0);transform:translate3d(50%,-50%,0);box-shadow:0 1px 2px rgba(0,0,0,.5)}.van-slider__button::after{content:'';position:absolute;width:200%;height:200%;top:-50%;left:-50%}.van-slider--disabled{opacity:.3}
|
4
dist/stepper/index.js
vendored
4
dist/stepper/index.js
vendored
@ -3,6 +3,10 @@
|
||||
const MAX = 2147483647;
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: [
|
||||
'custom-class',
|
||||
'input-class',
|
||||
|
4
dist/steps/index.js
vendored
4
dist/steps/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: [
|
||||
'custom-class'
|
||||
],
|
||||
|
4
dist/switch/index.js
vendored
4
dist/switch/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class', 'node-class'],
|
||||
|
||||
properties: {
|
||||
|
5
dist/tabbar-item/index.js
vendored
5
dist/tabbar-item/index.js
vendored
@ -1,8 +1,6 @@
|
||||
const TABBAR_PATH = '../tabbar/index';
|
||||
|
||||
Component({
|
||||
name: 'tabbar-item',
|
||||
|
||||
properties: {
|
||||
info: null,
|
||||
icon: String,
|
||||
@ -10,7 +8,8 @@ Component({
|
||||
},
|
||||
|
||||
options: {
|
||||
multipleSlots: true
|
||||
multipleSlots: true,
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
relations: {
|
||||
|
4
dist/tabbar/index.js
vendored
4
dist/tabbar/index.js
vendored
@ -1,6 +1,10 @@
|
||||
const ITEM_PATH = '../tabbar-item/index';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
|
4
dist/tag/index.js
vendored
4
dist/tag/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
|
4
dist/toast/index.js
vendored
4
dist/toast/index.js
vendored
@ -1,6 +1,10 @@
|
||||
import Toast from './toast';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
show: Boolean,
|
||||
mask: Boolean,
|
||||
|
4
dist/transition/index.js
vendored
4
dist/transition/index.js
vendored
@ -1,4 +1,8 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
|
4
dist/tree-select/index.js
vendored
4
dist/tree-select/index.js
vendored
@ -1,6 +1,10 @@
|
||||
const ITEM_HEIGHT = 44;
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
items: {
|
||||
type: Array,
|
||||
|
@ -28,6 +28,7 @@ const MAP = {
|
||||
notify: 'notify-201808112050.png',
|
||||
popup: 'popup-201808092138.png',
|
||||
panel: 'panel-201808092138.png',
|
||||
slider: 'slider-201808221024.png',
|
||||
stepper: 'stepper-201808092138.png',
|
||||
search: 'search-201808092138.png',
|
||||
steps: 'steps-201808092138.png',
|
||||
|
@ -19,6 +19,7 @@
|
||||
"pages/steps/index",
|
||||
"pages/switch/index",
|
||||
"pages/search/index",
|
||||
"pages/slider/index",
|
||||
"pages/tag/index",
|
||||
"pages/toast/index",
|
||||
"pages/tabbar/index",
|
||||
|
@ -71,6 +71,10 @@ export default [
|
||||
path: '/search',
|
||||
title: 'Search 搜索'
|
||||
},
|
||||
{
|
||||
path: '/slider',
|
||||
title: 'Slider 滑块'
|
||||
},
|
||||
{
|
||||
path: '/stepper',
|
||||
title: 'Stepper 步进器'
|
||||
|
10
example/pages/slider/index.js
Normal file
10
example/pages/slider/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
import Page from '../../common/page';
|
||||
|
||||
Page({
|
||||
onChange(event) {
|
||||
wx.showToast({
|
||||
icon: 'none',
|
||||
title: `当前值:${event.detail}`
|
||||
});
|
||||
}
|
||||
});
|
7
example/pages/slider/index.json
Normal file
7
example/pages/slider/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"navigationBarTitleText": "Slider 滑块",
|
||||
"usingComponents": {
|
||||
"demo-block": "../../components/demo-block/index",
|
||||
"van-slider": "../../dist/slider/index"
|
||||
}
|
||||
}
|
27
example/pages/slider/index.wxml
Normal file
27
example/pages/slider/index.wxml
Normal file
@ -0,0 +1,27 @@
|
||||
<demo-block title="基础用法">
|
||||
<van-slider custom-class="slider" value="50" bind:change="onChange" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="指定选择范围">
|
||||
<van-slider
|
||||
custom-class="slider"
|
||||
value="50"
|
||||
min="10"
|
||||
max="90"
|
||||
bind:change="onChange"
|
||||
/>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="禁用">
|
||||
<van-slider custom-class="slider" value="50" disabled />
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="指定步长">
|
||||
<van-slider
|
||||
custom-class="slider"
|
||||
value="50"
|
||||
step="10"
|
||||
bar-height="4px"
|
||||
bind:change="onChange"
|
||||
/>
|
||||
</demo-block>
|
3
example/pages/slider/index.wxss
Normal file
3
example/pages/slider/index.wxss
Normal file
@ -0,0 +1,3 @@
|
||||
.slider {
|
||||
margin: 0 15px 30px;
|
||||
}
|
22
packages/behaviors/touch.js
Normal file
22
packages/behaviors/touch.js
Normal file
@ -0,0 +1,22 @@
|
||||
module.exports = Behavior({
|
||||
methods: {
|
||||
touchStart(event) {
|
||||
this.direction = '';
|
||||
this.deltaX = 0;
|
||||
this.deltaY = 0;
|
||||
this.offsetX = 0;
|
||||
this.offsetY = 0;
|
||||
this.startX = event.touches[0].clientX;
|
||||
this.startY = event.touches[0].clientY;
|
||||
},
|
||||
|
||||
touchMove(event) {
|
||||
const touch = event.touches[0];
|
||||
this.deltaX = touch.clientX - this.startX;
|
||||
this.deltaY = touch.clientY - this.startY;
|
||||
this.offsetX = Math.abs(this.deltaX);
|
||||
this.offsetY = Math.abs(this.deltaY);
|
||||
this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : '';
|
||||
}
|
||||
}
|
||||
});
|
@ -80,7 +80,7 @@
|
||||
| 事件名 | 说明 | 参数 |
|
||||
|-----------|-----------|-----------|
|
||||
| bind:click | 点击按钮且按钮状态不为加载或禁用时触发 | - |
|
||||
| bind:getuserinfo | 用户点击该按钮时,会返回获取到的用户信息,从返回参数的 detail 中获取到的值同 wx.getUserInfo | - |
|
||||
| bind:getuserinfo | 用户点击该按钮时,会返回获取到的用户信息,<br>从返回参数的 detail 中获取到的值同 wx.getUserInfo | - |
|
||||
| bind:contact | 客服消息回调 | - |
|
||||
| bind:getphonenumber | 获取用户手机号回调 | - |
|
||||
| bind:error | 当使用开放能力时,发生错误的回调 | - |
|
||||
|
66
packages/slider/README.md
Normal file
66
packages/slider/README.md
Normal file
@ -0,0 +1,66 @@
|
||||
## Slider 滑块
|
||||
|
||||
### 使用指南
|
||||
在 index.json 中引入组件
|
||||
```json
|
||||
"usingComponents": {
|
||||
"van-slider": "/packages/slider/index"
|
||||
}
|
||||
```
|
||||
#### 基本用法
|
||||
|
||||
```html
|
||||
<van-slider value="50" bind:change="onChange" />
|
||||
```
|
||||
|
||||
```js
|
||||
Page({
|
||||
onChange(event) {
|
||||
wx.showToast({
|
||||
icon: 'none',
|
||||
title: `当前值:${event.detail}`
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### 指定选择范围
|
||||
|
||||
```html
|
||||
<van-slider value="50" min="10" max="90" />
|
||||
```
|
||||
|
||||
#### 禁用
|
||||
|
||||
```html
|
||||
<van-slider value="50" disabled />
|
||||
```
|
||||
|
||||
#### 指定步长
|
||||
|
||||
```html
|
||||
<van-slider value="50" step="10" bar-height="4px" />
|
||||
```
|
||||
|
||||
### API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|-----------|-----------|-----------|-------------|
|
||||
| value | 当前进度百分比,取值范围为 0-100 | `Number` | `0` |
|
||||
| disabled | 是否禁用滑块 | `Boolean` | `false` |
|
||||
| max | 最大值 | `Number` | `100` |
|
||||
| min | 最小值 | `Number` | `0` |
|
||||
| step | 步长 | `Number` | `1` |
|
||||
| bar-height | 进度条高度 | `String` | `2px` |
|
||||
|
||||
### Event
|
||||
|
||||
| 事件名 | 说明 | 参数 |
|
||||
|-----------|-----------|-----------|
|
||||
| bind:change | 进度值改变后触发 | event.detail: 当前进度 |
|
||||
|
||||
### 外部样式类
|
||||
|
||||
| 类名 | 说明 |
|
||||
|-----------|-----------|
|
||||
| custom-class | 根节点样式类 |
|
98
packages/slider/index.js
Normal file
98
packages/slider/index.js
Normal file
@ -0,0 +1,98 @@
|
||||
const touchBehaviors = require('../behaviors/touch');
|
||||
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
behaviors: [touchBehaviors],
|
||||
|
||||
properties: {
|
||||
disabled: Boolean,
|
||||
max: {
|
||||
type: Number,
|
||||
value: 100
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
value: 1
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
barHeight: {
|
||||
type: String,
|
||||
value: '2px'
|
||||
}
|
||||
},
|
||||
|
||||
attached() {
|
||||
this.updateValue(this.data.value);
|
||||
},
|
||||
|
||||
methods: {
|
||||
getRect(callback) {
|
||||
wx.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('.van-slider')
|
||||
.boundingClientRect(callback)
|
||||
.exec();
|
||||
},
|
||||
|
||||
onTouchStart(event) {
|
||||
if (this.data.disabled) return;
|
||||
|
||||
this.touchStart(event);
|
||||
this.startValue = this.format(this.data.value);
|
||||
},
|
||||
|
||||
onTouchMove(event) {
|
||||
if (this.data.disabled) return;
|
||||
|
||||
this.touchMove(event);
|
||||
this.getRect(rect => {
|
||||
const diff = this.deltaX / rect.width * 100;
|
||||
this.updateValue(this.startValue + diff);
|
||||
});
|
||||
},
|
||||
|
||||
onTouchEnd() {
|
||||
if (this.data.disabled) return;
|
||||
this.updateValue(this.data.value, true);
|
||||
},
|
||||
|
||||
onClick(event) {
|
||||
if (this.data.disabled) return;
|
||||
|
||||
this.getRect(rect => {
|
||||
const value = (event.detail.x - rect.left) / rect.width * 100;
|
||||
this.updateValue(value, true);
|
||||
});
|
||||
},
|
||||
|
||||
updateValue(value, end) {
|
||||
value = this.format(value);
|
||||
|
||||
this.setData({
|
||||
value,
|
||||
barStyle: `width: ${value}%; height: ${this.data.barHeight};`
|
||||
});
|
||||
|
||||
if (end) {
|
||||
this.triggerEvent('change', value);
|
||||
}
|
||||
},
|
||||
|
||||
format(value) {
|
||||
const { max, min, step } = this.data;
|
||||
return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
|
||||
}
|
||||
}
|
||||
});
|
3
packages/slider/index.json
Normal file
3
packages/slider/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
39
packages/slider/index.pcss
Normal file
39
packages/slider/index.pcss
Normal file
@ -0,0 +1,39 @@
|
||||
@import '../common/style/var.pcss';
|
||||
|
||||
.van-slider {
|
||||
position: relative;
|
||||
border-radius: 999px;
|
||||
background-color: $gray-light;
|
||||
|
||||
&__bar {
|
||||
position: relative;
|
||||
border-radius: inherit;
|
||||
background-color: $blue;
|
||||
}
|
||||
|
||||
&__button {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: $white;
|
||||
transform: translate3d(50%, -50%, 0);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .5);
|
||||
|
||||
/* use pseudo element to expand touch area */
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
}
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: .3;
|
||||
}
|
||||
}
|
11
packages/slider/index.wxml
Normal file
11
packages/slider/index.wxml
Normal file
@ -0,0 +1,11 @@
|
||||
<view class="custom-class van-slider {{ disabled ? 'van-slider--disabled' : '' }}" bind:tap="onClick">
|
||||
<view class="van-slider__bar" style="{{ barStyle }}">
|
||||
<view
|
||||
class="van-slider__button"
|
||||
bind:touchstart="onTouchStart"
|
||||
catch:touchmove="onTouchMove"
|
||||
bind:touchend="onTouchEnd"
|
||||
bind:touchcancel="onTouchEnd"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
Loading…
x
Reference in New Issue
Block a user