UNPKG

@tarojs/components

Version:
413 lines (412 loc) 11 kB
import { h, Host } from '@stencil/core'; export class Slider { constructor() { 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))); } static get is() { return "taro-slider-core"; } static get originalStyleUrls() { return { "$": ["./style/index.scss"] }; } static get styleUrls() { return { "$": ["./style/index.css"] }; } static get properties() { return { "min": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "min", "reflect": false, "defaultValue": "0" }, "max": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "max", "reflect": false, "defaultValue": "100" }, "step": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "step", "reflect": false, "defaultValue": "1" }, "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "disabled", "reflect": false, "defaultValue": "false" }, "value": { "type": "number", "mutable": true, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "value", "reflect": true, "defaultValue": "0" }, "activeColor": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "active-color", "reflect": false, "defaultValue": "'#1aad19'" }, "backgroundColor": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "background-color", "reflect": false, "defaultValue": "'#e9e9e9'" }, "blockSize": { "type": "number", "mutable": false, "complexType": { "original": "number", "resolved": "number", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "block-size", "reflect": false, "defaultValue": "28" }, "blockColor": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "block-color", "reflect": false, "defaultValue": "'#ffffff'" }, "showValue": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "show-value", "reflect": false, "defaultValue": "false" }, "name": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "name", "reflect": false, "defaultValue": "''" } }; } static get states() { return { "totalWidth": {}, "touching": {}, "ogX": {}, "touchId": {}, "percent": {}, "ogPercent": {}, "isWillLoadCalled": {} }; } static get events() { return [{ "method": "onChange", "name": "change", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }, { "method": "onChanging", "name": "changing", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }]; } static get elementRef() { return "el"; } static get watchers() { return [{ "propName": "value", "methodName": "function" }]; } }