mirror of
https://github.com/ant-design/ant-design-mini.git
synced 2024-10-23 08:44:21 +08:00
Slider 适配微信 (#935)
* feat: slider 适配微信 * fix: 更新 demo --------- Co-authored-by: DiamondYuan <fandi.yfd@antgroup.com>
This commit is contained in:
parent
3e8e10dcef
commit
f3bb78bfd8
@ -1,12 +1,12 @@
|
||||
<container title="基本使用">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
onChange="onChange"
|
||||
onAfterChange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="无节点双滑块">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ [20, 60] }}"
|
||||
range
|
||||
onChange="onChange"
|
||||
@ -14,7 +14,7 @@
|
||||
</container>
|
||||
|
||||
<container title="节点单滑块">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ 60 }}"
|
||||
step="{{ 20 }}"
|
||||
showTicks
|
||||
@ -23,7 +23,7 @@
|
||||
</container>
|
||||
|
||||
<container title="有数字节点单滑块">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
step="{{ 20 }}"
|
||||
showTicks
|
||||
@ -33,7 +33,7 @@
|
||||
</container>
|
||||
|
||||
<container title="节点双滑块">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ [10, 50] }}"
|
||||
step="{{ 10 }}"
|
||||
showTicks
|
||||
@ -43,7 +43,7 @@
|
||||
</container>
|
||||
|
||||
<container title="有数字节点双滑块">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ [10, 50] }}"
|
||||
step="{{ 10 }}"
|
||||
showTicks
|
||||
@ -54,7 +54,7 @@
|
||||
</container>
|
||||
|
||||
<container title="在拖动时显示悬浮提示">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
showTooltip
|
||||
onChange="onChange"
|
||||
@ -62,12 +62,12 @@
|
||||
</container>
|
||||
|
||||
<container title="受控模式">
|
||||
<slider
|
||||
<ant-slider
|
||||
min="{{ 0 }}"
|
||||
max="{{ 100 }}"
|
||||
value="{{ value }}"
|
||||
onChange="handleChange" />
|
||||
<stepper
|
||||
<ant-stepper
|
||||
min="{{ 0 }}"
|
||||
max="{{ 100 }}"
|
||||
value="{{ value }}"
|
||||
@ -75,7 +75,7 @@
|
||||
</container>
|
||||
|
||||
<container title="自定义">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
step="{{ 20 }}"
|
||||
showTooltip
|
||||
@ -89,27 +89,27 @@
|
||||
<text
|
||||
slot="tick"
|
||||
slot-scope="props"
|
||||
>{{ props.value }}</text
|
||||
>{{ props.value }}°C</text
|
||||
>
|
||||
<!-- display: inline -->
|
||||
<text
|
||||
slot="showTooltip"
|
||||
slot="tooltip"
|
||||
slot-scope="props"
|
||||
>{{ props.value }}</text
|
||||
>{{ props.value }}°C</text
|
||||
>
|
||||
|
||||
<view slot="slider">
|
||||
<view class="custom-slider-handler">
|
||||
<icon
|
||||
<ant-icon
|
||||
type="SmileOutline"
|
||||
style="color: #ff8f1f" />
|
||||
</view>
|
||||
</view>
|
||||
</slider>
|
||||
</ant-slider>
|
||||
</container>
|
||||
|
||||
<container title="禁用状态">
|
||||
<slider
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
disabled
|
||||
onChange="onChange" />
|
||||
|
@ -8,7 +8,7 @@ Page({
|
||||
onAfterChange: function (value, e) {
|
||||
console.log('当前值:', value, e);
|
||||
my.showToast({
|
||||
content: "\u5F53\u524D\u9009\u4E2D\u503C\u4E3A\uFF1A".concat(value)
|
||||
content: 'value: ' + value,
|
||||
});
|
||||
},
|
||||
handleChange: function (value, e) {
|
||||
@ -16,5 +16,5 @@ Page({
|
||||
this.setData({
|
||||
value: value,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"defaultTitle": "Slider",
|
||||
"usingComponents": {
|
||||
"slider": "../../../src/Slider/index",
|
||||
"icon": "../../../src/Icon/index",
|
||||
"stepper": "../../../src/Stepper/index",
|
||||
"ant-slider": "../../../src/Slider/index",
|
||||
"ant-icon": "../../../src/Icon/index",
|
||||
"ant-stepper": "../../../src/Stepper/index",
|
||||
"container": "../../../src/Container/index"
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect';
|
||||
import { ISliderProps, SliderValue } from './props';
|
||||
|
||||
interface Rect {
|
||||
@ -33,12 +34,12 @@ export class SliderController {
|
||||
|
||||
constructor(private _value: SliderValue, private _props: ISliderProps) {}
|
||||
|
||||
handleMove(e, type: MoveType) {
|
||||
handleMove(component: any, e, type: MoveType) {
|
||||
if (this.props.disabled) {
|
||||
return;
|
||||
}
|
||||
const currentId = this.getId();
|
||||
this.getRect(e).then((res) => {
|
||||
this.getRect(component, e).then((res) => {
|
||||
const { value, moveStatus } = this.getValue(res, type);
|
||||
const formatValue = this.formatValue(value);
|
||||
this.fireChange(currentId, formatValue, moveStatus, type, e);
|
||||
@ -116,28 +117,24 @@ export class SliderController {
|
||||
return id;
|
||||
}
|
||||
|
||||
private getRect(e): Promise<any> {
|
||||
private async getRect(component: any, e: any): Promise<any> {
|
||||
const elementId = e.currentTarget.id;
|
||||
return new Promise((r) => {
|
||||
my.createSelectorQuery()
|
||||
.select(`#${elementId}`)
|
||||
.boundingClientRect()
|
||||
.exec((list) => {
|
||||
const element = list[0];
|
||||
const touch = e.changedTouches[0];
|
||||
if (element) {
|
||||
return r({
|
||||
touch: {
|
||||
pageX: touch.pageX,
|
||||
},
|
||||
element: {
|
||||
left: element.left,
|
||||
width: element.width,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
const element = await getInstanceBoundingClientRect(
|
||||
component,
|
||||
`#${elementId}`
|
||||
);
|
||||
const touch = e.changedTouches[0];
|
||||
if (element) {
|
||||
return {
|
||||
touch: {
|
||||
pageX: touch.pageX,
|
||||
},
|
||||
element: {
|
||||
left: element.left,
|
||||
width: element.width,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fitSliderValue(
|
||||
@ -146,7 +143,7 @@ export class SliderController {
|
||||
max: number,
|
||||
isRange: boolean
|
||||
) {
|
||||
if (value === undefined) {
|
||||
if (value === undefined || value === null) {
|
||||
if (isRange) {
|
||||
return [min, min] as SliderValue;
|
||||
} else {
|
||||
|
@ -19,7 +19,6 @@
|
||||
</view>
|
||||
</view>
|
||||
</slot>
|
||||
|
||||
<view
|
||||
slot="content"
|
||||
class="ant-slider-tooltip-content">
|
||||
@ -48,37 +47,36 @@
|
||||
<view class="ant-slider-track-fill-background" />
|
||||
<view
|
||||
class="ant-slider-track-fill-front {{ activeLineClassName || '' }}"
|
||||
style="width: {{ sliderWidth }}%; left: {{ sliderLeft }}%; {{ activeLineStyle || '' }}">
|
||||
<view class="ant-slider-showTicks">
|
||||
<block
|
||||
a:for="{{ tickList }}"
|
||||
a:for-index="index"
|
||||
a:for-item="item">
|
||||
style="width: {{ sliderWidth }}%; left: {{ sliderLeft }}%; {{ activeLineStyle || '' }}" />
|
||||
<view class="ant-slider-showTicks">
|
||||
<block
|
||||
a:for="{{ tickList }}"
|
||||
a:for-index="index"
|
||||
a:for-item="item">
|
||||
<view
|
||||
class="ant-slider-tick ant-slider-tick-{{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) ? 'front' : 'back' }} {{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) && activeDotClassName ? activeDotClassName : '' }}"
|
||||
style="left: {{ item.left }}%;{{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) && activeDotStyle ? activeDotStyle : '' }}">
|
||||
<view
|
||||
class="ant-slider-tick ant-slider-tick-{{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) ? 'front' : 'back' }} {{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) && activeDotClassName ? activeDotClassName : '' }}"
|
||||
style="left: {{ item.left }}%;{{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) && activeDotStyle ? activeDotStyle : '' }}">
|
||||
<view
|
||||
a:if="{{ showNumber }}"
|
||||
class="ant-slider-tick-number">
|
||||
<slot
|
||||
name="tick"
|
||||
value="{{ item.value }}">
|
||||
{{ item.value }}
|
||||
</slot>
|
||||
</view>
|
||||
a:if="{{ showNumber }}"
|
||||
class="ant-slider-tick-number">
|
||||
<slot
|
||||
name="tick"
|
||||
value="{{ item.value }}">
|
||||
{{ item.value }}
|
||||
</slot>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<template
|
||||
a:if="{{ range }}"
|
||||
is="slider-handler"
|
||||
data="{{ position: sliderLeft, icon: icon, value: mixin.value[0], showTooltip: changingStart && showTooltip }}" />
|
||||
<template
|
||||
is="slider-handler"
|
||||
data="{{ position: sliderLeft + sliderWidth, icon: icon, value: range ? mixin.value[1] : mixin.value, showTooltip: changingEnd && showTooltip }}" />
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<template
|
||||
a:if="{{ range }}"
|
||||
is="slider-handler"
|
||||
data="{{ position: sliderLeft, icon: icon, value: mixin.value[0], showTooltip: changingStart && showTooltip }}" />
|
||||
<template
|
||||
is="slider-handler"
|
||||
data="{{ position: sliderLeft + sliderWidth, icon: icon, value: range ? mixin.value[1] : mixin.value, showTooltip: changingEnd && showTooltip }}" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view />
|
||||
</view>
|
||||
|
@ -1,4 +1,10 @@
|
||||
import { useEvent, useMemo, useRef, useState } from 'functional-mini/component';
|
||||
import {
|
||||
useEvent,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useComponent,
|
||||
} from 'functional-mini/component';
|
||||
import '../_util/assert-component2';
|
||||
import { mountComponent } from '../_util/component';
|
||||
import { useComponentEvent } from '../_util/hooks/useComponentEvent';
|
||||
@ -15,6 +21,7 @@ const useSliderController = (props: ISliderProps) => {
|
||||
};
|
||||
|
||||
const Slider = (props) => {
|
||||
const component = useComponent();
|
||||
const sliderController: SliderController = useSliderController(props);
|
||||
const [value, { update, isControlled }] = useMixState(props.defaultValue, {
|
||||
value: props.value,
|
||||
@ -55,18 +62,18 @@ const Slider = (props) => {
|
||||
|
||||
useEvent(
|
||||
'handleTrackTouchStart',
|
||||
(e) => sliderController.handleMove(e, 'start'),
|
||||
[props]
|
||||
(e) => sliderController.handleMove(component, e, 'start'),
|
||||
[component]
|
||||
);
|
||||
useEvent(
|
||||
'handleTrackTouchMove',
|
||||
(e) => sliderController.handleMove(e, 'move'),
|
||||
[props]
|
||||
(e) => sliderController.handleMove(component, e, 'move'),
|
||||
[component]
|
||||
);
|
||||
useEvent(
|
||||
'handleTrackTouchEnd',
|
||||
(e) => sliderController.handleMove(e, 'end'),
|
||||
[props]
|
||||
(e) => sliderController.handleMove(component, e, 'end'),
|
||||
[component, props]
|
||||
);
|
||||
|
||||
const tickList = useMemo(() => {
|
||||
@ -126,7 +133,18 @@ const Slider = (props) => {
|
||||
};
|
||||
|
||||
mountComponent(Slider, {
|
||||
min: 0,
|
||||
value: null,
|
||||
defaultValue: null,
|
||||
disabled: false,
|
||||
max: 100,
|
||||
min: 0,
|
||||
range: false,
|
||||
showNumber: false,
|
||||
step: 1,
|
||||
showTicks: false,
|
||||
showTooltip: false,
|
||||
activeLineStyle: '',
|
||||
activeDotStyle: '',
|
||||
activeLineClassName: '',
|
||||
activeDotClassName: '',
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"pages": [
|
||||
"demo/pages/Slider/index",
|
||||
"demo/pages/Stepper/index",
|
||||
"demo/pages/Input/index",
|
||||
"demo/pages/InputCustom/index",
|
||||
|
22
compiled/wechat/demo/pages/Slider/index.js
Normal file
22
compiled/wechat/demo/pages/Slider/index.js
Normal file
@ -0,0 +1,22 @@
|
||||
Page({
|
||||
data: {
|
||||
value: 80,
|
||||
},
|
||||
onChange: function (value, e) {
|
||||
console.log('slider changed:', value, e);
|
||||
},
|
||||
onAfterChange: function (value, e) {
|
||||
console.log('当前值:', value, e);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
wx.showToast({
|
||||
title: "value: ".concat(value.detail),
|
||||
});
|
||||
},
|
||||
handleChange: function (value, e) {
|
||||
console.log('slider changed:', value, e);
|
||||
this.setData({
|
||||
value: value.detail,
|
||||
});
|
||||
},
|
||||
});
|
9
compiled/wechat/demo/pages/Slider/index.json
Normal file
9
compiled/wechat/demo/pages/Slider/index.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"defaultTitle": "Slider",
|
||||
"usingComponents": {
|
||||
"ant-slider": "../../../src/Slider/index",
|
||||
"ant-icon": "../../../src/Icon/index",
|
||||
"ant-stepper": "../../../src/Stepper/index",
|
||||
"container": "../../../src/Container/index"
|
||||
}
|
||||
}
|
95
compiled/wechat/demo/pages/Slider/index.wxml
Normal file
95
compiled/wechat/demo/pages/Slider/index.wxml
Normal file
@ -0,0 +1,95 @@
|
||||
<container title="基本使用">
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="无节点双滑块">
|
||||
<ant-slider
|
||||
defaultValue="{{ [20, 60] }}"
|
||||
range
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="节点单滑块">
|
||||
<ant-slider
|
||||
defaultValue="{{ 60 }}"
|
||||
step="{{ 20 }}"
|
||||
showTicks
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="有数字节点单滑块">
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
step="{{ 20 }}"
|
||||
showTicks
|
||||
showNumber
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="节点双滑块">
|
||||
<ant-slider
|
||||
defaultValue="{{ [10, 50] }}"
|
||||
step="{{ 10 }}"
|
||||
showTicks
|
||||
range
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="有数字节点双滑块">
|
||||
<ant-slider
|
||||
defaultValue="{{ [10, 50] }}"
|
||||
step="{{ 10 }}"
|
||||
showTicks
|
||||
showNumber
|
||||
range
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="在拖动时显示悬浮提示">
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
showTooltip
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange" />
|
||||
</container>
|
||||
|
||||
<container title="受控模式">
|
||||
<ant-slider
|
||||
min="{{ 0 }}"
|
||||
max="{{ 100 }}"
|
||||
value="{{ value }}"
|
||||
bind:change="handleChange" />
|
||||
<ant-stepper
|
||||
min="{{ 0 }}"
|
||||
max="{{ 100 }}"
|
||||
value="{{ value }}"
|
||||
bind:change="handleChange" />
|
||||
</container>
|
||||
|
||||
<container title="自定义">
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
step="{{ 20 }}"
|
||||
showTooltip
|
||||
showTicks
|
||||
showNumber
|
||||
activeLineStyle="background-color: #ff8f1f"
|
||||
activeDotStyle="background-color: red"
|
||||
bind:change="onChange"
|
||||
bind:afterchange="onAfterChange"></ant-slider>
|
||||
</container>
|
||||
|
||||
<container title="禁用状态">
|
||||
<ant-slider
|
||||
defaultValue="{{ 80 }}"
|
||||
disabled
|
||||
bind:change="onChange" />
|
||||
</container>
|
9
compiled/wechat/demo/pages/Slider/index.wxss
Normal file
9
compiled/wechat/demo/pages/Slider/index.wxss
Normal file
@ -0,0 +1,9 @@
|
||||
.custom-slider-handler {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 4rpx 10rpx 0 rgba(0, 0, 0, 0.12);
|
||||
border-radius: 56rpx;
|
||||
text-align: center;
|
||||
line-height: 56rpx;
|
||||
}
|
251
compiled/wechat/src/Slider/controller.js
Normal file
251
compiled/wechat/src/Slider/controller.js
Normal file
@ -0,0 +1,251 @@
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect';
|
||||
var SliderController = /** @class */ (function () {
|
||||
function SliderController(_value, _props) {
|
||||
this._value = _value;
|
||||
this._props = _props;
|
||||
this.id = 0;
|
||||
this.valueId = 0;
|
||||
this._callback = null;
|
||||
this._moveStatus = null;
|
||||
}
|
||||
Object.defineProperty(SliderController.prototype, "value", {
|
||||
get: function () {
|
||||
return this._value;
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(SliderController.prototype, "props", {
|
||||
get: function () {
|
||||
return this._props;
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
SliderController.prototype.handleMove = function (component, e, type) {
|
||||
var _this = this;
|
||||
if (this.props.disabled) {
|
||||
return;
|
||||
}
|
||||
var currentId = this.getId();
|
||||
this.getRect(component, e).then(function (res) {
|
||||
var _a = _this.getValue(res, type), value = _a.value, moveStatus = _a.moveStatus;
|
||||
var formatValue = _this.formatValue(value);
|
||||
_this.fireChange(currentId, formatValue, moveStatus, type, e);
|
||||
});
|
||||
};
|
||||
SliderController.prototype.fireChange = function (id, value, moveStatus, type, event) {
|
||||
if (id < this.valueId) {
|
||||
return;
|
||||
}
|
||||
if (this._callback) {
|
||||
var changed = !this.isSliderValueEqual(this._value, value);
|
||||
var moveStatusChanged = this.isMoveStatusChanged(this._moveStatus, moveStatus);
|
||||
this._value = value;
|
||||
this.valueId = id;
|
||||
if (changed || moveStatusChanged) {
|
||||
this._callback(value, moveStatus, {
|
||||
valueChange: changed,
|
||||
moveStatusChange: moveStatusChanged,
|
||||
type: type,
|
||||
event: event,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
SliderController.prototype.isMoveStatusChanged = function (value1, value2) {
|
||||
if (value1 === value2) {
|
||||
return false;
|
||||
}
|
||||
if (!value1 || !value2) {
|
||||
return true;
|
||||
}
|
||||
if (value1.changingStart !== value2.changingStart) {
|
||||
return true;
|
||||
}
|
||||
if (value1.changingEnd !== value2.changingEnd) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
SliderController.prototype.isSliderValueEqual = function (value1, value2) {
|
||||
if (value1 === value2) {
|
||||
return true;
|
||||
}
|
||||
if (value1 === undefined || value2 === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (typeof value1 === 'number' || typeof value2 == 'number') {
|
||||
return value1 === value2;
|
||||
}
|
||||
if (value1[0] === value2[0] && value1[1] === value2[1]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
SliderController.prototype.getId = function () {
|
||||
var id = this.id;
|
||||
this.id = this.id + 1;
|
||||
return id;
|
||||
};
|
||||
SliderController.prototype.getRect = function (component, e) {
|
||||
return __awaiter(this, void 0, void 0, function () {
|
||||
var elementId, element, touch;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
elementId = e.currentTarget.id;
|
||||
return [4 /*yield*/, getInstanceBoundingClientRect(component, "#".concat(elementId))];
|
||||
case 1:
|
||||
element = _a.sent();
|
||||
touch = e.changedTouches[0];
|
||||
if (element) {
|
||||
return [2 /*return*/, {
|
||||
touch: {
|
||||
pageX: touch.pageX,
|
||||
},
|
||||
element: {
|
||||
left: element.left,
|
||||
width: element.width,
|
||||
},
|
||||
}];
|
||||
}
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
SliderController.prototype.fitSliderValue = function (value, min, max, isRange) {
|
||||
if (value === undefined || value === null) {
|
||||
if (isRange) {
|
||||
return [min, min];
|
||||
}
|
||||
else {
|
||||
return min !== null && min !== void 0 ? min : 0;
|
||||
}
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
if (value > max) {
|
||||
return max;
|
||||
}
|
||||
if (value < min) {
|
||||
return min;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
var leftValue = Math.min(value[0], value[1]);
|
||||
var rightValue = Math.max(value[0], value[1]);
|
||||
return [Math.max(min, leftValue), Math.min(max, rightValue)];
|
||||
};
|
||||
SliderController.prototype.getValue = function (rect, type) {
|
||||
var touchPosition = (rect.touch.pageX - rect.element.left) / rect.element.width;
|
||||
var props = this.props;
|
||||
var currentValue = this.value;
|
||||
var value = props.min + touchPosition * (props.max - props.min);
|
||||
if (!props.range) {
|
||||
return {
|
||||
value: value,
|
||||
moveStatus: type === 'end'
|
||||
? {
|
||||
changingEnd: false,
|
||||
changingStart: false,
|
||||
}
|
||||
: {
|
||||
changingEnd: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
else {
|
||||
var leftValue = currentValue[0];
|
||||
var rightValue = currentValue[1];
|
||||
var leftDistance = Math.abs(leftValue - value);
|
||||
var rightDistance = Math.abs(rightValue - value);
|
||||
var isFarFromLeft = leftDistance > rightDistance;
|
||||
var farValue = isFarFromLeft ? leftValue : rightValue;
|
||||
return {
|
||||
value: [value, farValue],
|
||||
moveStatus: type === 'end'
|
||||
? {
|
||||
changingEnd: false,
|
||||
changingStart: false,
|
||||
}
|
||||
: isFarFromLeft
|
||||
? {
|
||||
changingEnd: true,
|
||||
}
|
||||
: {
|
||||
changingStart: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
SliderController.prototype.formatValue = function (val) {
|
||||
var props = this.props;
|
||||
var value = this.fitSliderValue(val, props.min, props.max, props.range);
|
||||
value = this.getRoundedValue(value, props.step);
|
||||
return value;
|
||||
};
|
||||
SliderController.prototype.getRoundedValue = function (value, step) {
|
||||
if (step === void 0) { step = 1; }
|
||||
if (value === undefined) {
|
||||
return 0;
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
return Math.round(value / step) * step;
|
||||
}
|
||||
return [
|
||||
Math.round(value[0] / step) * step,
|
||||
Math.round(value[1] / step) * step,
|
||||
];
|
||||
};
|
||||
SliderController.prototype.updateProps = function (props) {
|
||||
this._props = props;
|
||||
};
|
||||
SliderController.prototype.updateValue = function (value) {
|
||||
this._value = value;
|
||||
};
|
||||
SliderController.prototype.updateMoveStatus = function (moveStatus) {
|
||||
this._moveStatus = moveStatus;
|
||||
};
|
||||
SliderController.prototype.onChange = function (callback) {
|
||||
this._callback = callback;
|
||||
};
|
||||
return SliderController;
|
||||
}());
|
||||
export { SliderController };
|
123
compiled/wechat/src/Slider/index.js
Normal file
123
compiled/wechat/src/Slider/index.js
Normal file
@ -0,0 +1,123 @@
|
||||
var __assign = (this && this.__assign) || function () {
|
||||
__assign = Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
import { useEvent, useMemo, useRef, useState, useComponent, } from 'functional-mini/component';
|
||||
import '../_util/assert-component2';
|
||||
import { mountComponent } from '../_util/component';
|
||||
import { useComponentEvent } from '../_util/hooks/useComponentEvent';
|
||||
import { useMixState } from '../_util/hooks/useMixState';
|
||||
import { SliderController } from './controller';
|
||||
import { sliderDefaultProps } from './props';
|
||||
var useSliderController = function (props) {
|
||||
var controllerRef = useRef();
|
||||
if (!controllerRef.current) {
|
||||
controllerRef.current = new SliderController(0, props);
|
||||
}
|
||||
return controllerRef.current;
|
||||
};
|
||||
var Slider = function (props) {
|
||||
var component = useComponent();
|
||||
var sliderController = useSliderController(props);
|
||||
var _a = useMixState(props.defaultValue, {
|
||||
value: props.value,
|
||||
postState: function (value) {
|
||||
return {
|
||||
valid: true,
|
||||
value: sliderController.formatValue(value),
|
||||
};
|
||||
},
|
||||
}), value = _a[0], _b = _a[1], update = _b.update, isControlled = _b.isControlled;
|
||||
var _c = useState({
|
||||
changingStart: false,
|
||||
changingEnd: false,
|
||||
}), moveStatus = _c[0], setMoveStatus = _c[1];
|
||||
var triggerEvent = useComponentEvent(props).triggerEvent;
|
||||
sliderController.updateProps(props);
|
||||
sliderController.updateValue(value);
|
||||
sliderController.updateMoveStatus(moveStatus);
|
||||
sliderController.onChange(function (v, moveStatus, _a) {
|
||||
var valueChange = _a.valueChange, moveStatusChange = _a.moveStatusChange, type = _a.type, event = _a.event;
|
||||
if (!isControlled) {
|
||||
update(v);
|
||||
}
|
||||
if (valueChange) {
|
||||
triggerEvent('change', v);
|
||||
}
|
||||
if (moveStatusChange) {
|
||||
setMoveStatus(function (v2) { return (__assign(__assign({}, v2), moveStatus)); });
|
||||
}
|
||||
if (value && type === 'end') {
|
||||
triggerEvent('afterChange', v, event);
|
||||
}
|
||||
});
|
||||
useEvent('handleTrackTouchStart', function (e) { return sliderController.handleMove(component, e, 'start'); }, [component]);
|
||||
useEvent('handleTrackTouchMove', function (e) { return sliderController.handleMove(component, e, 'move'); }, [component]);
|
||||
useEvent('handleTrackTouchEnd', function (e) { return sliderController.handleMove(component, e, 'end'); }, [component, props]);
|
||||
var tickList = useMemo(function () {
|
||||
var step = props.step, min = props.min, max = props.max, showTicks = props.showTicks;
|
||||
if (!showTicks) {
|
||||
return [];
|
||||
}
|
||||
var tickList = [];
|
||||
var stepCount = (max - min) / step;
|
||||
for (var i = 0; i <= stepCount; i += 1) {
|
||||
tickList.push({
|
||||
left: i * (100 / stepCount),
|
||||
value: i * step + min,
|
||||
});
|
||||
}
|
||||
return tickList;
|
||||
}, [props]);
|
||||
var _d = useMemo(function () {
|
||||
var _a, _b;
|
||||
var roundedValue = value;
|
||||
var leftValue = 0;
|
||||
var rightValue = 0;
|
||||
var max = (_a = props.max) !== null && _a !== void 0 ? _a : sliderDefaultProps.max;
|
||||
var min = (_b = props.min) !== null && _b !== void 0 ? _b : sliderDefaultProps.min;
|
||||
if (roundedValue !== undefined) {
|
||||
if (typeof roundedValue === 'number') {
|
||||
leftValue = min;
|
||||
rightValue = roundedValue;
|
||||
}
|
||||
else {
|
||||
leftValue = roundedValue[0];
|
||||
rightValue = roundedValue[1];
|
||||
}
|
||||
}
|
||||
// FIX_ME when min and max is equal
|
||||
var width = ((rightValue - leftValue) / (max - min)) * 100;
|
||||
var left = ((leftValue - min) / (max - min)) * 100;
|
||||
return {
|
||||
sliderLeft: left,
|
||||
sliderWidth: width,
|
||||
};
|
||||
}, [value]), sliderLeft = _d.sliderLeft, sliderWidth = _d.sliderWidth;
|
||||
return __assign({ mixin: {
|
||||
value: value,
|
||||
}, tickList: tickList, sliderLeft: sliderLeft, sliderWidth: sliderWidth }, moveStatus);
|
||||
};
|
||||
mountComponent(Slider, {
|
||||
value: null,
|
||||
defaultValue: null,
|
||||
disabled: false,
|
||||
max: 100,
|
||||
min: 0,
|
||||
range: false,
|
||||
showNumber: false,
|
||||
step: 1,
|
||||
showTicks: false,
|
||||
showTooltip: false,
|
||||
activeLineStyle: '',
|
||||
activeDotStyle: '',
|
||||
activeLineClassName: '',
|
||||
activeDotClassName: '',
|
||||
});
|
6
compiled/wechat/src/Slider/index.json
Normal file
6
compiled/wechat/src/Slider/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"popover": "../Popover/index"
|
||||
}
|
||||
}
|
45
compiled/wechat/src/Slider/index.md
Normal file
45
compiled/wechat/src/Slider/index.md
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
nav:
|
||||
path: /components
|
||||
group:
|
||||
title: 信息输入
|
||||
toc: 'content'
|
||||
---
|
||||
|
||||
# Slider 滑块
|
||||
|
||||
<code src="../../docs/components/compatibility.tsx" inline="true"></code>
|
||||
|
||||
可以通过移动滑块在某一范围内取值
|
||||
|
||||
## 何时使用
|
||||
用于在一定范围内移动滑块获取单个或者区间数值
|
||||
|
||||
## 代码示例
|
||||
<code src='pages/Slider/index'></code>
|
||||
|
||||
## API
|
||||
| 属性 | 说明 | 类型 | 默认值 |
|
||||
| -----|-----|-----|----- |
|
||||
| activeDotClassName | 选中小圆点的类名 | string | - |
|
||||
| activeLineClassName | 选中线条的样式 | string | - |
|
||||
| activeDotStyle | 选中小圆点的类型 | string | - |
|
||||
| activeLineStyle | 选中线条的样式 | string | - |
|
||||
| className | 类名 | string | - |
|
||||
| defaultValue | 初始值 | number \| [number, number] | - |
|
||||
| disabled | 是否禁用 | boolean | false |
|
||||
| max | 最大值 | number | 100 |
|
||||
| min | 最小值 | number | 0 |
|
||||
| range | 是否是双滑块 | boolean | false |
|
||||
| showNumber | 是否展示刻度上的数据 | boolean | false |
|
||||
| step | 步距,取值必须大于 0,并且可被 (max - min) 整除 | number | 1 |
|
||||
| style | 样式 | string | - |
|
||||
| showTicks | 是否显示刻度 | boolean | false |
|
||||
| showTooltip | 是否在拖动时显示悬浮提示,支持使用作用域插槽自定义 | boolean | false |
|
||||
| slider | 自定义滑块 | slot | - |
|
||||
| tick | 自定义刻度 | slot | - |
|
||||
| tooltip | 自定义拖动时显示悬浮提示 | slot | - |
|
||||
| value | 当前值 | number \| [number, number] | - |
|
||||
| onChange | slider 值改变时触发 | (value: number | [number, number]) => void | - |
|
||||
| onAfterChange | 与 touchend 触发时机一致,把当前值作为参数传入 | (value: number | [number, number]) => void | - |
|
||||
|
72
compiled/wechat/src/Slider/index.wxml
Normal file
72
compiled/wechat/src/Slider/index.wxml
Normal file
@ -0,0 +1,72 @@
|
||||
<wxs
|
||||
src="./index.wxs"
|
||||
module="sliderSjs" />
|
||||
|
||||
<template name="slider-handler">
|
||||
<view
|
||||
class="ant-slider-handler"
|
||||
style="left: {{ position }}%">
|
||||
<popover
|
||||
placement="top"
|
||||
visible="{{ showTooltip }}"
|
||||
showMask="{{ false }}">
|
||||
<view class="ant-slider-handler-block">
|
||||
<view class="ant-slider-handler-icon-default">
|
||||
<view class="ant-slider-handler-icon-default-line1" />
|
||||
<view class="ant-slider-handler-icon-default-line2" />
|
||||
<view class="ant-slider-handler-icon-default-line3" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
slot="content"
|
||||
class="ant-slider-tooltip-content">
|
||||
{{ value }}
|
||||
</view>
|
||||
</popover>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<view
|
||||
class="ant-slider {{ className ? className : '' }}"
|
||||
style="opacity: {{ disabled ? '0.4' : '1' }};">
|
||||
<view
|
||||
class="ant-slider-track {{ showNumber ? 'ant-slider-track-number' : '' }}">
|
||||
<view
|
||||
class="ant-slider-track-touch-area"
|
||||
id="ant-slider-id-{{ $id }}"
|
||||
bind:touchstart="handleTrackTouchStart"
|
||||
bind:touchend="handleTrackTouchEnd"
|
||||
bind:touchmove="handleTrackTouchMove">
|
||||
<view class="ant-slider-track-fill">
|
||||
<view class="ant-slider-track-fill-background" />
|
||||
<view
|
||||
class="ant-slider-track-fill-front {{ activeLineClassName || '' }}"
|
||||
style="width: {{ sliderWidth }}%; left: {{ sliderLeft }}%; {{ activeLineStyle || '' }}" />
|
||||
<view class="ant-slider-showTicks">
|
||||
<block
|
||||
wx:for="{{ tickList }}"
|
||||
wx:for-index="index"
|
||||
wx:for-item="item">
|
||||
<view
|
||||
class="ant-slider-tick ant-slider-tick-{{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) ? 'front' : 'back' }} {{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) && activeDotClassName ? activeDotClassName : '' }}"
|
||||
style="left: {{ item.left }}%;{{ sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) && activeDotStyle ? activeDotStyle : '' }}">
|
||||
<view
|
||||
wx:if="{{ showNumber }}"
|
||||
class="ant-slider-tick-number">
|
||||
{{ item.value }}
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<template
|
||||
wx:if="{{ range }}"
|
||||
is="slider-handler"
|
||||
data="{{ position: sliderLeft, icon: icon, value: mixin.value[0], showTooltip: changingStart && showTooltip }}" />
|
||||
<template
|
||||
is="slider-handler"
|
||||
data="{{ position: sliderLeft + sliderWidth, icon: icon, value: range ? mixin.value[1] : mixin.value, showTooltip: changingEnd && showTooltip }}" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view />
|
||||
</view>
|
6
compiled/wechat/src/Slider/index.wxs
Normal file
6
compiled/wechat/src/Slider/index.wxs
Normal file
@ -0,0 +1,6 @@
|
||||
var isFrontTick = function isFrontTick(item, sliderLeft, sliderWidth) {
|
||||
return item.left >= sliderLeft && item.left <= sliderLeft + sliderWidth;
|
||||
};
|
||||
module.exports = {
|
||||
isFrontTick: isFrontTick
|
||||
};
|
131
compiled/wechat/src/Slider/index.wxss
Normal file
131
compiled/wechat/src/Slider/index.wxss
Normal file
@ -0,0 +1,131 @@
|
||||
.ant-slider {
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
}
|
||||
.ant-slider-track {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.ant-slider-track-number {
|
||||
height: 48.5px;
|
||||
}
|
||||
.ant-slider-track-touch-area {
|
||||
position: absolute;
|
||||
left: 14px;
|
||||
top: 0px;
|
||||
right: 12.5px;
|
||||
height: 100%;
|
||||
}
|
||||
.ant-slider-track-fill {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 12.5px;
|
||||
right: 0px;
|
||||
height: 3px;
|
||||
}
|
||||
.ant-slider-track-fill-background {
|
||||
position: absolute;
|
||||
background-color: #f5f5f5;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 1.5px;
|
||||
}
|
||||
.ant-slider-track-fill-front {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
border-radius: 1.5px;
|
||||
background-color: #1677ff;
|
||||
}
|
||||
.ant-slider-handler {
|
||||
position: absolute;
|
||||
touch-action: none;
|
||||
left: 0;
|
||||
transform: translate(-50%, -50%);
|
||||
top: 1.5px;
|
||||
}
|
||||
.ant-slider-handler-block {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
border-radius: 28px;
|
||||
text-align: center;
|
||||
line-height: 28px;
|
||||
color: #1677ff;
|
||||
}
|
||||
.ant-slider-handler-icon-default {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.ant-slider-handler-icon-default-line1 {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 8px;
|
||||
background-color: #1677ff;
|
||||
border-radius: 1px;
|
||||
top: 10px;
|
||||
left: 8px;
|
||||
}
|
||||
.ant-slider-handler-icon-default-line2 {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 12px;
|
||||
background-color: #1677ff;
|
||||
border-radius: 1px;
|
||||
top: 8px;
|
||||
right: 13px;
|
||||
}
|
||||
.ant-slider-handler-icon-default-line3 {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 8px;
|
||||
background-color: #1677ff;
|
||||
border-radius: 1px;
|
||||
top: 10px;
|
||||
right: 8px;
|
||||
}
|
||||
.ant-slider-handler-icon-from-props {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
text-align: center;
|
||||
line-height: 100%;
|
||||
}
|
||||
.ant-slider-handler-icon-from-props-icon {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.ant-slider-tick {
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 8px;
|
||||
top: 1.5px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.ant-slider-tick-front {
|
||||
background-color: #1677ff;
|
||||
}
|
||||
.ant-slider-tick-back {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.ant-slider-tick-number {
|
||||
position: absolute;
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
transform: translateX(-50%);
|
||||
top: 22px;
|
||||
left: 4px;
|
||||
text-align: center;
|
||||
line-height: 16.5px;
|
||||
height: 16.5px;
|
||||
}
|
5
compiled/wechat/src/Slider/props.js
Normal file
5
compiled/wechat/src/Slider/props.js
Normal file
@ -0,0 +1,5 @@
|
||||
export var sliderDefaultProps = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
step: 1,
|
||||
};
|
0
compiled/wechat/src/Slider/variable.wxss
Normal file
0
compiled/wechat/src/Slider/variable.wxss
Normal file
@ -1,5 +1,6 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/Slider",
|
||||
"pages/Container",
|
||||
"pages/Stepper",
|
||||
"pages/Button",
|
||||
@ -23,6 +24,7 @@
|
||||
"src": [
|
||||
"_util",
|
||||
"Button",
|
||||
"Slider",
|
||||
"Container",
|
||||
"Icon",
|
||||
"Loading",
|
||||
|
@ -1,13 +1,13 @@
|
||||
import Slider from '../../../src/Slider/index.axml';
|
||||
import Icon from '../../../src/Icon/index.axml';
|
||||
import Stepper from '../../../src/Stepper/index.axml';
|
||||
import { Component, InternalData, Text, View } from 'tsxml';
|
||||
import Container from '../../../src/Container/index.axml';
|
||||
import { View, Component, Slot, InternalData, Text } from 'tsxml';
|
||||
import AntIcon from '../../../src/Icon/index.axml';
|
||||
import AntSlider from '../../../src/Slider/index.axml';
|
||||
import AntStepper from '../../../src/Stepper/index.axml';
|
||||
|
||||
export default ({ value, props }: InternalData) => (
|
||||
<Component>
|
||||
<Container title="基本使用">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={80}
|
||||
onChange="onChange"
|
||||
onAfterChange="onAfterChange"
|
||||
@ -15,7 +15,7 @@ export default ({ value, props }: InternalData) => (
|
||||
</Container>
|
||||
|
||||
<Container title="无节点双滑块">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={[20, 60]}
|
||||
range
|
||||
onChange="onChange"
|
||||
@ -24,7 +24,7 @@ export default ({ value, props }: InternalData) => (
|
||||
</Container>
|
||||
|
||||
<Container title="节点单滑块">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={60}
|
||||
step={20}
|
||||
showTicks
|
||||
@ -34,7 +34,7 @@ export default ({ value, props }: InternalData) => (
|
||||
</Container>
|
||||
|
||||
<Container title="有数字节点单滑块">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={80}
|
||||
step={20}
|
||||
showTicks
|
||||
@ -45,7 +45,7 @@ export default ({ value, props }: InternalData) => (
|
||||
</Container>
|
||||
|
||||
<Container title="节点双滑块">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={[10, 50]}
|
||||
step={10}
|
||||
showTicks
|
||||
@ -56,7 +56,7 @@ export default ({ value, props }: InternalData) => (
|
||||
</Container>
|
||||
|
||||
<Container title="有数字节点双滑块">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={[10, 50]}
|
||||
step={10}
|
||||
showTicks
|
||||
@ -68,7 +68,7 @@ export default ({ value, props }: InternalData) => (
|
||||
</Container>
|
||||
|
||||
<Container title="在拖动时显示悬浮提示">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={80}
|
||||
showTooltip
|
||||
onChange="onChange"
|
||||
@ -77,12 +77,12 @@ export default ({ value, props }: InternalData) => (
|
||||
</Container>
|
||||
|
||||
<Container title="受控模式">
|
||||
<Slider min={0} max={100} value={value} onChange="handleChange" />
|
||||
<Stepper min={0} max={100} value={value} onChange="handleChange" />
|
||||
<AntSlider min={0} max={100} value={value} onChange="handleChange" />
|
||||
<AntStepper min={0} max={100} value={value} onChange="handleChange" />
|
||||
</Container>
|
||||
|
||||
<Container title="自定义">
|
||||
<Slider
|
||||
<AntSlider
|
||||
defaultValue={80}
|
||||
step={20}
|
||||
showTooltip
|
||||
@ -93,23 +93,26 @@ export default ({ value, props }: InternalData) => (
|
||||
onChange="onChange"
|
||||
onAfterChange="onAfterChange"
|
||||
>
|
||||
{/* #if ALIPAY */}
|
||||
{/* 微信暂时不支持 slot */}
|
||||
<Text slot="tick" slot-scope="props">
|
||||
{props.value}
|
||||
{props.value}°C
|
||||
</Text>
|
||||
<Text slot="showTooltip" slot-scope="props">
|
||||
{props.value}
|
||||
<Text slot="tooltip" slot-scope="props">
|
||||
{props.value}°C
|
||||
</Text>
|
||||
|
||||
<View slot="slider">
|
||||
<View class="custom-slider-handler">
|
||||
<Icon type="SmileOutline" style="color: #ff8f1f" />
|
||||
<AntIcon type="SmileOutline" style="color: #ff8f1f" />
|
||||
</View>
|
||||
</View>
|
||||
</Slider>
|
||||
{/* #endif */}
|
||||
</AntSlider>
|
||||
</Container>
|
||||
|
||||
<Container title="禁用状态">
|
||||
<Slider defaultValue={80} disabled onChange="onChange" />
|
||||
<AntSlider defaultValue={80} disabled onChange="onChange" />
|
||||
</Container>
|
||||
</Component>
|
||||
);
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"defaultTitle": "Slider",
|
||||
"usingComponents": {
|
||||
"slider": "../../../src/Slider/index",
|
||||
"icon": "../../../src/Icon/index",
|
||||
"stepper": "../../../src/Stepper/index",
|
||||
"ant-slider": "../../../src/Slider/index",
|
||||
"ant-icon": "../../../src/Icon/index",
|
||||
"ant-stepper": "../../../src/Stepper/index",
|
||||
"container": "../../../src/Container/index"
|
||||
}
|
||||
}
|
||||
|
@ -3,18 +3,37 @@ Page({
|
||||
value: 80,
|
||||
},
|
||||
onChange(value, e) {
|
||||
console.log('slider changed:', value, e)
|
||||
console.log('slider changed:', value, e);
|
||||
},
|
||||
onAfterChange(value, e) {
|
||||
console.log('当前值:', value, e);
|
||||
/// #if ALIPAY
|
||||
my.showToast({
|
||||
content: `当前选中值为:${value}`
|
||||
content: 'value: ' + value,
|
||||
});
|
||||
/// #endif
|
||||
|
||||
/// #if WECHAT
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
wx.showToast({
|
||||
title: `value: ${value.detail}`,
|
||||
});
|
||||
/// #endif
|
||||
},
|
||||
handleChange(value, e) {
|
||||
console.log('slider changed:', value, e)
|
||||
console.log('slider changed:', value, e);
|
||||
|
||||
/// #if WECHAT
|
||||
this.setData({
|
||||
value: value.detail,
|
||||
});
|
||||
/// #endif
|
||||
|
||||
/// #if ALIPAY
|
||||
this.setData({
|
||||
value,
|
||||
});
|
||||
}
|
||||
/// #endif
|
||||
},
|
||||
});
|
||||
|
@ -40,6 +40,11 @@ export const wechat: PlatformConfig = {
|
||||
onScroll: 'bind:scroll',
|
||||
},
|
||||
props: {
|
||||
view: {
|
||||
onTouchStart: 'bind:touchstart',
|
||||
onTouchMove: 'bind:touchmove',
|
||||
onTouchEnd: 'bind:touchend',
|
||||
},
|
||||
input: {
|
||||
onInput: 'bindinput',
|
||||
onConfirm: 'bindconfirm',
|
||||
@ -57,6 +62,9 @@ export const wechat: PlatformConfig = {
|
||||
'ant-textarea': {
|
||||
onChange: 'bind:change',
|
||||
},
|
||||
'ant-slider': {
|
||||
onAfterChange: 'bind:afterchange',
|
||||
},
|
||||
'ant-input': {
|
||||
onBlur: 'bind:blur',
|
||||
onConfirm: 'bind:confirm',
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect';
|
||||
import { ISliderProps, SliderValue } from './props';
|
||||
|
||||
interface Rect {
|
||||
@ -33,12 +34,12 @@ export class SliderController {
|
||||
|
||||
constructor(private _value: SliderValue, private _props: ISliderProps) {}
|
||||
|
||||
handleMove(e, type: MoveType) {
|
||||
handleMove(component: any, e, type: MoveType) {
|
||||
if (this.props.disabled) {
|
||||
return;
|
||||
}
|
||||
const currentId = this.getId();
|
||||
this.getRect(e).then((res) => {
|
||||
this.getRect(component, e).then((res) => {
|
||||
const { value, moveStatus } = this.getValue(res, type);
|
||||
const formatValue = this.formatValue(value);
|
||||
this.fireChange(currentId, formatValue, moveStatus, type, e);
|
||||
@ -116,28 +117,24 @@ export class SliderController {
|
||||
return id;
|
||||
}
|
||||
|
||||
private getRect(e): Promise<any> {
|
||||
private async getRect(component: any, e: any): Promise<any> {
|
||||
const elementId = e.currentTarget.id;
|
||||
return new Promise((r) => {
|
||||
my.createSelectorQuery()
|
||||
.select(`#${elementId}`)
|
||||
.boundingClientRect()
|
||||
.exec((list) => {
|
||||
const element = list[0];
|
||||
const touch = e.changedTouches[0];
|
||||
if (element) {
|
||||
return r({
|
||||
touch: {
|
||||
pageX: touch.pageX,
|
||||
},
|
||||
element: {
|
||||
left: element.left,
|
||||
width: element.width,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
const element = await getInstanceBoundingClientRect(
|
||||
component,
|
||||
`#${elementId}`
|
||||
);
|
||||
const touch = e.changedTouches[0];
|
||||
if (element) {
|
||||
return {
|
||||
touch: {
|
||||
pageX: touch.pageX,
|
||||
},
|
||||
element: {
|
||||
left: element.left,
|
||||
width: element.width,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fitSliderValue(
|
||||
@ -146,7 +143,7 @@ export class SliderController {
|
||||
max: number,
|
||||
isRange: boolean
|
||||
) {
|
||||
if (value === undefined) {
|
||||
if (value === undefined || value === null) {
|
||||
if (isRange) {
|
||||
return [min, min] as SliderValue;
|
||||
} else {
|
||||
|
@ -45,11 +45,14 @@ export default (
|
||||
{/* #if ALIPAY */}
|
||||
</Slot>
|
||||
{/* #endif */}
|
||||
|
||||
<View slot="content" class="ant-slider-tooltip-content">
|
||||
{/* #if ALIPAY */}
|
||||
<Slot name="tooltip" value={value}>
|
||||
{/* #endif */}
|
||||
{value}
|
||||
{/* #if ALIPAY */}
|
||||
</Slot>
|
||||
{/* #endif */}
|
||||
</View>
|
||||
</Popover>
|
||||
</View>
|
||||
@ -78,62 +81,66 @@ export default (
|
||||
style={`width: ${sliderWidth}%; left: ${sliderLeft}%; ${
|
||||
activeLineStyle || ''
|
||||
}`}
|
||||
>
|
||||
<View class="ant-slider-showTicks">
|
||||
{tickList.map((item) => (
|
||||
<View
|
||||
class={`ant-slider-tick ant-slider-tick-${
|
||||
sliderSjs.isFrontTick(item, sliderLeft, sliderWidth)
|
||||
? 'front'
|
||||
: 'back'
|
||||
} ${
|
||||
sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) &&
|
||||
activeDotClassName
|
||||
? activeDotClassName
|
||||
: ''
|
||||
}`}
|
||||
style={`left: ${item.left}%;${
|
||||
sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) &&
|
||||
activeDotStyle
|
||||
? activeDotStyle
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{showNumber && (
|
||||
<View class="ant-slider-tick-number">
|
||||
<Slot name="tick" value={item.value}>
|
||||
{item.value}
|
||||
</Slot>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
/>
|
||||
<View class="ant-slider-showTicks">
|
||||
{tickList.map((item) => (
|
||||
<View
|
||||
class={`ant-slider-tick ant-slider-tick-${
|
||||
sliderSjs.isFrontTick(item, sliderLeft, sliderWidth)
|
||||
? 'front'
|
||||
: 'back'
|
||||
} ${
|
||||
sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) &&
|
||||
activeDotClassName
|
||||
? activeDotClassName
|
||||
: ''
|
||||
}`}
|
||||
style={`left: ${item.left}%;${
|
||||
sliderSjs.isFrontTick(item, sliderLeft, sliderWidth) &&
|
||||
activeDotStyle
|
||||
? activeDotStyle
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{showNumber && (
|
||||
<View class="ant-slider-tick-number">
|
||||
{/* #if ALIPAY */}
|
||||
<Slot name="tick" value={item.value}>
|
||||
{/* #endif */}
|
||||
|
||||
{range && (
|
||||
<Template
|
||||
is="slider-handler"
|
||||
data={{
|
||||
position: sliderLeft,
|
||||
icon: icon,
|
||||
value: mixin.value[0],
|
||||
showTooltip: changingStart && showTooltip,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{item.value}
|
||||
{/* #if ALIPAY */}
|
||||
</Slot>
|
||||
{/* #endif */}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
{range && (
|
||||
<Template
|
||||
is="slider-handler"
|
||||
data={{
|
||||
position: sliderLeft + sliderWidth,
|
||||
position: sliderLeft,
|
||||
icon: icon,
|
||||
value: range ? mixin.value[1] : mixin.value,
|
||||
showTooltip: changingEnd && showTooltip,
|
||||
value: mixin.value[0],
|
||||
showTooltip: changingStart && showTooltip,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
<Template
|
||||
is="slider-handler"
|
||||
data={{
|
||||
position: sliderLeft + sliderWidth,
|
||||
icon: icon,
|
||||
value: range ? mixin.value[1] : mixin.value,
|
||||
showTooltip: changingEnd && showTooltip,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View></View>
|
||||
</View>
|
||||
</Component>
|
||||
);
|
||||
|
@ -1,4 +1,10 @@
|
||||
import { useEvent, useMemo, useRef, useState } from 'functional-mini/component';
|
||||
import {
|
||||
useEvent,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
useComponent,
|
||||
} from 'functional-mini/component';
|
||||
import '../_util/assert-component2';
|
||||
import { mountComponent } from '../_util/component';
|
||||
import { useComponentEvent } from '../_util/hooks/useComponentEvent';
|
||||
@ -15,6 +21,7 @@ const useSliderController = (props: ISliderProps) => {
|
||||
};
|
||||
|
||||
const Slider = (props) => {
|
||||
const component = useComponent();
|
||||
const sliderController: SliderController = useSliderController(props);
|
||||
const [value, { update, isControlled }] = useMixState(props.defaultValue, {
|
||||
value: props.value,
|
||||
@ -55,18 +62,18 @@ const Slider = (props) => {
|
||||
|
||||
useEvent(
|
||||
'handleTrackTouchStart',
|
||||
(e) => sliderController.handleMove(e, 'start'),
|
||||
[props]
|
||||
(e) => sliderController.handleMove(component, e, 'start'),
|
||||
[component]
|
||||
);
|
||||
useEvent(
|
||||
'handleTrackTouchMove',
|
||||
(e) => sliderController.handleMove(e, 'move'),
|
||||
[props]
|
||||
(e) => sliderController.handleMove(component, e, 'move'),
|
||||
[component]
|
||||
);
|
||||
useEvent(
|
||||
'handleTrackTouchEnd',
|
||||
(e) => sliderController.handleMove(e, 'end'),
|
||||
[props]
|
||||
(e) => sliderController.handleMove(component, e, 'end'),
|
||||
[component, props]
|
||||
);
|
||||
|
||||
const tickList = useMemo(() => {
|
||||
@ -126,7 +133,18 @@ const Slider = (props) => {
|
||||
};
|
||||
|
||||
mountComponent(Slider, {
|
||||
min: 0,
|
||||
value: null,
|
||||
defaultValue: null,
|
||||
disabled: false,
|
||||
max: 100,
|
||||
min: 0,
|
||||
range: false,
|
||||
showNumber: false,
|
||||
step: 1,
|
||||
showTicks: false,
|
||||
showTooltip: false,
|
||||
activeLineStyle: '',
|
||||
activeDotStyle: '',
|
||||
activeLineClassName: '',
|
||||
activeDotClassName: '',
|
||||
});
|
||||
|
@ -5,12 +5,14 @@ import os from 'os';
|
||||
import path from 'path';
|
||||
import shallowequal from 'shallowequal';
|
||||
import vm from 'vm';
|
||||
import { SelectorQuery } from './selector-query';
|
||||
|
||||
interface Instance {
|
||||
$id: number;
|
||||
props: Record<string, any>;
|
||||
data: Record<string, any>;
|
||||
methods: Record<string, (this: Instance, ...args: any) => void>;
|
||||
createSelectorQuery: () => SelectorQuery;
|
||||
setData: (
|
||||
data: Record<string, any>,
|
||||
callback?: (this: Instance) => void
|
||||
@ -63,6 +65,7 @@ function createInstance(config: Instance, props: Record<string, any>, my: any) {
|
||||
methods: {
|
||||
...config.methods,
|
||||
},
|
||||
createSelectorQuery: my.createSelectorQuery,
|
||||
setData(data: Record<string, any>, callback: (this: Instance) => void) {
|
||||
if (shallowequal(data, instance.data)) {
|
||||
return;
|
||||
|
@ -17,6 +17,12 @@
|
||||
"tsxml": ["./src/tsxml/index.tsx"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*", "typings/**/*", "demo/**/*", "tests/**/*"],
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"./typings/**/*",
|
||||
"demo/**/*",
|
||||
"tests/**/*",
|
||||
"demo/wechat.d.ts"
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user