form-ruler.ts 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // components/form-ruler/form-ruler.ts
  2. type Axis = {
  3. value: number;
  4. type?: 'integer' | 'median' | 'tick';
  5. }[]
  6. const prefix = 't-' as const;
  7. const createAxis = (min = 0, max = 10, precision = 0.1) => {
  8. // const length = precision.toString().match(/\d+(?:\.(\d*))/)?.[1]?.length ?? 0
  9. // 计算精度的倒数(即1除以精度),然后乘以10的幂来得到一个整数
  10. const scale = Math.pow(10, Math.ceil(Math.log10(1 / precision)));
  11. const _min = min * scale;
  12. const _max = Math.floor(max * scale);
  13. const _precision = precision * scale;
  14. const ticks: Axis = [];
  15. let current = _min;
  16. while (current < _max + _precision) {
  17. ticks.push({
  18. value: current / scale,
  19. type: Math.floor(current) % 10 ? Math.floor(current) % 5 ? 'tick' : 'median' : 'integer',
  20. });
  21. current += _precision;
  22. }
  23. return ticks;
  24. }
  25. Component({
  26. options: {
  27. multipleSlots: true,
  28. },
  29. properties: {
  30. value: { type: Number, value: Number.NaN },
  31. min: { type: Number, value: 0 },
  32. max: { type: Number, value: 1 },
  33. precision: { type: Number, value: 0.1 },
  34. defaultValue: { type: Number, value: Number.NaN }
  35. },
  36. observers: {
  37. 'min, max, precision'(...args: [number, number, number]) {
  38. this._updateAxis(args);
  39. },
  40. 'defaultValue,min, max'(value, min, max) {
  41. if (!value || Number.isNaN(value)) {
  42. value = Math.floor((max - min) / 2 + min)
  43. // this.setData({ value });
  44. }
  45. this._scrollValue(value);
  46. }
  47. },
  48. lifetimes: {
  49. attached() {
  50. this._updateRect();
  51. },
  52. },
  53. data: {
  54. prefix,
  55. initialValue: '',
  56. axis: [] as Axis,
  57. rect: { width: 0, height: 0, gap: 5 }
  58. },
  59. /**
  60. * 组件的方法列表
  61. */
  62. methods: {
  63. _updateAxis(params: [number, number, number]) {
  64. const axis = createAxis.apply(null, params);
  65. this.setData({ axis })
  66. },
  67. _updateRect() {
  68. this.createSelectorQuery()
  69. .select('.form-ruler')
  70. .boundingClientRect()
  71. .exec(res => {
  72. const rect = res[0] as WechatMiniprogram.BoundingClientRectResult;
  73. const width = rect.width - 2;
  74. const height = rect.height - 2;
  75. this.setData({ 'rect.width': width, 'rect.height': height, });
  76. })
  77. },
  78. _updateValue(index?: number) {
  79. const value = this.data.axis[index ?? 0]?.value
  80. this.setData({ value })
  81. },
  82. _scrollValue(value: number) {
  83. const index = this.data.axis.findIndex(item => item.value === value);
  84. clearTimeout((this as any).lock);
  85. (this as any).lock = setTimeout(() => { this.setData({ initialValue: `${prefix}${index}` }); }, 300);
  86. },
  87. onScrollUpdate(event: WechatMiniprogram.ScrollViewScroll) {
  88. const left = event.detail.scrollLeft;
  89. if (left >= 0) { this._updateValue(Math.floor(left / this.data.rect.gap)); }
  90. },
  91. onScrollEnd() {
  92. this._scrollValue(this.data.value);
  93. }
  94. }
  95. })