Desarrollar componentes de escala basados en uni-app

? ? ? ¿Por qué la imagen cargada es tan ancha? Después de publicar el atributo de ancho en el conjunto de etiquetas img, todavía está llena de pantalla ancha. Por favor, ayuda

I. Introducción

El editor recibió recientemente una tarea, que consiste en no usar más el teclado tradicional al ingresar valores, sino seleccionar valores arrastrando una regla, que se ve así:

De hecho, este requisito no es la primera vez que el producto quiere hacer esto en la primera versión de nuestra aplicación.
Por supuesto, cuando recibí esta tarea por primera vez, me negué. No me pueden dejar hacerlo, así que lo haré de inmediato. Primero, tengo que investigar un poco, porque no quiero pasar tanto tiempo. desarrollando este componente y agregando algunos más.

Después de deslizarse por el borde, el duang puede recuperarse, pero de hecho, no es conveniente ingresar números directamente en el teclado, por lo que el líder definitivamente me regañará; después de investigar un poco y evaluar el tiempo, finalmente elegí otro conjunto de planes. :

Yo mismo escribí un conjunto de teclados numéricos, que es mucho más simple que la escala, y no consume mucho rendimiento.Es bastante conveniente de usar.

¿Por qué no utilizar el propio teclado del sistema? No hace falta decir que todos saben lo repugnante que el navegador móvil llama al teclado del propio sistema.
Sin embargo, la aplicación dio paso a una segunda versión, y el producto volvió a sacar la báscula y amenazó: "¡Si quieres reducir la demanda, córtame primero!".

Sin embargo, es cierto que la segunda versión tiene una escena más compleja, el valor seleccionado debe estar limitado en el rango, y el tamaño del rango seguirá cambiando con algunas condiciones. Si el usuario puede ingresar el valor correcto de manera intuitiva y rápidamente, solo se puede utilizar la báscula.

Después de dos minutos de deliberación, finalmente asumí la tarea.

2. Desarrollo

Primero, echemos un vistazo a las características de la escala.

  1. puede deslizarse;
  2. Emita el valor de acuerdo con la distancia de deslizamiento;
  3. Deslice sobre la cabeza rebotará automáticamente;

Parece que podemos desarrollar en función del componente de vista de desplazamiento proporcionado por uni-app, que proporciona las siguientes propiedades adecuadas para nuestra función de escala:

nombre de la propiedad Tipos de valores predeterminados ilustrar
desplazamiento-x booleano falso Permitir desplazamiento horizontal
desplazarse hacia la izquierda Número/Cadena Establecer la posición de la barra de desplazamiento horizontal
desplazamiento con animación booleano falso Use transiciones animadas al configurar la posición de la barra de desplazamiento
@Desplazarse EventHandle 滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}

然后第二步,需要计算刻度。
小编先设置好了默认每个刻度占10像素;

const GUTTER = 10;
复制代码

然后就开始计算我们一共需要多少个刻度,其实很简单,就是你需要多少刻度,就传进来一个最大最小值,然后用最大值减去最小值,就是刻度的数量了;

这时候会出现一个交互问题,因为刻度尺的选择标是放在屏幕中间的,所以刻度尺的边界是需要显示多余的刻度用来充满屏幕,于是小编就决定生成相当于两倍于屏幕宽度的多余刻度;

// 多余的刻度数量
const extraGridCount = Math.ceil(window.innerWidth / GUTTER);
// 生成刻度数组
this.gridList = Array.from(Array(this.gridMax - this.gridMin + extraGridCount * 2)).map((_, i) => {
      const num = i + this.gridMin - extraGridCount;
      const displayNum = this.decimal === 1 ? num / 10 : num;
      return {
        num,
        displayNum,
        isLongGrid: num % GUTTER === 0,
        showText: num % GUTTER === 0 && num >= this.gridMin && num <= this.gridMax
      }
});
复制代码

刻度数组内每个元素就是一个刻度对象,包含了以下属性:

  1. 刻度数值
  2. 刻度显示的数值(显示的数值可能会与实际数值不一致,是为了扩展小数用的)
  3. 是否是长刻度(因为刻度尺每隔10个就会出现一条长刻度)
  4. 是否显示刻度的数值(只有长刻度和有效刻度才会显示数值)

数组生成好,就可以根据数组来渲染整个刻度尺了;

 <u-row v-if="show" class="grid-wrapper" align="top">
    <view
        class="grid-item"
        :class="{'long': item.isLongGrid}"
        v-for="(item, i) in gridList"
        :key="i"
        :style="item.showText ? { ...gridItemStyle, height: '40px' } : gridItemStyle"
    >
      <text
          class="grid-num"
          v-if="item.showText"
      >{{item.displayNum}}</text>
    </view>
  </u-row>
复制代码

渲染完毕之后,就可以通过一些算法计算刻度尺的初始位置了。然后通过scroll事件,在刻度尺滑动过程中计算数值;

scroll(e){
  const scrollLeft = e.detail.scrollLeft;
  let value = Math.floor((scrollLeft - this.offsetScroll + this.gridMin * GUTTER) / GUTTER);
  if(value < this.gridMin){
    value = this.gridMin;
  }else if(value > this.gridMax){
    value = this.gridMax;
  }}
复制代码

其中offsetScroll 就是多余的那部分刻度,需要减掉的,还要判断一下是否小于最小值或者是否大于最大值; 接下来就是刻度尺的回弹了,当滑动超过最大值或最小值时,需要往回弹,在视觉上与计算好的数值保持一致; 其实也只是在滑动结束时算一下刻度尺是否应该回到边界就好了,动画上scroll-view已经帮我们解决好了;

adjustScrollPosition(){
    /** 滚动结束后调节滚动位置 */
    if(this.actualScrollLeft < this.offsetScroll){
        this.scrollLeft = this.offsetScroll + (Math.random() / 100);
    } else if(this.actualScrollLeft > (this.gridMax - this.gridMin) * GUTTER + this.offsetScroll){
        this.scrollLeft = (this.gridMax - this.gridMin) * GUTTER + 
        this.offsetScroll + (Math.random() / 100);
    } else if(Math.floor(this.actualScrollLeft - this.offsetScroll) % GUTTER !== 0){
        const dryScrollLeft = this.actualScrollLeft - this.offsetScroll;
        this.scrollLeft = dryScrollLeft - dryScrollLeft % GUTTER + this.offsetScroll;
    }
}
复制代码

至此,一个刻度尺组件就大致完成了。当然,还有很多细节问题没解决,比如:

  1. 要是需要支持小数位怎么办呢;
  2. 如果刻度过多是否有性能问题呢;
  3. 等等...

这些问题就由大家思考完善一下吧,嘻嘻!

Supongo que te gusta

Origin juejin.im/post/7079464646222512136
Recomendado
Clasificación