// components/form-ruler/form-ruler.ts type Axis = { value: number; type?: 'integer' | 'median' | 'tick'; }[] const prefix = 't-' as const; const createAxis = (min = 0, max = 10, precision = 0.1) => { // const length = precision.toString().match(/\d+(?:\.(\d*))/)?.[1]?.length ?? 0 // 计算精度的倒数(即1除以精度),然后乘以10的幂来得到一个整数 const scale = Math.pow(10, Math.ceil(Math.log10(1 / precision))); const _min = min * scale; const _max = Math.floor(max * scale); const _precision = precision * scale; const ticks: Axis = []; let current = _min; while (current < _max + _precision) { ticks.push({ value: current / scale, type: Math.floor(current) % 10 ? Math.floor(current) % 5 ? 'tick' : 'median' : 'integer', }); current += _precision; } return ticks; } Component({ options: { multipleSlots: true, }, properties: { value: { type: String, value: '' }, min: { type: Number, value: 0 }, max: { type: Number, value: 1 }, precision: { type: Number, value: 0.1 }, defaultValue: { type: Number, value: Number.NaN }, line: { type: Array, value: [] }, }, observers: { 'precision'(precision: number) { const scale = Math.pow(10, Math.ceil(Math.log10(1 / precision))); this.setData({ scale }); }, 'min, max, precision'(...args: [number, number, number]) { this._updateAxis(args); }, 'defaultValue, min, max, precision, line'(value, min, max, precision, line) { const offset = precision >= 1 ? precision : 0 if (!value || Number.isNaN(+value)) { if (Array.isArray(line)) { min = line[0]?.value ?? min; max = line[1]?.value ?? max; } value = Math.floor((max - min - offset) / 2 + min) } this._scrollValue(value); } }, lifetimes: { attached() { this._updateRect(); }, }, data: { prefix, initialValue: '', scale: 0, axis: [] as Axis, rect: { width: 0, height: 0, gap: 5 } }, /** * 组件的方法列表 */ methods: { _updateAxis(params: [number, number, number]) { const axis = createAxis.apply(null, params); this.setData({ axis }) }, _updateRect() { this.createSelectorQuery() .select('.form-ruler') .boundingClientRect() .exec(res => { const rect = res[0] as WechatMiniprogram.BoundingClientRectResult; const width = rect.width - 2; const height = rect.height - 2; this.setData({ 'rect.width': width, 'rect.height': height, }); }) }, _updateValue(index?: number) { const value = this.data.axis[index ?? 0]?.value this.setData({ value: value.toFixed(Math.log10(this.data.scale)) }) }, _scrollValue(value: number | string) { const index = this.data.axis.findIndex(item => item.value === value); clearTimeout((this as any).lock); (this as any).lock = setTimeout(() => { this.setData({ initialValue: `${prefix}${index}` }); }, 300); }, onScrollUpdate(event: WechatMiniprogram.ScrollViewScroll) { const left = event.detail.scrollLeft; if (left >= 0) { this._updateValue(Math.floor(left / this.data.rect.gap)); } }, onScrollEnd() { this._scrollValue(this.data.value); } } })