@tarojs/components
Version:
198 lines (193 loc) • 7.09 kB
JavaScript
import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
const indexCss = ".weui-slider{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:15px 18px}.weui-slider__inner{background-color:#e9e9e9;height:2px;position:relative}.weui-slider__track{background-color:#1aad19;width:0;height:2px}.weui-slider__handler{background-color:#fff;border-radius:50%;width:28px;height:28px;margin-top:-14px;margin-left:-14px;position:absolute;top:50%;left:0;-webkit-box-shadow:0 0 4px rgba(0,0,0,.2);box-shadow:0 0 4px rgba(0,0,0,.2)}.weui-slider-box{-ms-flex-align:center;align-items:center;display:-ms-flexbox;display:flex}.weui-slider-box .weui-slider{-ms-flex:1;flex:1}.weui-slider-box__value{color:#888;text-align:center;min-width:24px;margin-left:.5em;font-size:14px}";
const Slider = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
constructor() {
super();
this.__registerHost();
this.onChange = createEvent(this, "change", 7);
this.onChanging = createEvent(this, "changing", 7);
this.handleTouchStart = (e) => {
if (this.touching || this.disabled)
return;
this.touching = true;
this.touchId = e.targetTouches[0].identifier;
this.totalWidth = this.sliderInsRef.clientWidth || 1;
this.ogX = e.targetTouches[0].pageX;
this.ogPercent = this.percent;
};
this.handleTouchMove = (e) => {
const { disabled, touching, touchId, totalWidth, max, min, ogX, ogPercent } = this;
if (!touching || disabled)
return;
if (e.targetTouches[0].identifier !== touchId)
return;
// 阻止默认事件
e.preventDefault();
const pageX = e.targetTouches[0].pageX;
const diffX = pageX - ogX;
let percent = diffX / totalWidth * 100 + ogPercent;
percent = this.handleValueUpdate(percent, 0, 100);
const val = min + percent * 0.01 * (max - min);
this.updateByStep(val);
this.onChanging.emit({
detail: e.detail,
value: this.value
});
};
this.handleTouchEnd = (e) => {
const { disabled, touching } = this;
if (!touching || disabled)
return;
if (this.percent !== this.ogPercent) {
this.onChange.emit({
detail: e.detail,
value: this.value
});
}
this.touching = false;
this.touchId = null;
this.ogX = 0;
this.ogPercent = 0;
};
this.handleValueUpdate = (e, min = this.min, max = this.max) => {
e = isNaN(e) ? 0 : e;
return Math.max(min, Math.min(e, max));
};
this.min = 0;
this.max = 100;
this.step = 1;
this.disabled = false;
this.value = 0;
this.activeColor = '#1aad19';
this.backgroundColor = '#e9e9e9';
this.blockSize = 28;
this.blockColor = '#ffffff';
this.showValue = false;
this.name = '';
this.totalWidth = 1;
this.touching = false;
this.ogX = 0;
this.touchId = null;
this.percent = 0;
this.ogPercent = undefined;
this.isWillLoadCalled = false;
}
function(value) {
if (!this.isWillLoadCalled)
return;
const { max, min } = this;
if (value !== null) {
const val = this.handleValueUpdate(value, min, max);
this.updateByStep(val);
}
}
componentDidLoad() {
// 在自动化测试时,如果通过 JSX 绑定 touch 事件,
// 模拟的 touch 事件只会在浏览器的 device mode 下触发,Karma 跑的测试就会跪。
// 因此改为 didLoad 后 addEventListener 的形式。
this.handler.addEventListener('touchstart', this.handleTouchStart);
this.handler.addEventListener('touchmove', this.handleTouchMove);
this.handler.addEventListener('touchend', this.handleTouchEnd);
}
componentWillLoad() {
this.isWillLoadCalled = true;
const { value, max, min } = this;
const val = this.handleValueUpdate(value, min, max);
this.updateByStep(val);
}
// 根据步长 step 修改 value
updateByStep(value) {
const { max, min, step } = this;
const steps = Math.floor((max - min) / step);
for (let i = 0; i <= steps; i++) {
const current = min + step * i;
const next = i === steps ? null : min + step * (i + 1);
if (value === current)
break;
if (!next && value > current) {
// step 不能被 max - min 整除
value = current;
}
if (next && value > current && value < next) {
if (value - current < step / 2) {
value = current;
}
else {
value = next;
}
break;
}
}
const percent = (value - min) / (max - min) * 100;
this.value = value;
this.percent = percent;
}
render() {
const { showValue, backgroundColor, activeColor, blockColor, name, percent, value } = this;
let blockSize = this.blockSize;
const innerStyles = { backgroundColor };
const percentage = percent > 100 ? 100 : percent;
const trackStyles = {
width: `${percentage}%`,
backgroundColor: activeColor
};
if (blockSize < 12) {
blockSize = 12;
}
if (blockSize > 28) {
blockSize = 28;
}
const handlerStyles = {
left: `${percentage}%`,
width: `${blockSize}px`,
height: `${blockSize}px`,
backgroundColor: blockColor,
marginTop: `-${Math.floor(blockSize / 2)}px`,
marginLeft: `-${Math.floor(blockSize / 2)}px`
};
return (h(Host, { class: 'weui-slider-box' }, h("div", { class: 'weui-slider' }, h("div", { class: 'weui-slider__inner', style: innerStyles, ref: c => (this.sliderInsRef = c) }, h("div", { style: trackStyles, class: 'weui-slider__track' }), h("div", { class: 'weui-slider__handler', ref: dom => {
if (dom)
this.handler = dom;
}, style: handlerStyles }), h("input", { type: 'hidden', name: name, value: value }))), showValue && h("div", { class: 'weui-slider-box__value' }, value)));
}
get el() { return this; }
static get watchers() { return {
"value": ["function"]
}; }
static get style() { return indexCss; }
}, [0, "taro-slider-core", {
"min": [2],
"max": [2],
"step": [2],
"disabled": [4],
"value": [1538],
"activeColor": [1, "active-color"],
"backgroundColor": [1, "background-color"],
"blockSize": [2, "block-size"],
"blockColor": [1, "block-color"],
"showValue": [4, "show-value"],
"name": [1],
"totalWidth": [32],
"touching": [32],
"ogX": [32],
"touchId": [32],
"percent": [32],
"ogPercent": [32],
"isWillLoadCalled": [32]
}]);
function defineCustomElement$1() {
if (typeof customElements === "undefined") {
return;
}
const components = ["taro-slider-core"];
components.forEach(tagName => { switch (tagName) {
case "taro-slider-core":
if (!customElements.get(tagName)) {
customElements.define(tagName, Slider);
}
break;
} });
}
const TaroSliderCore = Slider;
const defineCustomElement = defineCustomElement$1;
export { TaroSliderCore, defineCustomElement };