| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- // 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);
- }
- }
- })
|