UNPKG

@tarojs/components

Version:
162 lines (158 loc) 6.11 kB
import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-ab3c86da.js'; 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 = class { constructor(hostRef) { registerInstance(this, hostRef); 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 getElement(this); } static get watchers() { return { "value": ["function"] }; } }; Slider.style = indexCss; export { Slider as taro_slider_core };